initial commit of lk (little kernel) project
diff --git a/arch/arm/arch.c b/arch/arm/arch.c
new file mode 100644
index 0000000..37b557c
--- /dev/null
+++ b/arch/arm/arch.c
@@ -0,0 +1,72 @@
+/*
+ * Copyright (c) 2008 Travis Geiselbrecht
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files
+ * (the "Software"), to deal in the Software without restriction,
+ * including without limitation the rights to use, copy, modify, merge,
+ * publish, distribute, sublicense, and/or sell copies of the Software,
+ * and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+#include <debug.h>
+#include <arch.h>
+#include <arch/ops.h>
+#include <arch/arm.h>
+#include <arch/arm/mmu.h>
+#include <platform.h>
+
+#if ARM_CPU_CORTEX_A8
+static void set_vector_base(addr_t addr)
+{
+	__asm__ volatile("mcr	p15, 0, %0, c12, c0, 0" :: "r" (addr));
+}
+#endif
+
+void arch_early_init(void)
+{
+	/* turn off the cache */
+	arch_disable_cache(UCACHE);
+
+	/* set the vector base to our exception vectors so we dont need to double map at 0 */
+#if ARM_CPU_CORTEX_A8
+	set_vector_base(MEMBASE);
+#endif
+
+#if ARM_WITH_MMU
+	arm_mmu_init();
+
+	platform_init_mmu_mappings();
+#endif
+
+	/* turn the cache back on */
+	arch_enable_cache(UCACHE);
+
+#if ARM_WITH_NEON
+	/* enable cp10 and cp11 */
+	uint32_t val;
+	__asm__ volatile("mrc	p15, 0, %0, c1, c0, 2" : "=r" (val));
+	val |= (3<<22)|(3<<20);
+	__asm__ volatile("mcr	p15, 0, %0, c1, c0, 2" :: "r" (val));
+
+	/* set enable bit in fpexc */
+	val = (1<<30);
+	__asm__ volatile("mcr  p10, 7, %0, c8, c0, 0" :: "r" (val));
+#endif
+}
+
+void arch_init(void)
+{
+}
+
diff --git a/arch/arm/asm.S b/arch/arm/asm.S
new file mode 100644
index 0000000..2953bd6
--- /dev/null
+++ b/arch/arm/asm.S
@@ -0,0 +1,88 @@
+/*
+ * Copyright (c) 2008 Travis Geiselbrecht
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files
+ * (the "Software"), to deal in the Software without restriction,
+ * including without limitation the rights to use, copy, modify, merge,
+ * publish, distribute, sublicense, and/or sell copies of the Software,
+ * and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+#include <asm.h>
+
+
+	/* context switch frame is as follows:
+	 * ulr
+	 * usp
+	 * lr
+	 * r11
+	 * r10
+	 * r9
+	 * r8
+	 * r7
+	 * r6
+	 * r5
+	 * r4
+	 */
+/* arm_context_switch(addr_t *old_sp, addr_t new_sp) */
+FUNCTION(arm_context_switch)
+	/* save all the usual registers + user regs */
+	/* the spsr is saved and restored in the iframe by exceptions.S */
+	sub		r3, sp, #(11*4)		/* can't use sp in user mode stm */
+	mov		r12, lr
+	stmia	r3, { r4-r11, r12, r13, r14 }^
+	
+	/* save old sp */
+	str		r3, [r0] 
+
+	/* load new regs */
+	ldmia	r1, { r4-r11, r12, r13, r14 }^
+	mov		lr, r12				/* restore lr */
+	add		sp, r1, #(11*4)     /* restore sp */
+	bx		lr
+
+FUNCTION(arm_save_mode_regs)
+	mrs		r1, cpsr
+
+#if ARM_ISA_ARMv6
+	cps		#0x11			/* fiq */
+	str		r13, [r0], #4
+	str		r14, [r0], #4
+	cps		#0x12			/* irq */
+	str		r13, [r0], #4
+	str		r14, [r0], #4
+	cps		#0x13			/* svc */
+	str		r13, [r0], #4
+	str		r14, [r0], #4
+	cps		#0x17			/* abt */
+	str		r13, [r0], #4
+	str		r14, [r0], #4
+	cps		#0x1b			/* und */
+	str		r13, [r0], #4
+	str		r14, [r0], #4
+	cps		#0x1f			/* sys */
+	str		r13, [r0], #4
+	str		r14, [r0], #4
+#else
+	// XXX implement
+	b		.
+#endif
+	
+	msr		cpsr, r1
+
+	bx		lr
+
+	
+
diff --git a/arch/arm/cache-ops.S b/arch/arm/cache-ops.S
new file mode 100644
index 0000000..8a545dc
--- /dev/null
+++ b/arch/arm/cache-ops.S
@@ -0,0 +1,366 @@
+/*
+ * Copyright (c) 2008 Travis Geiselbrecht
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files
+ * (the "Software"), to deal in the Software without restriction,
+ * including without limitation the rights to use, copy, modify, merge,
+ * publish, distribute, sublicense, and/or sell copies of the Software,
+ * and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+#include <asm.h>
+#include <arch/ops.h>
+#include <arch/defines.h>
+
+.text
+
+#if ARM_WITH_CACHE
+
+/* low level cache routines for various cpu families */
+
+#if ARM_CPU_ARM1136 || ARM_CPU_ARM926
+
+/* void arch_disable_cache(uint flags) */
+FUNCTION(arch_disable_cache)
+	mov		r12, #0						// zero register
+	mrs		r3, cpsr					// save the old interrupt state
+#if ARM_ISA_ARMv6
+	.word	0xf10c01c0	/* cpsid iaf */	// interrupts disabled
+#else
+	orr		r3, r3, #(1<<7)
+	msr		cpsr, r3
+#endif
+	
+.Ldcache_disable:
+	tst		r0, #DCACHE
+	beq		.Licache_disable
+	mrc     p15, 0, r1, c1, c0, 0		// cr1
+	tst		r1, #(1<<2)					// is the dcache already disabled?
+	beq		.Licache_disable
+
+	bic		r1, #(1<<2)
+	mcr		p15, 0, r1, c1, c0, 0		// disable dcache
+
+#if ARM_CPU_ARM1136
+    mcr     p15, 0, r12, c7, c14, 0     // clean & invalidate dcache
+#elif ARM_CPU_ARM926
+0:
+	mrc		p15, 0, r15, c7, c14, 3		// clean & invalidate dcache
+	bne		0b
+#else
+#error whut?
+#endif
+	mcr		p15, 0, r0, c7, c10, 4		// data sync barrier (formerly drain write buffer)
+
+.Licache_disable:
+	tst		r0, #ICACHE
+	beq		.Ldone_disable
+
+	mrc     p15, 0, r1, c1, c0, 0		// cr1
+	bic		r1, #(1<<12)
+	mcr		p15, 0, r1, c1, c0, 0		// disable icache
+
+	mcr		p15, 0, r12, c7, c5, 0		// invalidate icache
+
+.Ldone_disable:
+	msr		cpsr, r3
+	bx		lr
+
+/* void arch_enable_cache(uint flags) */
+FUNCTION(arch_enable_cache)
+	mov		r12, #0						// zero register
+	mrs		r3, cpsr					// save the old interrupt state
+#if ARM_ISA_ARMv6
+	.word	0xf10c01c0	/* cpsid iaf */	// interrupts disabled
+#else
+	orr		r3, r3, #(1<<7)
+	msr		cpsr, r3
+#endif
+	
+.Ldcache_enable:
+	tst		r0, #DCACHE
+	beq		.Licache_enable
+	mrc     p15, 0, r1, c1, c0, 0		// cr1
+	tst		r1, #(1<<2)					// is the dcache already enabled?
+	bne		.Licache_enable
+
+    mcr     p15, 0, r12, c7, c6, 0      // invalidate dcache
+
+	orr		r1, #(1<<2)
+	mcr		p15, 0, r1, c1, c0, 0		// enable dcache
+
+.Licache_enable:
+	tst		r0, #ICACHE
+	beq		.Ldone_enable
+
+	mcr		p15, 0, r12, c7, c5, 0		// invalidate icache
+
+	mrc     p15, 0, r1, c1, c0, 0		// cr1
+	orr		r1, #(1<<12)
+	mcr		p15, 0, r1, c1, c0, 0		// enable icache
+
+.Ldone_enable:
+	msr		cpsr, r3
+	bx		lr
+
+#elif ARM_CPU_CORTEX_A8
+
+/* void arch_disable_cache(uint flags) */
+FUNCTION(arch_disable_cache)
+	stmfd	sp!, {r4-r11, lr}
+
+	mov		r7, r0						// save flags
+
+	mrs		r12, cpsr					// save the old interrupt state
+	.word	0xf10c01c0	/* cpsid iaf */	// interrupts disabled
+
+.Ldcache_disable:
+	tst		r7, #DCACHE
+	beq		.Licache_disable
+	mrc     p15, 0, r0, c1, c0, 0		// cr1
+	tst		r0, #(1<<2)					// is the dcache already disabled?
+	beq		.Ldcache_already_disabled
+
+	bic		r0, #(1<<2)
+	mcr		p15, 0, r0, c1, c0, 0		// disable dcache
+
+	// flush and invalidate the dcache
+	// NOTE: trashes a bunch of registers, can't be spilling stuff to the stack
+	bl		flush_invalidate_cache_v7
+
+	b		.Ldcache_disable_L2
+
+.Ldcache_already_disabled:
+	// make sure all of the caches are invalidated
+	// NOTE: trashes a bunch of registers, can't be spilling stuff to the stack
+	bl		invalidate_cache_v7
+
+.Ldcache_disable_L2:
+
+#if ARM_WITH_L2
+	// disable the L2, if present
+	mrc     p15, 0, r0, c1, c0, 1		// aux cr1
+	bic		r0, #(1<<1)
+	mcr		p15, 0, r0, c1, c0, 1		// disable L2 dcache
+#endif
+
+.Licache_disable:
+	tst		r7, #ICACHE
+	beq		.Ldone_disable
+
+	mrc     p15, 0, r0, c1, c0, 0		// cr1
+	bic		r0, #(1<<12)
+	mcr		p15, 0, r0, c1, c0, 0		// disable icache
+
+.Ldone_disable:
+	// make sure the icache is always invalidated
+	mov		r0, #0
+	mcr		p15, 0, r0, c7, c5, 0		// invalidate icache to PoU
+
+	msr		cpsr, r12
+	ldmfd	sp!, {r4-r11, pc}
+
+/* void arch_enable_cache(uint flags) */
+FUNCTION(arch_enable_cache)
+	stmfd	sp!, {r4-r11, lr}
+
+	mov		r7, r0						// save flags
+
+	mrs		r12, cpsr					// save the old interrupt state
+	.word	0xf10c01c0	/* cpsid iaf */	// interrupts disabled
+	
+.Ldcache_enable:
+	tst		r7, #DCACHE
+	beq		.Licache_enable
+	mrc     p15, 0, r0, c1, c0, 0		// cr1
+	tst		r0, #(1<<2)					// is the dcache already enabled?
+	bne		.Licache_enable
+
+	// invalidate L1 and L2
+	// NOTE: trashes a bunch of registers, can't be spilling stuff to the stack
+	bl		invalidate_cache_v7
+
+#if ARM_WITH_L2
+	// enable the L2, if present
+	mrc     p15, 0, r0, c1, c0, 1		// aux cr1
+	orr		r0, #(1<<1)
+	mcr		p15, 0, r0, c1, c0, 1		// enable L2 dcache
+#endif
+
+	mrc     p15, 0, r0, c1, c0, 0		// cr1
+	orr		r0, #(1<<2)
+	mcr		p15, 0, r0, c1, c0, 0		// enable dcache
+
+.Licache_enable:
+	tst		r7, #ICACHE
+	beq		.Ldone_enable
+
+	mov		r0, #0
+	mcr		p15, 0, r0, c7, c5, 0		// invalidate icache to PoU
+
+	mrc     p15, 0, r0, c1, c0, 0		// cr1
+	orr		r0, #(1<<12)
+	mcr		p15, 0, r0, c1, c0, 0		// enable icache
+
+.Ldone_enable:
+	msr		cpsr, r12
+	ldmfd	sp!, {r4-r11, pc}
+
+// flush & invalidate cache routine, trashes r0-r6, r9-r11
+flush_invalidate_cache_v7:
+	/* from ARMv7 manual, B2-17 */
+	MRC 	p15, 1, R0, c0, c0, 1 		// Read CLIDR 
+	ANDS 	R3, R0, #0x7000000 
+	MOV 	R3, R3, LSR #23 			// Cache level value (naturally aligned) 
+	BEQ 	.Lfinished 
+	MOV 	R10, #0 
+.Loop1:
+	ADD 	R2, R10, R10, LSR #1 		// Work out 3xcachelevel 
+	MOV 	R1, R0, LSR R2 				// bottom 3 bits are the Cache type for this level 
+	AND 	R1, R1, #7 					// get those 3 bits alone 
+	CMP 	R1, #2 
+	BLT 	.Lskip 						// no cache or only instruction cache at this level 
+	MCR 	p15, 2, R10, c0, c0, 0 		// write the Cache Size selection register 
+	.word	0xf57ff06f	// ISB 			// ISB to sync the change to the CacheSizeID reg 
+	MRC 	p15, 1, R1, c0, c0, 0 		// reads current Cache Size ID register 
+	AND 	R2, R1, #0x7 				// extract the line length field 
+	ADD 	R2, R2, #4 					// add 4 for the line length offset (log2 16 bytes) 
+	LDR 	R4, =0x3FF 
+	ANDS 	R4, R4, R1, LSR #3 			// R4 is the max number on the way size (right aligned) 
+	CLZ 	R5, R4 						// R5 is the bit position of the way size increment 
+	LDR 	R6, =0x00007FFF 
+	ANDS 	R6, R6, R1, LSR #13 		// R6 is the max number of the index size (right aligned) 
+.Loop2:
+	MOV 	R9, R4 						// R9 working copy of the max way size (right aligned) 
+.Loop3:
+	ORR 	R11, R10, R9, LSL R5 		// factor in the way number and cache number into R11 
+	ORR 	R11, R11, R6, LSL R2 		// factor in the index number 
+	MCR 	p15, 0, R11, c7, c14, 2 	// clean & invalidate by set/way 
+	SUBS 	R9, R9, #1 					// decrement the way number 
+	BGE 	.Loop3 
+	SUBS 	R6, R6, #1 					// decrement the index 
+	BGE 	.Loop2 
+.Lskip:
+ 	ADD 	R10, R10, #2 					// increment the cache number 
+	CMP 	R3, R10 
+	BGT 	.Loop1 
+
+.Lfinished:
+	mov		r10, #0
+	mcr		p15, 2, r10, c0, c0, 0		// select cache level 0
+	.word	0xf57ff06f	// isb
+
+	bx		lr
+
+// invalidate cache routine, trashes r0-r6, r9-r11
+invalidate_cache_v7:
+	/* from ARMv7 manual, B2-17 */
+	MRC 	p15, 1, R0, c0, c0, 1 		// Read CLIDR 
+	ANDS 	R3, R0, #0x7000000 
+	MOV 	R3, R3, LSR #23 			// Cache level value (naturally aligned) 
+	BEQ 	.Lfinished_invalidate
+	MOV 	R10, #0 
+.Loop1_invalidate:
+	ADD 	R2, R10, R10, LSR #1 		// Work out 3xcachelevel 
+	MOV 	R1, R0, LSR R2 				// bottom 3 bits are the Cache type for this level 
+	AND 	R1, R1, #7 					// get those 3 bits alone 
+	CMP 	R1, #2 
+	BLT 	.Lskip_invalidate 			// no cache or only instruction cache at this level 
+	MCR 	p15, 2, R10, c0, c0, 0 		// write the Cache Size selection register 
+	.word	0xf57ff06f	// ISB 			// ISB to sync the change to the CacheSizeID reg 
+	MRC 	p15, 1, R1, c0, c0, 0 		// reads current Cache Size ID register 
+	AND 	R2, R1, #0x7 				// extract the line length field 
+	ADD 	R2, R2, #4 					// add 4 for the line length offset (log2 16 bytes) 
+	LDR 	R4, =0x3FF 
+	ANDS 	R4, R4, R1, LSR #3 			// R4 is the max number on the way size (right aligned) 
+	CLZ 	R5, R4 						// R5 is the bit position of the way size increment 
+	LDR 	R6, =0x00007FFF 
+	ANDS 	R6, R6, R1, LSR #13 		// R6 is the max number of the index size (right aligned) 
+.Loop2_invalidate:
+	MOV 	R9, R4 						// R9 working copy of the max way size (right aligned) 
+.Loop3_invalidate:
+	ORR 	R11, R10, R9, LSL R5 		// factor in the way number and cache number into R11 
+	ORR 	R11, R11, R6, LSL R2 		// factor in the index number 
+	MCR 	p15, 0, R11, c7, c6, 2 		// invalidate by set/way 
+	SUBS 	R9, R9, #1 					// decrement the way number 
+	BGE 	.Loop3_invalidate 
+	SUBS 	R6, R6, #1 					// decrement the index 
+	BGE 	.Loop2_invalidate 
+.Lskip_invalidate:
+ 	ADD 	R10, R10, #2 				// increment the cache number 
+	CMP 	R3, R10 
+	BGT 	.Loop1_invalidate 
+
+.Lfinished_invalidate:
+	mov		r10, #0
+	mcr		p15, 2, r10, c0, c0, 0		// select cache level 0
+	.word	0xf57ff06f	// isb
+
+	bx		lr
+
+#else
+#error unhandled cpu
+#endif
+
+#if ARM_CPU_ARM926 || ARM_CPU_ARM1136 || ARM_CPU_CORTEX_A8
+/* shared cache flush routines */
+
+	/* void arch_flush_cache_range(addr_t start, size_t len); */
+FUNCTION(arch_clean_cache_range)
+0:
+	mcr		p15, 0, r0, c7, c10, 1		// clean cache to PoC by MVA
+	add		r0, r0, #CACHE_LINE
+	subs	r1, r1, #CACHE_LINE
+	bhs		0b
+	
+	mov		r0, #0
+	mcr		p15, 0, r0, c7, c10, 4		// data sync barrier (formerly drain write buffer)
+
+	bx		lr
+
+	/* void arch_flush_invalidate_cache_range(addr_t start, size_t len); */
+FUNCTION(arch_clean_invalidate_cache_range)
+0:
+	mcr		p15, 0, r0, c7, c14, 1		// clean & invalidate cache to PoC by MVA
+	add		r0, r0, #CACHE_LINE
+	subs	r1, r1, #CACHE_LINE
+	bhs		0b
+
+	mov		r0, #0
+	mcr		p15, 0, r0, c7, c10, 4		// data sync barrier (formerly drain write buffer)
+
+	bx		lr
+#else
+#error unhandled cpu
+#endif
+
+#else
+
+/* no cache */
+
+FUNCTION(arch_disable_cache)
+	bx		lr
+
+FUNCTION(arch_enable_cache)
+	bx		lr
+
+FUNCTION(arch_clean_cache_range)
+	bx		lr
+
+FUNCTION(arch_clean_invalidate_cache_range)
+	bx		lr
+
+#endif // ARM_WITH_CACHE
+
diff --git a/arch/arm/cache.c b/arch/arm/cache.c
new file mode 100644
index 0000000..0a403b5
--- /dev/null
+++ b/arch/arm/cache.c
@@ -0,0 +1,22 @@
+/*
+ * Copyright (c) 2008 Travis Geiselbrecht
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files
+ * (the "Software"), to deal in the Software without restriction,
+ * including without limitation the rights to use, copy, modify, merge,
+ * publish, distribute, sublicense, and/or sell copies of the Software,
+ * and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
diff --git a/arch/arm/compile.mk b/arch/arm/compile.mk
new file mode 100644
index 0000000..b509e16
--- /dev/null
+++ b/arch/arm/compile.mk
@@ -0,0 +1,33 @@
+
+$(BUILDDIR)/%.o: %.c $(SRCDEPS)
+	@$(MKDIR)
+	@echo compiling $<
+	$(NOECHO)$(CC) $(CFLAGS) $(THUMBCFLAGS) --std=c99 $(INCLUDES) -c $< -MD -MT $@ -MF $(@:%o=%d) -o $@
+
+$(BUILDDIR)/%.o: %.cpp $(SRCDEPS)
+	@$(MKDIR)
+	@echo compiling $<
+	$(NOECHO)$(CC) $(CFLAGS) $(CPPFLAGS) $(THUMBCFLAGS) $(INCLUDES) -c $< -MD -MT $@ -MF $(@:%o=%d) -o $@
+
+# to override thumb setting, mark the .o file as .Ao
+$(BUILDDIR)/%.Ao: %.c $(SRCDEPS)
+	@$(MKDIR)
+	@echo compiling $<
+	$(NOECHO)$(CC) $(CFLAGS) --std=c99 $(INCLUDES) -c $< -MD -MT $@ -MF $(@:%o=%d) -o $@
+
+$(BUILDDIR)/%.Ao: %.cpp $(SRCDEPS)
+	@$(MKDIR)
+	@echo compiling $<
+	$(NOECHO)$(CC) $(CFLAGS) $(CPPFLAGS) $(INCLUDES) -c $< -MD -MT $@ -MF $(@:%o=%d) -o $@
+
+# assembly is always compiled in ARM mode at the moment
+$(BUILDDIR)/%.Ao: %.S $(SRCDEPS)
+	@$(MKDIR)
+	@echo compiling $<
+	$(NOECHO)$(CC) $(CFLAGS) $(ASMFLAGS) $(INCLUDES) -c $< -MD -MT $@ -MF $(@:%o=%d) -o $@
+
+$(BUILDDIR)/%.o: %.S $(SRCDEPS)
+	@$(MKDIR)
+	@echo compiling $<
+	$(NOECHO)$(CC) $(CFLAGS) $(ASMFLAGS) $(INCLUDES) -c $< -MD -MT $@ -MF $(@:%o=%d) -o $@
+
diff --git a/arch/arm/crt0.S b/arch/arm/crt0.S
new file mode 100644
index 0000000..40cbf27
--- /dev/null
+++ b/arch/arm/crt0.S
@@ -0,0 +1,115 @@
+/*
+ * Copyright (c) 2008 Travis Geiselbrecht
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files
+ * (the "Software"), to deal in the Software without restriction,
+ * including without limitation the rights to use, copy, modify, merge,
+ * publish, distribute, sublicense, and/or sell copies of the Software,
+ * and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+.text
+.globl _start
+_start:
+	b	reset
+	b	arm_undefined
+	b	arm_syscall
+	b	arm_prefetch_abort
+	b	arm_data_abort
+	b	arm_reserved
+	b	arm_irq
+	b	arm_fiq
+
+reset:
+	/* do some cpu setup */
+#if ARM_WITH_CP15
+	mrc		p15, 0, r0, c1, c0, 0
+		/* XXX this is currently for arm926, revist with armv6 cores */
+		/* new thumb behavior, low exception vectors, i/d cache disable, mmu disabled */
+	bic		r0, r0, #(1<<15| 1<<13 | 1<<12)
+	bic		r0, r0, #(1<<2 | 1<<0)
+		/* enable alignment faults */
+	orr		r0, r0, #(1<<1)
+	mcr		p15, 0, r0, c1, c0, 0
+#endif
+
+	/* set up the stack for irq, fiq, abort, undefined, system/user, and lastly supervisor mode */
+	mrs     r0, cpsr
+	bic     r0, r0, #0x1f
+
+	ldr		r2, =abort_stack_top
+	orr     r1, r0, #0x12 // irq
+	msr     cpsr_c, r1
+	ldr		r13, =irq_save_spot		/* save a pointer to a temporary dumping spot used during irq delivery */
+	    
+	orr     r1, r0, #0x11 // fiq
+	msr     cpsr_c, r1
+	mov		sp, r2
+	            
+	orr     r1, r0, #0x17 // abort
+	msr     cpsr_c, r1
+	mov		sp, r2
+	    
+	orr     r1, r0, #0x1b // undefined
+	msr     cpsr_c, r1
+	mov		sp, r2
+	    
+	orr     r1, r0, #0x1f // system
+	msr     cpsr_c, r1
+	mov		sp, r2
+
+	orr		r1, r0, #0x13 // supervisor
+	msr		cpsr_c, r1
+	mov		sp, r2
+
+	/* copy the initialized data segment out of rom if necessary */
+	ldr		r0, =__data_start_rom
+	ldr		r1, =__data_start
+	ldr		r2, =__data_end
+
+	cmp		r0, r1
+	beq		__do_bss
+
+__copy_loop:
+	cmp		r1, r2
+	ldrlt	r3, [r0], #4
+	strlt	r3, [r1], #4
+	blt		__copy_loop
+
+__do_bss:
+	/* clear out the bss */
+	ldr		r0, =__bss_start
+	ldr		r1, =_end
+	mov		r2, #0
+__bss_loop:
+	cmp		r0, r1
+	strlt	r2, [r0], #4
+	blt		__bss_loop
+
+	bl		kmain
+	b		.
+
+.ltorg
+
+.bss
+.align 2
+	/* the abort stack is for unrecoverable errors.
+	 * also note the initial working stack is set to here.
+	 * when the threading system starts up it'll switch to a new 
+	 * dynamically allocated stack, so we don't need it for very long
+	 */
+abort_stack:
+	.skip 1024
+abort_stack_top:
diff --git a/arch/arm/exceptions.S b/arch/arm/exceptions.S
new file mode 100644
index 0000000..fa0ea9e
--- /dev/null
+++ b/arch/arm/exceptions.S
@@ -0,0 +1,132 @@
+/*
+ * Copyright (c) 2008 Travis Geiselbrecht
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files
+ * (the "Software"), to deal in the Software without restriction,
+ * including without limitation the rights to use, copy, modify, merge,
+ * publish, distribute, sublicense, and/or sell copies of the Software,
+ * and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+#include <asm.h>
+
+FUNCTION(arm_undefined)
+	stmfd 	sp!, { r0-r12, r14 }
+	sub		sp, sp, #12
+	mov		r0, sp
+	mrs		r1, spsr
+	stmia	r0, { r1, r13-r14 }^
+	b		arm_undefined_handler
+	b		.
+
+FUNCTION(arm_syscall)
+	stmfd 	sp!, { r0-r12, r14 }
+	sub		sp, sp, #12
+	mov		r0, sp
+	mrs		r1, spsr
+	stmia	r0, { r1, r13-r14 }^
+	b		arm_syscall_handler
+	b		.
+	
+FUNCTION(arm_prefetch_abort)
+	stmfd 	sp!, { r0-r12, r14 }
+	sub		sp, sp, #12
+	mov		r0, sp
+	mrs		r1, spsr
+	stmia	r0, { r1, r13-r14 }^
+	b		arm_prefetch_abort_handler
+	b		.
+
+FUNCTION(arm_data_abort)
+	stmfd 	sp!, { r0-r12, r14 }
+	sub		sp, sp, #12
+	mov		r0, sp
+	mrs		r1, spsr
+	stmia	r0, { r1, r13-r14 }^
+	b		arm_data_abort_handler
+	b		.
+	
+FUNCTION(arm_reserved)
+	b	.
+	
+FUNCTION(arm_irq)
+	/* XXX only deals with interrupting supervisor mode */
+
+	/* save r4-r6 and use as a temporary place to save while we switch into supervisor mode */
+	stmia	r13, { r4-r6 }
+	mov		r4, r13
+	sub		r5, lr, #4
+	mrs		r6, spsr
+
+	/* move into supervisor mode. irq/fiq disabled */
+	msr	cpsr_c, #(3<<6 | 0x13)
+
+	/* save the return address */
+	stmfd	sp!, { r5 }
+
+	/* save C trashed regs, supervisor lr */
+	stmfd	sp!, { r0-r3, r12, lr }
+
+	/* save spsr */
+	stmfd	sp!, { r6 }
+
+	/* restore r4-r6 */
+	ldmia	r4, { r4-r6 }
+
+	/* increment the global critical section count */
+	ldr     r1, =critical_section_count
+	ldr     r0, [r1]
+	add     r0, r0, #1
+	str     r0, [r1]
+	
+	/* call into higher level code */
+	mov	r0, sp /* iframe */
+	bl	platform_irq
+
+	/* reschedule if the handler returns nonzero */
+	cmp     r0, #0
+	blne    thread_preempt
+
+	/* decrement the global critical section count */
+	ldr     r1, =critical_section_count
+	ldr     r0, [r1]
+	sub     r0, r0, #1
+	str     r0, [r1]
+
+	/* restore spsr */
+	ldmfd	sp!, { r0 }
+	msr	spsr, r0
+
+	/* restore back to where we came from */
+	ldmfd	sp!, { r0-r3, r12, lr, pc }^
+
+.bss
+.align 2
+	.global irq_save_spot
+irq_save_spot:
+	.word	0	/* r4 */
+	.word	0	/* r5 */
+	.word	0	/* r6 */
+	
+.text
+FUNCTION(arm_fiq)
+	sub	lr, lr, #4
+	stmfd	sp!, { r0-r3, r12, lr }
+
+	bl	platform_fiq
+	
+	ldmfd	sp!, { r0-r3, r12, pc }^
+
+.ltorg
diff --git a/arch/arm/faults.c b/arch/arm/faults.c
new file mode 100644
index 0000000..c16aff0
--- /dev/null
+++ b/arch/arm/faults.c
@@ -0,0 +1,73 @@
+/*
+ * Copyright (c) 2008 Travis Geiselbrecht
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files
+ * (the "Software"), to deal in the Software without restriction,
+ * including without limitation the rights to use, copy, modify, merge,
+ * publish, distribute, sublicense, and/or sell copies of the Software,
+ * and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+#include <debug.h>
+#include <arch/arm.h>
+#include <kernel/thread.h>
+
+static void dump_fault_frame(struct arm_fault_frame *frame)
+{
+	dprintf("r0  0x%08x r1  0x%08x r2  0x%08x r3  0x%08x\n", frame->r[0], frame->r[1], frame->r[2], frame->r[3]);
+	dprintf("r4  0x%08x r5  0x%08x r6  0x%08x r7  0x%08x\n", frame->r[4], frame->r[5], frame->r[6], frame->r[7]);
+	dprintf("r8  0x%08x r9  0x%08x r10 0x%08x r11 0x%08x\n", frame->r[8], frame->r[9], frame->r[10], frame->r[11]);
+	dprintf("r12 0x%08x usp 0x%08x ulr 0x%08x pc  0x%08x\n", frame->r[12], frame->usp, frame->ulr, frame->pc);
+	dprintf("spsr 0x%08x\n", frame->spsr);
+
+	struct arm_mode_regs regs;
+	arm_save_mode_regs(&regs);
+
+	dprintf("%c%s r13 0x%08x r14 0x%08x\n", ((frame->spsr & MODE_MASK) == MODE_FIQ) ? '*' : ' ', "fiq", regs.fiq_r13, regs.fiq_r14);
+	dprintf("%c%s r13 0x%08x r14 0x%08x\n", ((frame->spsr & MODE_MASK) == MODE_IRQ) ? '*' : ' ', "irq", regs.irq_r13, regs.irq_r14);
+	dprintf("%c%s r13 0x%08x r14 0x%08x\n", ((frame->spsr & MODE_MASK) == MODE_SVC) ? '*' : ' ', "svc", regs.svc_r13, regs.svc_r14);
+	dprintf("%c%s r13 0x%08x r14 0x%08x\n", ((frame->spsr & MODE_MASK) == MODE_UND) ? '*' : ' ', "und", regs.und_r13, regs.und_r14);
+	dprintf("%c%s r13 0x%08x r14 0x%08x\n", ((frame->spsr & MODE_MASK) == MODE_SYS) ? '*' : ' ', "sys", regs.sys_r13, regs.sys_r14);
+}
+
+static void exception_die(struct arm_fault_frame *frame, int pc_off, const char *msg)
+{
+	inc_critical_section();
+	frame->pc += pc_off;
+	dump_fault_frame(frame);
+	dprintf(msg);
+	debug_halt();
+	for(;;);
+}
+
+void arm_syscall_handler(struct arm_fault_frame *frame)
+{
+	exception_die(frame, -4, "unhandled syscall, halting\n");
+}
+
+void arm_undefined_handler(struct arm_fault_frame *frame)
+{
+	exception_die(frame, -4, "undefined abort, halting\n");
+}
+
+void arm_data_abort_handler(struct arm_fault_frame *frame)
+{
+	exception_die(frame, -8, "data abort, halting\n");
+}
+
+void arm_prefetch_abort_handler(struct arm_fault_frame *frame)
+{
+	exception_die(frame, -4, "prefetch abort, halting\n");
+}
diff --git a/arch/arm/include/arch/arch_thread.h b/arch/arm/include/arch/arch_thread.h
new file mode 100644
index 0000000..2f4facf
--- /dev/null
+++ b/arch/arm/include/arch/arch_thread.h
@@ -0,0 +1,31 @@
+/*
+ * Copyright (c) 2008 Travis Geiselbrecht
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files
+ * (the "Software"), to deal in the Software without restriction,
+ * including without limitation the rights to use, copy, modify, merge,
+ * publish, distribute, sublicense, and/or sell copies of the Software,
+ * and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+#ifndef __ARM_ARCH_THREAD_H
+#define __ARM_ARCH_THREAD_H
+
+struct arch_thread {
+	vaddr_t sp;
+};
+
+#endif
+
diff --git a/arch/arm/include/arch/arm.h b/arch/arm/include/arch/arm.h
new file mode 100644
index 0000000..a14bf9c
--- /dev/null
+++ b/arch/arm/include/arch/arm.h
@@ -0,0 +1,94 @@
+/*
+ * Copyright (c) 2008 Travis Geiselbrecht
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files
+ * (the "Software"), to deal in the Software without restriction,
+ * including without limitation the rights to use, copy, modify, merge,
+ * publish, distribute, sublicense, and/or sell copies of the Software,
+ * and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+#ifndef __ARCH_ARM_H
+#define __ARCH_ARM_H
+
+#include <sys/types.h>
+#include <arch/arm/cores.h>
+
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
+void arm_context_switch(vaddr_t *old_sp, vaddr_t new_sp);
+
+static inline uint32_t read_cpsr() {
+	uint32_t cpsr;
+
+	__asm__ volatile("mrs   %0, cpsr" : "=r" (cpsr));
+	return cpsr;
+}
+
+struct arm_iframe {
+	uint32_t spsr;
+	uint32_t r0;
+	uint32_t r1;
+	uint32_t r2;
+	uint32_t r3;
+	uint32_t r12;
+	uint32_t lr;
+	uint32_t pc;
+};
+
+struct arm_fault_frame {
+	uint32_t spsr;
+	uint32_t usp;
+	uint32_t ulr;
+	uint32_t r[13];
+	uint32_t pc;
+};
+
+#define MODE_MASK 0x1f
+#define MODE_USR 0x10
+#define MODE_FIQ 0x11
+#define MODE_IRQ 0x12
+#define MODE_SVC 0x13
+#define MODE_MON 0x16
+#define MODE_ABT 0x17
+#define MODE_UND 0x1b
+#define MODE_SYS 0x1f
+
+struct arm_mode_regs {
+	uint32_t fiq_r13, fiq_r14;
+	uint32_t irq_r13, irq_r14;
+	uint32_t svc_r13, svc_r14;
+	uint32_t abt_r13, abt_r14;
+	uint32_t und_r13, und_r14;
+	uint32_t sys_r13, sys_r14;
+};
+
+void arm_save_mode_regs(struct arm_mode_regs *regs);
+
+uint32_t arm_read_cr1(void);
+void arm_write_cr1(uint32_t val);
+uint32_t arm_read_cr1_aux(void);
+void arm_write_cr1_aux(uint32_t val);
+void arm_write_ttbr(uint32_t val);
+void arm_write_dacr(uint32_t val);
+void arm_invalidate_tlb(void);
+
+#if defined(__cplusplus)
+}
+#endif
+
+#endif
diff --git a/arch/arm/include/arch/arm/cores.h b/arch/arm/include/arch/arm/cores.h
new file mode 100644
index 0000000..e5ddd66
--- /dev/null
+++ b/arch/arm/include/arch/arm/cores.h
@@ -0,0 +1,122 @@
+/*
+ * Copyright (c) 2008 Travis Geiselbrecht
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files
+ * (the "Software"), to deal in the Software without restriction,
+ * including without limitation the rights to use, copy, modify, merge,
+ * publish, distribute, sublicense, and/or sell copies of the Software,
+ * and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+#ifndef __ARM_CORES_H
+#define __ARM_CORES_H
+
+/* 
+ * make the gcc built in define a little easier to deal with 
+ * to decide what core it is generating code for
+ *
+ * ARM_ARCH_LEVEL gets assigned a numeric value of the general family
+ *
+ * ARM_ARCH_* gets defined for each feature recursively
+ */
+
+#if defined(__ARM_ARCH_7M__)
+#define ARM_ARCH_7M 1
+#endif
+#if defined(__ARM_ARCH_7R__)
+#define ARM_ARCH_7R 1
+#endif
+#if defined(__ARM_ARCH_7A__) || defined(ARM_ARCH_7R)
+#define ARM_ARCH_7A 1
+#endif
+#if defined(__ARM_ARCH_7__) || defined(ARM_ARCH_7A) || defined(ARM_ARCH_7M)
+#define ARM_ARCH_7 1
+#ifndef ARM_ARCH_LEVEL
+#define ARM_ARCH_LEVEL 7
+#endif
+#endif
+
+#if defined(__ARM_ARCH_6M__)
+#define ARM_ARCH_6M 1
+#endif
+#if defined(__ARM_ARCH_6T2__) || defined(ARM_ARCH_7)
+#define ARM_ARCH_6T2 1
+#endif
+#if defined(__ARM_ARCH_6ZK__)
+#define ARM_ARCH_6ZK 1
+#endif
+#if defined(__ARM_ARCH_6Z__) || defined(ARM_ARCH_6ZK)
+#define ARM_ARCH_6Z 1
+#endif
+#if defined(__ARM_ARCH_6K__) || defined(ARM_ARCH_6ZK) || defined(ARM_ARCH_7)
+#define ARM_ARCH_6K 1
+#endif
+#if defined(__ARM_ARCH_6J__)
+#define ARM_ARCH_6J 1
+#endif
+#if defined(__ARM_ARCH_6__) || defined(ARM_ARCH_6J) || defined(ARM_ARCH_6K) || defined(ARM_ARCH_6Z) || defined(ARM_ARCH_6T2) || defined(ARM_ARCH_6M)
+#define ARM_ARCH_6 1
+#ifndef ARM_ARCH_LEVEL
+#define ARM_ARCH_LEVEL 6
+#endif
+#endif
+
+#if defined(__ARM_ARCH_5TEJ__)
+#define ARM_ARCH_5TEJ 1
+#endif
+#if defined(__ARM_ARCH_5TE__) || defined(ARM_ARCH_5TEJ) || defined(ARM_ARCH_6)
+#define ARM_ARCH_5TE 1
+#endif
+#if defined(__ARM_ARCH_5E__) || defined(ARM_ARCH_5TE)
+#define ARM_ARCH_5E 1
+#endif
+#if defined(__ARM_ARCH_5T__) || defined(ARM_ARCH_5TE)
+#define ARM_ARCH_5T 1
+#endif
+#if defined(__ARM_ARCH_5__) || defined(ARM_ARCH_5E) || defined(ARM_ARCH_5T)
+#define ARM_ARCH_5 1
+#ifndef ARM_ARCH_LEVEL
+#define ARM_ARCH_LEVEL 5
+#endif
+#endif
+
+#if defined(__ARM_ARCH_4T__) || defined(ARM_ARCH_5T)
+#define ARM_ARCH_4T 1
+#endif
+#if defined(__ARM_ARCH_4__) || defined(ARM_ARCH_4T) || defined(ARM_ARCH_5)
+#define ARM_ARCH_4 1
+#ifndef ARM_ARCH_LEVEL
+#define ARM_ARCH_LEVEL 4
+#endif
+#endif
+
+#if 0
+/* test */
+#if ARM_ARCH_LEVEL >= 7
+#warning ARM_ARCH_LEVEL >= 7
+#endif
+#if ARM_ARCH_LEVEL >= 6
+#warning ARM_ARCH_LEVEL >= 6
+#endif
+#if ARM_ARCH_LEVEL >= 5
+#warning ARM_ARCH_LEVEL >= 5
+#endif
+#if ARM_ARCH_LEVEL >= 4
+#warning ARM_ARCH_LEVEL >= 4
+#endif
+#endif
+
+#endif
+
diff --git a/arch/arm/include/arch/arm/mmu.h b/arch/arm/include/arch/arm/mmu.h
new file mode 100644
index 0000000..719710c
--- /dev/null
+++ b/arch/arm/include/arch/arm/mmu.h
@@ -0,0 +1,44 @@
+/*
+ * Copyright (c) 2008 Travis Geiselbrecht
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files
+ * (the "Software"), to deal in the Software without restriction,
+ * including without limitation the rights to use, copy, modify, merge,
+ * publish, distribute, sublicense, and/or sell copies of the Software,
+ * and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+#ifndef __ARCH_ARM_MMU_H
+#define __ARCH_ARM_MMU_H
+
+#include <sys/types.h>
+
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
+void arm_mmu_init(void);
+
+#define MMU_FLAG_CACHED 0x1
+#define MMU_FLAG_BUFFERED 0x2
+#define MMU_FLAG_READWRITE 0x4
+void arm_mmu_map_section(addr_t paddr, addr_t vaddr, uint flags);
+
+
+#if defined(__cplusplus)
+}
+#endif
+
+#endif
diff --git a/arch/arm/include/arch/arm/ops.h b/arch/arm/include/arch/arm/ops.h
new file mode 100644
index 0000000..6e763c9
--- /dev/null
+++ b/arch/arm/include/arch/arm/ops.h
@@ -0,0 +1,48 @@
+/*
+ * Copyright (c) 2008 Travis Geiselbrecht
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files
+ * (the "Software"), to deal in the Software without restriction,
+ * including without limitation the rights to use, copy, modify, merge,
+ * publish, distribute, sublicense, and/or sell copies of the Software,
+ * and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+#ifndef __ARCH_ARM_OPS_H
+#define __ARHC_ARM_OPS_H
+
+#if 0
+#include <compiler.h>
+
+#ifndef ASSEMBLY
+
+#if ARM_ISA_ARMV7 || ARM_ISA_ARMV6
+// override of some routines
+__GNU_INLINE __ALWAYS_INLINE extern inline void arch_enable_ints(void)
+{
+	__asm__("cpsie i");
+}
+
+__GNU_INLINE __ALWAYS_INLINE extern inline void arch_disable_ints(void)
+{
+	__asm__("cpsid i");
+}
+#endif
+
+#endif
+#endif
+
+#endif
+
diff --git a/arch/arm/include/arch/defines.h b/arch/arm/include/arch/defines.h
new file mode 100644
index 0000000..1d62a68
--- /dev/null
+++ b/arch/arm/include/arch/defines.h
@@ -0,0 +1,43 @@
+/*
+ * Copyright (c) 2008 Travis Geiselbrecht
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files
+ * (the "Software"), to deal in the Software without restriction,
+ * including without limitation the rights to use, copy, modify, merge,
+ * publish, distribute, sublicense, and/or sell copies of the Software,
+ * and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+#ifndef __ARCH_CPU_H
+#define __ARCH_CPU_H
+
+/* arm specific stuff */
+#define PAGE_SIZE 4096
+
+#if ARM_CPU_ARM7
+/* irrelevant, no consistent cache */
+#define CACHE_LINE 32
+#elif ARM_CPU_ARM926
+#define CACHE_LINE 32
+#elif ARM_CPU_ARM1136
+#define CACHE_LINE 32
+#elif ARM_CPU_CORTEX_A8
+#define CACHE_LINE 64
+#else
+#error unknown cpu
+#endif
+
+#endif
+
diff --git a/arch/arm/mmu.c b/arch/arm/mmu.c
new file mode 100644
index 0000000..8109e39
--- /dev/null
+++ b/arch/arm/mmu.c
@@ -0,0 +1,92 @@
+/*
+ * Copyright (c) 2008 Travis Geiselbrecht
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files
+ * (the "Software"), to deal in the Software without restriction,
+ * including without limitation the rights to use, copy, modify, merge,
+ * publish, distribute, sublicense, and/or sell copies of the Software,
+ * and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+#include <debug.h>
+#include <sys/types.h>
+#include <compiler.h>
+#include <arch.h>
+#include <arch/arm.h>
+#include <arch/arm/mmu.h>
+
+#if ARM_WITH_MMU
+
+#define MB (1024*1024)
+
+/* the location of the table may be brought in from outside */
+#if WITH_EXTERNAL_TRANSLATION_TABLE
+#if !defined(MMU_TRANSLATION_TABLE_ADDR)
+#error must set MMU_TRANSLATION_TABLE_ADDR in the make configuration
+#endif
+static uint32_t *tt = (void *)MMU_TRANSLATION_TABLE_ADDR;
+#else
+/* the main translation table */
+static uint32_t tt[4096] __ALIGNED(16384);
+#endif
+
+#define MMU_FLAG_CACHED 0x1
+#define MMU_FLAG_BUFFERED 0x2
+#define MMU_FLAG_READWRITE 0x4
+
+void arm_mmu_map_section(addr_t paddr, addr_t vaddr, uint flags)
+{
+	int index;
+	uint AP;
+	uint CB;
+
+	AP = (flags & MMU_FLAG_READWRITE) ? 0x3 : 0x2;
+	CB = ((flags & MMU_FLAG_CACHED) ? 0x2 : 0) | ((flags & MMU_FLAG_BUFFERED) ? 0x1 : 0);
+
+	index = vaddr / MB;
+	tt[index] = (paddr & ~(MB-1)) | (AP << 10) | (0<<5) | (CB << 2) | (2<<0); // section mapping
+
+	arm_invalidate_tlb();
+}
+
+void arm_mmu_init(void)
+{
+	int i;
+
+	/* set some mmu specific control bits */
+	arm_write_cr1(arm_read_cr1() & ~((1<<29)|(1<<28)|(1<<0))); // access flag disabled, TEX remap disabled, mmu disabled
+
+	/* set up an identity-mapped translation table with cache disabled */
+	for (i=0; i < 4096; i++) {
+		arm_mmu_map_section(i * MB, i * MB,  MMU_FLAG_READWRITE); // map everything uncached
+	}
+
+	/* set up the translation table base */
+	arm_write_ttbr((uint32_t)tt);
+
+	/* set up the domain access register */
+	arm_write_dacr(0x00000001);
+
+	/* turn on the mmu */
+	arm_write_cr1(arm_read_cr1() | 0x1);
+}
+
+void arch_disable_mmu(void)
+{
+	arm_write_cr1(arm_read_cr1() & ~(1<<0)); // access flag disabled, TEX remap disabled, mmu disabled
+}
+
+#endif // ARM_WITH_MMU
+
diff --git a/arch/arm/ops.S b/arch/arm/ops.S
new file mode 100644
index 0000000..c1d612c
--- /dev/null
+++ b/arch/arm/ops.S
@@ -0,0 +1,159 @@
+/*
+ * Copyright (c) 2008 Travis Geiselbrecht
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files
+ * (the "Software"), to deal in the Software without restriction,
+ * including without limitation the rights to use, copy, modify, merge,
+ * publish, distribute, sublicense, and/or sell copies of the Software,
+ * and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+#include <asm.h>
+
+.text
+
+/* void arch_enable_ints(void); */
+FUNCTION(arch_enable_ints)
+	mrs	r0, cpsr
+	bic	r0, r0, #(1<<7)		/* clear the I bit */
+	msr	cpsr_c, r0
+	bx	lr
+
+/* void arch_disable_ints(void); */
+FUNCTION(arch_disable_ints)
+	mrs	r0, cpsr
+	orr	r0, r0, #(1<<7)
+	msr	cpsr_c, r0
+	bx	lr
+
+/* int atomic_swap(int *ptr, int val); */
+FUNCTION(atomic_swap)
+	swp	r0, r2, [r1]
+	bx	lr
+
+/* int atomic_add(int *ptr, int val); */
+FUNCTION(atomic_add)
+	/* disable interrupts, do the add, and reenable */
+	mrs	r2, cpsr
+	mov	r12, r2
+	orr	r2, r2, #(3<<6)
+	msr	cpsr_c, r2
+
+	/* ints disabled, old cpsr state in r12 */
+	
+	/* do the add, leave the previous value in r0 */
+	mov	r3, r0
+	ldr	r0, [r3]
+	add	r2, r0, r1
+	str	r2, [r3]
+
+	/* restore interrupts and exit */
+	msr	cpsr_c, r12
+	bx	lr
+	
+/* int atomic_and(int *ptr, int val); */
+FUNCTION(atomic_and)
+	/* disable interrupts, do the and, and reenable */
+	mrs	r2, cpsr
+	mov	r12, r2
+	orr	r2, r2, #(3<<6)
+	msr	cpsr_c, r2
+
+	/* ints disabled, old cpsr state in r12 */
+	
+	/* do the and, leave the previous value in r0 */
+	mov	r3, r0
+	ldr	r0, [r3]
+	and	r2, r0, r1
+	str	r2, [r3]
+
+	/* restore interrupts and exit */
+	msr	cpsr_c, r12
+	bx	lr
+	
+/* int atomic_or(int *ptr, int val); */
+FUNCTION(atomic_or)
+	/* disable interrupts, do the or, and reenable */
+	mrs	r2, cpsr
+	mov	r12, r2
+	orr	r2, r2, #(3<<6)
+	msr	cpsr_c, r2
+
+	/* ints disabled, old cpsr state in r12 */
+	
+	/* do the or, leave the previous value in r0 */
+	mov	r3, r0
+	ldr	r0, [r3]
+	orr	r2, r0, r1
+	str	r2, [r3]
+
+	/* restore interrupts and exit */
+	msr	cpsr_c, r12
+	bx	lr
+
+/* void arch_idle(); */
+FUNCTION(arch_idle)
+#if ARM_CPU_CORTEX_A8
+	.word 0xe320f003 /* wfi */
+#elif ARM_CPU_ARM1136 || ARM_CPU_ARM926
+	mov	r0, #0
+	mcr	p15, 0, r0, c7, c0, #4
+#elif ARM_CPU_ARM7
+	/* nothing to do here */
+#else
+#error unknown cpu
+#endif
+	bx	lr
+
+/* uint32_t arm_read_cr1(void) */
+FUNCTION(arm_read_cr1)
+	mrc		p15, 0, r0, c1, c0, 0
+	bx		lr
+
+/* void arm_write_cr1(uint32_t val) */
+FUNCTION(arm_write_cr1)
+	mcr		p15, 0, r0, c1, c0, 0
+	bx		lr
+
+/* uint32_t arm_read_cr1_aux(void) */
+FUNCTION(arm_read_cr1_aux)
+	mrc		p15, 0, r0, c1, c0, 1
+	bx		lr
+
+/* void arm_write_cr1_aux(uint32_t val) */
+FUNCTION(arm_write_cr1_aux)
+	mcr		p15, 0, r0, c1, c0, 1
+	bx		lr
+
+/* void arm_write_ttbr(uint32_t val) */
+FUNCTION(arm_write_ttbr)
+	mcr 	p15, 0, r0, c2, c0, 0
+	bx		lr
+
+/* void arm_write_dacr(uint32_t val) */
+FUNCTION(arm_write_dacr)
+	mcr 	p15, 0, r0, c3, c0, 0
+	bx		lr
+
+/* void arm_invalidate_tlb(void) */
+FUNCTION(arm_invalidate_tlb)
+	mov		r0, #0
+	mcr 	p15, 0, r0, c8, c7, 0
+	bx		lr
+
+/* void arch_switch_stacks_and_call(addr_t call, addr_t stack) */
+FUNCTION(arch_switch_stacks_and_call)
+	mov		sp, r1
+	bx		r0	
diff --git a/arch/arm/rules.mk b/arch/arm/rules.mk
new file mode 100644
index 0000000..c8e3d5d
--- /dev/null
+++ b/arch/arm/rules.mk
@@ -0,0 +1,125 @@
+LOCAL_DIR := $(GET_LOCAL_DIR)
+
+TOOLCHAIN_PREFIX ?= arm-elf-
+
+ENABLE_THUMB ?= true
+
+CFLAGS += -finline
+
+DEFINES += \
+	ARM_CPU_$(ARM_CPU)=1
+
+# do set some options based on the cpu core
+HANDLED_CORE := false
+ifeq ($(ARM_CPU),cortex-a8)
+DEFINES += \
+	ARM_WITH_CP15=1 \
+	ARM_WITH_MMU=1 \
+	ARM_ISA_ARMv7=1 \
+	ARM_WITH_VFP=1 \
+	ARM_WITH_NEON=1 \
+	ARM_WITH_THUMB=1 \
+	ARM_WITH_THUMB2=1 \
+	ARM_WITH_CACHE=1 \
+	ARM_WITH_L2=1
+#CFLAGS += -mcpu=$(ARM_CPU)
+CFLAGS += -mcpu=arm1136jf-s # compiler doesn't understand cortex yet
+HANDLED_CORE := true
+#CFLAGS += -mfpu=vfp -mfloat-abi=softfp
+endif
+ifeq ($(ARM_CPU),arm1176jzf-s)
+DEFINES += \
+	ARM_WITH_CP15=1 \
+	ARM_WITH_MMU=1 \
+	ARM_ISA_ARMv6=1 \
+	ARM_WITH_VFP=1 \
+	ARM_WITH_THUMB=1 \
+	ARM_WITH_CACHE=1 \
+	ARM_CPU_ARM1136=1
+CFLAGS += -mcpu=$(ARM_CPU)
+HANDLED_CORE := true
+endif
+ifeq ($(ARM_CPU),arm926ej-s)
+DEFINES += \
+	ARM_WITH_CP15=1 \
+	ARM_WITH_MMU=1 \
+	ARM_ISA_ARMv5E=1 \
+	ARM_WITH_THUMB=1 \
+	ARM_WITH_CACHE=1 \
+	ARM_CPU_ARM9=1 \
+	ARM_CPU_ARM926=1
+CFLAGS += -mcpu=$(ARM_CPU)
+HANDLED_CORE := true
+endif
+ifeq ($(ARM_CPU),arm7tdmi)
+DEFINES += \
+	ARM_ISA_ARMv4=1 \
+	ARM_WITH_THUMB=1 \
+	ARM_CPU_ARM7=1
+CFLAGS += -mcpu=$(ARM_CPU)
+HANDLED_CORE := true
+endif
+
+ifneq ($(HANDLED_CORE),true)
+$(warning $(LOCAL_DIR)/rules.mk doesnt have logic for arm core $(ARM_CPU))
+$(warning this is likely to be broken)
+endif
+
+THUMBCFLAGS :=
+THUMBINTERWORK :=
+ifeq ($(ENABLE_THUMB),true)
+THUMBCFLAGS := -mthumb -D__thumb__
+THUMBINTERWORK := -mthumb-interwork
+endif
+
+CFLAGS += $(THUMBINTERWORK)
+
+INCLUDES += \
+	-I$(LOCAL_DIR)/include
+
+BOOTOBJS += \
+	$(LOCAL_DIR)/crt0.o
+
+OBJS += \
+	$(LOCAL_DIR)/arch.Ao \
+	$(LOCAL_DIR)/asm.o \
+	$(LOCAL_DIR)/cache.o \
+	$(LOCAL_DIR)/cache-ops.o \
+	$(LOCAL_DIR)/ops.o \
+	$(LOCAL_DIR)/exceptions.o \
+	$(LOCAL_DIR)/faults.o \
+	$(LOCAL_DIR)/mmu.o \
+	$(LOCAL_DIR)/thread.o
+
+# make sure some bits were set up
+MEMVARS_SET := 0
+ifneq ($(MEMBASE),)
+MEMVARS_SET := 1
+endif
+ifneq ($(MEMSIZE),)
+MEMVARS_SET := 1
+endif
+ifeq ($(MEMVARS_SET),0)
+$(error missing MEMBASE or MEMSIZE variable, please set in target rules.mk)
+endif
+
+LIBGCC := $(shell $(TOOLCHAIN_PREFIX)gcc $(CFLAGS) $(THUMBCFLAGS) -print-libgcc-file-name)
+#$(info LIBGCC = $(LIBGCC))
+
+# potentially generated files that should be cleaned out with clean make rule
+GENERATED += \
+	$(BUILDDIR)/system-onesegment.ld \
+	$(BUILDDIR)/system-twosegment.ld
+
+# rules for generating the linker scripts
+
+$(BUILDDIR)/system-onesegment.ld: $(LOCAL_DIR)/system-onesegment.ld
+	@echo generating $@
+	@$(MKDIR)
+	$(NOECHO)sed "s/%MEMBASE%/$(MEMBASE)/;s/%MEMSIZE%/$(MEMSIZE)/" < $< > $@
+
+$(BUILDDIR)/system-twosegment.ld: $(LOCAL_DIR)/system-twosegment.ld
+	@echo generating $@
+	@$(MKDIR)
+	$(NOECHO)sed "s/%ROMBASE%/$(ROMBASE)/;s/%MEMBASE%/$(MEMBASE)/;s/%MEMSIZE%/$(MEMSIZE)/" < $< > $@
+
diff --git a/arch/arm/system-onesegment.ld b/arch/arm/system-onesegment.ld
new file mode 100644
index 0000000..fe3a83c
--- /dev/null
+++ b/arch/arm/system-onesegment.ld
@@ -0,0 +1,78 @@
+OUTPUT_FORMAT("elf32-littlearm", "elf32-littlearm", "elf32-littlearm")
+OUTPUT_ARCH(arm)
+
+ENTRY(_start)
+SECTIONS
+{
+	. = %MEMBASE%;
+
+	.interp : { *(.interp) }
+	.hash : { *(.hash) }
+	.dynsym : { *(.dynsym) }
+	.dynstr : { *(.dynstr) }
+	.rel.text : { *(.rel.text) *(.rel.gnu.linkonce.t*) }
+	.rela.text : { *(.rela.text) *(.rela.gnu.linkonce.t*) }
+	.rel.data : { *(.rel.data) *(.rel.gnu.linkonce.d*) }
+	.rela.data : { *(.rela.data) *(.rela.gnu.linkonce.d*) }
+	.rel.rodata : { *(.rel.rodata) *(.rel.gnu.linkonce.r*) }
+	.rela.rodata : { *(.rela.rodata) *(.rela.gnu.linkonce.r*) }
+	.rel.got : { *(.rel.got) }
+	.rela.got : { *(.rela.got) }
+	.rel.ctors : { *(.rel.ctors) }
+	.rela.ctors : { *(.rela.ctors) }
+	.rel.dtors : { *(.rel.dtors) }
+	.rela.dtors : { *(.rela.dtors) }
+	.rel.init : { *(.rel.init) }
+	.rela.init : { *(.rela.init) }
+	.rel.fini : { *(.rel.fini) }
+	.rela.fini : { *(.rela.fini) }
+	.rel.bss : { *(.rel.bss) }
+	.rela.bss : { *(.rela.bss) }
+	.rel.plt : { *(.rel.plt) }
+	.rela.plt : { *(.rela.plt) }
+	.init : { *(.init) } =0x9090
+	.plt : { *(.plt) }
+
+	/* text/read-only data */
+	.text :	{ *(.text .text.* .glue_7* .gnu.linkonce.t.*) } =0x9090
+
+	.rodata : { 
+		*(.rodata .rodata.* .gnu.linkonce.r.*)
+		. = ALIGN(4);
+		__commands_start = .;
+		KEEP (*(.commands))
+		__commands_end = .;
+		. = ALIGN(4); 
+		__rodata_end = . ;		
+	}
+
+	/* writable data  */
+	__data_start_rom = .;	/* in one segment binaries, the rom data address is on top of the ram data address */
+	__data_start = .;
+	.data : { *(.data .data.* .gnu.linkonce.d.*) }
+
+	__ctor_list = .;
+	.ctors : { *(.ctors) }
+	__ctor_end = .;
+	__dtor_list = .;
+	.dtors : { *(.dtors) }
+	__dtor_end = .;
+	.got : { *(.got.plt) *(.got) }
+	.dynamic : { *(.dynamic) }
+
+	__data_end = .;
+
+	/* unintialized data (in same segment as writable data) */
+	. = ALIGN(4);
+	__bss_start = .;
+	.bss : { *(.bss .bss.*) }
+
+	. = ALIGN(4); 
+	_end = .;
+
+	. = %MEMBASE% + %MEMSIZE%;
+	_end_of_ram = .;
+
+	/* Strip unnecessary stuff */
+	/DISCARD/ : { *(.comment .note .eh_frame) }
+}
diff --git a/arch/arm/system-twosegment.ld b/arch/arm/system-twosegment.ld
new file mode 100644
index 0000000..aee3913
--- /dev/null
+++ b/arch/arm/system-twosegment.ld
@@ -0,0 +1,81 @@
+OUTPUT_FORMAT("elf32-littlearm", "elf32-littlearm", "elf32-littlearm")
+OUTPUT_ARCH(arm)
+
+ENTRY(_start)
+SECTIONS
+{
+	. = %ROMBASE%;
+
+	.interp : { *(.interp) }
+	.hash : { *(.hash) }
+	.dynsym : { *(.dynsym) }
+	.dynstr : { *(.dynstr) }
+	.rel.text : { *(.rel.text) *(.rel.gnu.linkonce.t*) }
+	.rela.text : { *(.rela.text) *(.rela.gnu.linkonce.t*) }
+	.rel.data : { *(.rel.data) *(.rel.gnu.linkonce.d*) }
+	.rela.data : { *(.rela.data) *(.rela.gnu.linkonce.d*) }
+	.rel.rodata : { *(.rel.rodata) *(.rel.gnu.linkonce.r*) }
+	.rela.rodata : { *(.rela.rodata) *(.rela.gnu.linkonce.r*) }
+	.rel.got : { *(.rel.got) }
+	.rela.got : { *(.rela.got) }
+	.rel.ctors : { *(.rel.ctors) }
+	.rela.ctors : { *(.rela.ctors) }
+	.rel.dtors : { *(.rel.dtors) }
+	.rela.dtors : { *(.rela.dtors) }
+	.rel.init : { *(.rel.init) }
+	.rela.init : { *(.rela.init) }
+	.rel.fini : { *(.rel.fini) }
+	.rela.fini : { *(.rela.fini) }
+	.rel.bss : { *(.rel.bss) }
+	.rela.bss : { *(.rela.bss) }
+	.rel.plt : { *(.rel.plt) }
+	.rela.plt : { *(.rela.plt) }
+	.init : { *(.init) } =0x9090
+	.plt : { *(.plt) }
+
+	/* text/read-only data */
+	.text :	{ *(.text .text.* .glue_7* .gnu.linkonce.t.*) } =0x9090
+
+	.rodata : { 
+		*(.rodata .rodata.* .gnu.linkonce.r.*) 
+		. = ALIGN(4); 
+		__commands_start = .;
+		KEEP (*(.commands))
+		__commands_end = .;
+		. = ALIGN(4); 
+		__rodata_end = . ;
+	}
+
+	/* writable data  */
+	__data_start_rom = .;
+	. = %MEMBASE%;
+	__data_start = .;
+	.data : 
+		AT ( ADDR (.rodata) + SIZEOF (.rodata) )
+		{ *(.data .data.* .gnu.linkonce.d.*) }
+
+	__ctor_list = .;
+	.ctors : { *(.ctors) }
+	__ctor_end = .;
+	__dtor_list = .;
+	.dtors : { *(.dtors) }
+	__dtor_end = .;
+	.got : { *(.got.plt) *(.got) }
+	.dynamic : { *(.dynamic) }
+
+	__data_end = .;
+	
+	/* unintialized data (in same segment as writable data) */
+	. = ALIGN(4);
+	__bss_start = .;
+	.bss : { *(.bss .bss.*) }
+
+	. = ALIGN(4); 
+	_end = . ;
+
+	. = %MEMBASE% + %MEMSIZE%;
+	_end_of_ram = . ;
+
+	/* Strip unnecessary stuff */
+	/DISCARD/ : { *(.comment .note .eh_frame) }
+}
diff --git a/arch/arm/thread.c b/arch/arm/thread.c
new file mode 100644
index 0000000..a3b9a95
--- /dev/null
+++ b/arch/arm/thread.c
@@ -0,0 +1,88 @@
+/*
+ * Copyright (c) 2008 Travis Geiselbrecht
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files
+ * (the "Software"), to deal in the Software without restriction,
+ * including without limitation the rights to use, copy, modify, merge,
+ * publish, distribute, sublicense, and/or sell copies of the Software,
+ * and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+#include <sys/types.h>
+#include <string.h>
+#include <stdlib.h>
+#include <debug.h>
+#include <kernel/thread.h>
+#include <arch/arm.h>
+
+struct context_switch_frame {
+	vaddr_t r4;
+	vaddr_t r5;
+	vaddr_t r6;
+	vaddr_t r7;
+	vaddr_t r8;
+	vaddr_t r9;
+	vaddr_t r10;
+	vaddr_t r11;
+	vaddr_t lr;
+	vaddr_t usp;
+	vaddr_t ulr;
+};
+
+extern void arm_context_switch(addr_t *old_sp, addr_t new_sp);
+
+static void initial_thread_func(void) __NO_RETURN;
+static void initial_thread_func(void)
+{
+	int ret;
+
+//	dprintf("initial_thread_func: thread %p calling %p with arg %p\n", current_thread, current_thread->entry, current_thread->arg);
+//	dump_thread(current_thread);
+
+	/* exit the implicit critical section we're within */
+	exit_critical_section();
+
+	ret = current_thread->entry(current_thread->arg);
+
+	dprintf("initial_thread_func: thread %p exiting with %d\n", current_thread, ret);
+
+	thread_exit(ret);
+}
+
+void arch_thread_initialize(thread_t *t)
+{
+	// create a default stack frame on the stack
+	vaddr_t stack_top = (vaddr_t)t->stack + t->stack_size;
+
+	// make sure the top of the stack is 8 byte aligned for EABI compliance
+	stack_top = ROUNDDOWN(stack_top, 8);
+
+	struct context_switch_frame *frame = (struct context_switch_frame *)(stack_top);
+	frame--;
+
+	// fill it in
+	memset(frame, 0, sizeof(*frame));
+	frame->lr = (vaddr_t)&initial_thread_func;
+	
+	// set the stack pointer
+	t->arch.sp = (vaddr_t)frame;
+}
+
+void arch_context_switch(thread_t *oldthread, thread_t *newthread)
+{
+//	dprintf("arch_context_switch: old %p (%s), new %p (%s)\n", oldthread, oldthread->name, newthread, newthread->name);
+	arm_context_switch(&oldthread->arch.sp, newthread->arch.sp);
+}
+