ARMv8 Trusted Firmware release v0.2
diff --git a/lib/arch/aarch64/cache_helpers.S b/lib/arch/aarch64/cache_helpers.S
new file mode 100644
index 0000000..b8a5608
--- /dev/null
+++ b/lib/arch/aarch64/cache_helpers.S
@@ -0,0 +1,233 @@
+/*
+ * Copyright (c) 2013, ARM Limited. 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.
+ *
+ * Neither the name of ARM nor the names of its contributors may be used
+ * to endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "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 COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <arch_helpers.h>
+#include <asm_macros.S>
+
+	.globl	dcisw
+	.globl	dccisw
+	.globl	dccsw
+	.globl	dccvac
+	.globl	dcivac
+	.globl	dccivac
+	.globl	dccvau
+	.globl	dczva
+	.globl	flush_dcache_range
+	.globl	inv_dcache_range
+	.globl	dcsw_op_louis
+	.globl	dcsw_op_all
+
+	.section	.text, "ax"; .align 3
+
+dcisw:; .type dcisw, %function
+	dc	isw, x0
+	dsb	sy
+	isb
+	ret
+
+
+dccisw:; .type dccisw, %function
+	dc	cisw, x0
+	dsb	sy
+	isb
+	ret
+
+
+dccsw:; .type dccsw, %function
+	dc	csw, x0
+	dsb	sy
+	isb
+	ret
+
+
+dccvac:; .type dccvac, %function
+	dc	cvac, x0
+	dsb	sy
+	isb
+	ret
+
+
+dcivac:; .type dcivac, %function
+	dc	ivac, x0
+	dsb	sy
+	isb
+	ret
+
+
+dccivac:; .type dccivac, %function
+	dc	civac, x0
+	dsb	sy
+	isb
+	ret
+
+
+dccvau:; .type dccvau, %function
+	dc	cvau, x0
+	dsb	sy
+	isb
+	ret
+
+
+dczva:; .type dczva, %function
+	dc	zva, x0
+	dsb	sy
+	isb
+	ret
+
+
+	/* ------------------------------------------
+	 * Clean+Invalidate from base address till
+	 * size. 'x0' = addr, 'x1' = size
+	 * ------------------------------------------
+	 */
+flush_dcache_range:; .type flush_dcache_range, %function
+	dcache_line_size x2, x3
+	add	x1, x0, x1
+	sub	x3, x2, #1
+	bic	x0, x0, x3
+flush_loop:
+	dc	civac, x0
+	add	x0, x0, x2
+	cmp	x0, x1
+	b.lo    flush_loop
+	dsb	sy
+	ret
+
+
+	/* ------------------------------------------
+	 * Invalidate from base address till
+	 * size. 'x0' = addr, 'x1' = size
+	 * ------------------------------------------
+	 */
+inv_dcache_range:; .type inv_dcache_range, %function
+	dcache_line_size x2, x3
+	add	x1, x0, x1
+	sub	x3, x2, #1
+	bic	x0, x0, x3
+inv_loop:
+	dc	ivac, x0
+	add	x0, x0, x2
+	cmp	x0, x1
+	b.lo    inv_loop
+	dsb	sy
+	ret
+
+
+	/* ------------------------------------------
+	 * Data cache operations by set/way to the
+	 * level specified
+	 * ------------------------------------------
+	 * ----------------------------------
+	 * Call this func with the clidr in
+	 * x0, starting cache level in x10,
+	 * last cache level in x3 & cm op in
+	 * x14
+	 * ----------------------------------
+	 */
+dcsw_op:; .type dcsw_op, %function
+all_start_at_level:
+	add	x2, x10, x10, lsr #1            // work out 3x current cache level
+	lsr	x1, x0, x2                      // extract cache type bits from clidr
+	and	x1, x1, #7                      // mask of the bits for current cache only
+	cmp	x1, #2                          // see what cache we have at this level
+	b.lt	skip                            // skip if no cache, or just i-cache
+	msr	csselr_el1, x10                 // select current cache level in csselr
+	isb                                     // isb to sych the new cssr&csidr
+	mrs	x1, ccsidr_el1                  // read the new ccsidr
+	and	x2, x1, #7                      // extract the length of the cache lines
+	add	x2, x2, #4                      // add 4 (line length offset)
+	mov	x4, #0x3ff
+	and	x4, x4, x1, lsr #3              // find maximum number on the way size
+	clz	w5, w4                          // find bit position of way size increment
+	mov	x7, #0x7fff
+	and	x7, x7, x1, lsr #13             // extract max number of the index size
+loop2:
+	mov	x9, x4                          // create working copy of max way size
+loop3:
+	lsl	x6, x9, x5
+	orr	x11, x10, x6                    // factor way and cache number into x11
+	lsl	x6, x7, x2
+	orr	x11, x11, x6                    // factor index number into x11
+	mov	x12, x0
+	mov	x13, x30 // lr
+	mov	x0, x11
+	blr	x14
+	mov	x0, x12
+	mov	x30, x13 // lr
+	subs	x9, x9, #1                      // decrement the way
+	b.ge    loop3
+	subs	x7, x7, #1                      // decrement the index
+	b.ge    loop2
+skip:
+	add	x10, x10, #2                    // increment cache number
+	cmp	x3, x10
+	b.gt    all_start_at_level
+finished:
+	mov	x10, #0                         // swith back to cache level 0
+	msr	csselr_el1, x10                 // select current cache level in csselr
+	dsb	sy
+	isb
+	ret
+
+
+do_dcsw_op:; .type do_dcsw_op, %function
+	cbz	x3, exit
+	cmp	x0, #DCISW
+	b.eq	dc_isw
+	cmp	x0, #DCCISW
+	b.eq	dc_cisw
+	cmp	x0, #DCCSW
+	b.eq	dc_csw
+dc_isw:
+	mov	x0, x9
+	adr	x14, dcisw
+	b	dcsw_op
+dc_cisw:
+	mov	x0, x9
+	adr	x14, dccisw
+	b	dcsw_op
+dc_csw:
+	mov	x0, x9
+	adr	x14, dccsw
+	b	dcsw_op
+exit:
+	ret
+
+
+dcsw_op_louis:; .type dcsw_op_louis, %function
+	dsb	sy
+	setup_dcsw_op_args x10, x3, x9, #LOUIS_SHIFT, #CLIDR_FIELD_WIDTH, #LEVEL_SHIFT
+	b	do_dcsw_op
+
+
+dcsw_op_all:; .type dcsw_op_all, %function
+	dsb	sy
+	setup_dcsw_op_args x10, x3, x9, #LOC_SHIFT, #CLIDR_FIELD_WIDTH, #LEVEL_SHIFT
+	b	do_dcsw_op
diff --git a/lib/arch/aarch64/misc_helpers.S b/lib/arch/aarch64/misc_helpers.S
new file mode 100644
index 0000000..8c1f740
--- /dev/null
+++ b/lib/arch/aarch64/misc_helpers.S
@@ -0,0 +1,274 @@
+/*
+ * Copyright (c) 2013, ARM Limited. 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.
+ *
+ * Neither the name of ARM nor the names of its contributors may be used
+ * to endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "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 COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <arch_helpers.h>
+
+	.globl	enable_irq
+	.globl	disable_irq
+
+	.globl	enable_fiq
+	.globl	disable_fiq
+
+	.globl	enable_serror
+	.globl	disable_serror
+
+	.globl	read_daif
+	.globl	write_daif
+
+	.globl	read_spsr
+	.globl	read_spsr_el1
+	.globl	read_spsr_el2
+	.globl	read_spsr_el3
+
+	.globl	write_spsr
+	.globl	write_spsr_el1
+	.globl	write_spsr_el2
+	.globl	write_spsr_el3
+
+	.globl	read_elr
+	.globl	read_elr_el1
+	.globl	read_elr_el2
+	.globl	read_elr_el3
+
+	.globl	write_elr
+	.globl	write_elr_el1
+	.globl	write_elr_el2
+	.globl	write_elr_el3
+
+	.globl	get_afflvl_shift
+	.globl	mpidr_mask_lower_afflvls
+	.globl	dsb
+	.globl	isb
+	.globl	sev
+	.globl	wfe
+	.globl	wfi
+	.globl	eret
+	.globl	smc
+
+
+	.section	.text, "ax"
+
+get_afflvl_shift:; .type get_afflvl_shift, %function
+	cmp	x0, #3
+	cinc	x0, x0, eq
+	mov	x1, #MPIDR_AFFLVL_SHIFT
+	lsl	x0, x0, x1
+	ret
+
+mpidr_mask_lower_afflvls:; .type mpidr_mask_lower_afflvls, %function
+	cmp	x1, #3
+	cinc	x1, x1, eq
+	mov	x2, #MPIDR_AFFLVL_SHIFT
+	lsl	x2, x1, x2
+	lsr	x0, x0, x2
+	lsl	x0, x0, x2
+	ret
+
+	/* -----------------------------------------------------
+	 * Asynchronous exception manipulation accessors
+	 * -----------------------------------------------------
+	 */
+enable_irq:; .type enable_irq, %function
+	msr	daifclr, #DAIF_IRQ_BIT
+	ret
+
+
+enable_fiq:; .type enable_fiq, %function
+	msr	daifclr, #DAIF_FIQ_BIT
+	ret
+
+
+enable_serror:; .type enable_serror, %function
+	msr	daifclr, #DAIF_ABT_BIT
+	ret
+
+
+disable_irq:; .type disable_irq, %function
+	msr	daifset, #DAIF_IRQ_BIT
+	ret
+
+
+disable_fiq:; .type disable_fiq, %function
+	msr	daifset, #DAIF_FIQ_BIT
+	ret
+
+
+disable_serror:; .type disable_serror, %function
+	msr	daifset, #DAIF_ABT_BIT
+	ret
+
+
+read_daif:; .type read_daif, %function
+	mrs	x0, daif
+	ret
+
+
+write_daif:; .type write_daif, %function
+	msr	daif, x0
+	ret
+
+
+read_spsr:; .type read_spsr, %function
+	mrs	x0, CurrentEl
+	cmp	x0, #(MODE_EL1 << MODE_EL_SHIFT)
+	b.eq	read_spsr_el1
+	cmp	x0, #(MODE_EL2 << MODE_EL_SHIFT)
+	b.eq	read_spsr_el2
+	cmp	x0, #(MODE_EL3 << MODE_EL_SHIFT)
+	b.eq	read_spsr_el3
+
+
+read_spsr_el1:; .type read_spsr_el1, %function
+	mrs	x0, spsr_el1
+	ret
+
+
+read_spsr_el2:; .type read_spsr_el2, %function
+	mrs	x0, spsr_el2
+	ret
+
+
+read_spsr_el3:; .type read_spsr_el3, %function
+	mrs	x0, spsr_el3
+	ret
+
+
+write_spsr:; .type write_spsr, %function
+	mrs	x1, CurrentEl
+	cmp	x1, #(MODE_EL1 << MODE_EL_SHIFT)
+	b.eq	write_spsr_el1
+	cmp	x1, #(MODE_EL2 << MODE_EL_SHIFT)
+	b.eq	write_spsr_el2
+	cmp	x1, #(MODE_EL3 << MODE_EL_SHIFT)
+	b.eq	write_spsr_el3
+
+
+write_spsr_el1:; .type write_spsr_el1, %function
+	msr	spsr_el1, x0
+	isb
+	ret
+
+
+write_spsr_el2:; .type write_spsr_el2, %function
+	msr	spsr_el2, x0
+	isb
+	ret
+
+
+write_spsr_el3:; .type write_spsr_el3, %function
+	msr	spsr_el3, x0
+	isb
+	ret
+
+
+read_elr:; .type read_elr, %function
+	mrs	x0, CurrentEl
+	cmp	x0, #(MODE_EL1 << MODE_EL_SHIFT)
+	b.eq	read_elr_el1
+	cmp	x0, #(MODE_EL2 << MODE_EL_SHIFT)
+	b.eq	read_elr_el2
+	cmp	x0, #(MODE_EL3 << MODE_EL_SHIFT)
+	b.eq	read_elr_el3
+
+
+read_elr_el1:; .type read_elr_el1, %function
+	mrs	x0, elr_el1
+	ret
+
+
+read_elr_el2:; .type read_elr_el2, %function
+	mrs	x0, elr_el2
+	ret
+
+
+read_elr_el3:; .type read_elr_el3, %function
+	mrs	x0, elr_el3
+	ret
+
+
+write_elr:; .type write_elr, %function
+	mrs	x1, CurrentEl
+	cmp	x1, #(MODE_EL1 << MODE_EL_SHIFT)
+	b.eq	write_elr_el1
+	cmp	x1, #(MODE_EL2 << MODE_EL_SHIFT)
+	b.eq	write_elr_el2
+	cmp	x1, #(MODE_EL3 << MODE_EL_SHIFT)
+	b.eq	write_elr_el3
+
+
+write_elr_el1:; .type write_elr_el1, %function
+	msr	elr_el1, x0
+	isb
+	ret
+
+
+write_elr_el2:; .type write_elr_el2, %function
+	msr	elr_el2, x0
+	isb
+	ret
+
+
+write_elr_el3:; .type write_elr_el3, %function
+	msr	elr_el3, x0
+	isb
+	ret
+
+
+dsb:; .type dsb, %function
+	dsb	sy
+	ret
+
+
+isb:; .type isb, %function
+	isb
+	ret
+
+
+sev:; .type sev, %function
+	sev
+	ret
+
+
+wfe:; .type wfe, %function
+	wfe
+	ret
+
+
+wfi:; .type wfi, %function
+	wfi
+	ret
+
+
+eret:; .type eret, %function
+	eret
+
+
+smc:; .type smc, %function
+	smc	#0
diff --git a/lib/arch/aarch64/sysreg_helpers.S b/lib/arch/aarch64/sysreg_helpers.S
new file mode 100644
index 0000000..e68192f
--- /dev/null
+++ b/lib/arch/aarch64/sysreg_helpers.S
@@ -0,0 +1,1154 @@
+/*
+ * Copyright (c) 2013, ARM Limited. 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.
+ *
+ * Neither the name of ARM nor the names of its contributors may be used
+ * to endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "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 COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <arch_helpers.h>
+
+	.globl	read_vbar
+	.globl	read_vbar_el1
+	.globl	read_vbar_el2
+	.globl	read_vbar_el3
+	.globl	write_vbar
+	.globl	write_vbar_el1
+	.globl	write_vbar_el2
+	.globl	write_vbar_el3
+
+	.globl	read_sctlr
+	.globl	read_sctlr_el1
+	.globl	read_sctlr_el2
+	.globl	read_sctlr_el3
+	.globl	write_sctlr
+	.globl	write_sctlr_el1
+	.globl	write_sctlr_el2
+	.globl	write_sctlr_el3
+
+	.globl	read_actlr
+	.globl	read_actlr_el1
+	.globl	read_actlr_el2
+	.globl	read_actlr_el3
+	.globl	write_actlr
+	.globl	write_actlr_el1
+	.globl	write_actlr_el2
+	.globl	write_actlr_el3
+
+	.globl	read_esr
+	.globl	read_esr_el1
+	.globl	read_esr_el2
+	.globl	read_esr_el3
+	.globl	write_esr
+	.globl	write_esr_el1
+	.globl	write_esr_el2
+	.globl	write_esr_el3
+
+	.globl	read_afsr0
+	.globl	read_afsr0_el1
+	.globl	read_afsr0_el2
+	.globl	read_afsr0_el3
+	.globl	write_afsr0
+	.globl	write_afsr0_el1
+	.globl	write_afsr0_el2
+	.globl	write_afsr0_el3
+
+	.globl	read_afsr1
+	.globl	read_afsr1_el1
+	.globl	read_afsr1_el2
+	.globl	read_afsr1_el3
+	.globl	write_afsr1
+	.globl	write_afsr1_el1
+	.globl	write_afsr1_el2
+	.globl	write_afsr1_el3
+
+	.globl	read_far
+	.globl	read_far_el1
+	.globl	read_far_el2
+	.globl	read_far_el3
+	.globl	write_far
+	.globl	write_far_el1
+	.globl	write_far_el2
+	.globl	write_far_el3
+
+	.globl	read_mair
+	.globl	read_mair_el1
+	.globl	read_mair_el2
+	.globl	read_mair_el3
+	.globl	write_mair
+	.globl	write_mair_el1
+	.globl	write_mair_el2
+	.globl	write_mair_el3
+
+	.globl	read_amair
+	.globl	read_amair_el1
+	.globl	read_amair_el2
+	.globl	read_amair_el3
+	.globl	write_amair
+	.globl	write_amair_el1
+	.globl	write_amair_el2
+	.globl	write_amair_el3
+
+	.globl	read_rvbar
+	.globl	read_rvbar_el1
+	.globl	read_rvbar_el2
+	.globl	read_rvbar_el3
+
+	.globl	read_rmr
+	.globl	read_rmr_el1
+	.globl	read_rmr_el2
+	.globl	read_rmr_el3
+	.globl	write_rmr
+	.globl	write_rmr_el1
+	.globl	write_rmr_el2
+	.globl	write_rmr_el3
+
+	.globl	read_tcr
+	.globl	read_tcr_el1
+	.globl	read_tcr_el2
+	.globl	read_tcr_el3
+	.globl	write_tcr
+	.globl	write_tcr_el1
+	.globl	write_tcr_el2
+	.globl	write_tcr_el3
+
+	.globl	read_cptr
+	.globl	read_cptr_el2
+	.globl	read_cptr_el3
+	.globl	write_cptr
+	.globl	write_cptr_el2
+	.globl	write_cptr_el3
+
+	.globl	read_ttbr0
+	.globl	read_ttbr0_el1
+	.globl	read_ttbr0_el2
+	.globl	read_ttbr0_el3
+	.globl	write_ttbr0
+	.globl	write_ttbr0_el1
+	.globl	write_ttbr0_el2
+	.globl	write_ttbr0_el3
+
+	.globl	read_ttbr1
+	.globl	read_ttbr1_el1
+	.globl	read_ttbr1_el2
+	.globl	write_ttbr1
+	.globl	write_ttbr1_el1
+	.globl	write_ttbr1_el2
+
+	.globl	read_cpacr
+	.globl	write_cpacr
+
+	.globl	read_cntfrq
+	.globl	write_cntfrq
+
+	.globl	read_cpuectlr
+	.globl	write_cpuectlr
+
+	.globl	read_cnthctl_el2
+	.globl	write_cnthctl_el2
+
+	.globl	read_cntfrq_el0
+	.globl	write_cntfrq_el0
+
+	.globl	read_scr
+	.globl	write_scr
+
+	.globl	read_hcr
+	.globl	write_hcr
+
+	.globl	read_midr
+	.globl	read_mpidr
+
+	.globl	read_current_el
+	.globl	read_id_pfr1_el1
+	.globl	read_id_aa64pfr0_el1
+
+#if SUPPORT_VFP
+	.globl	enable_vfp
+	.globl	read_fpexc
+	.globl	write_fpexc
+#endif
+
+
+	.section	.text, "ax"
+
+read_current_el:; .type read_current_el, %function
+	mrs	x0, CurrentEl
+	ret
+
+
+read_id_pfr1_el1:; .type read_id_pfr1_el1, %function
+	mrs	x0, id_pfr1_el1
+	ret
+
+
+read_id_aa64pfr0_el1:; .type read_id_aa64pfr0_el1, %function
+	mrs	x0, id_aa64pfr0_el1
+	ret
+
+
+	/* -----------------------------------------------------
+	 * VBAR accessors
+	 * -----------------------------------------------------
+	 */
+read_vbar:; .type read_vbar, %function
+	mrs	x0, CurrentEl
+	cmp	x0, #(MODE_EL1 << MODE_EL_SHIFT)
+	b.eq	read_vbar_el1
+	cmp	x0, #(MODE_EL2 << MODE_EL_SHIFT)
+	b.eq	read_vbar_el2
+	cmp	x0, #(MODE_EL3 << MODE_EL_SHIFT)
+	b.eq	read_vbar_el3
+
+
+read_vbar_el1:; .type read_vbar_el1, %function
+	mrs	x0, vbar_el1
+	ret
+
+
+read_vbar_el2:; .type read_vbar_el2, %function
+	mrs	x0, vbar_el2
+	ret
+
+
+read_vbar_el3:; .type read_vbar_el3, %function
+	mrs	x0, vbar_el3
+	ret
+
+
+write_vbar:; .type write_vbar, %function
+	mrs	x1, CurrentEl
+	cmp	x1, #(MODE_EL1 << MODE_EL_SHIFT)
+	b.eq	write_vbar_el1
+	cmp	x1, #(MODE_EL2 << MODE_EL_SHIFT)
+	b.eq	write_vbar_el2
+	cmp	x1, #(MODE_EL3 << MODE_EL_SHIFT)
+	b.eq	write_vbar_el3
+
+
+write_vbar_el1:; .type write_vbar_el1, %function
+	msr	vbar_el1, x0
+	isb
+	ret
+
+
+write_vbar_el2:; .type write_vbar_el2, %function
+	msr	vbar_el2, x0
+	isb
+	ret
+
+
+write_vbar_el3:; .type write_vbar_el3, %function
+	msr	vbar_el3, x0
+	isb
+	ret
+
+
+	/* -----------------------------------------------------
+	 * AFSR0 accessors
+	 * -----------------------------------------------------
+	 */
+read_afsr0:; .type read_afsr0, %function
+	mrs	x0, CurrentEl
+	cmp	x0, #(MODE_EL1 << MODE_EL_SHIFT)
+	b.eq	read_afsr0_el1
+	cmp	x0, #(MODE_EL2 << MODE_EL_SHIFT)
+	b.eq	read_afsr0_el2
+	cmp	x0, #(MODE_EL3 << MODE_EL_SHIFT)
+	b.eq	read_afsr0_el3
+
+
+read_afsr0_el1:; .type read_afsr0_el1, %function
+	mrs	x0, afsr0_el1
+	ret
+
+
+read_afsr0_el2:; .type read_afsr0_el2, %function
+	mrs	x0, afsr0_el2
+	ret
+
+
+read_afsr0_el3:; .type read_afsr0_el3, %function
+	mrs	x0, afsr0_el3
+	ret
+
+
+write_afsr0:; .type write_afsr0, %function
+	mrs	x1, CurrentEl
+	cmp	x1, #(MODE_EL1 << MODE_EL_SHIFT)
+	b.eq	write_afsr0_el1
+	cmp	x1, #(MODE_EL2 << MODE_EL_SHIFT)
+	b.eq	write_afsr0_el2
+	cmp	x1, #(MODE_EL3 << MODE_EL_SHIFT)
+	b.eq	write_afsr0_el3
+
+
+write_afsr0_el1:; .type write_afsr0_el1, %function
+	msr	afsr0_el1, x0
+	isb
+	ret
+
+
+write_afsr0_el2:; .type write_afsr0_el2, %function
+	msr	afsr0_el2, x0
+	isb
+	ret
+
+
+write_afsr0_el3:; .type write_afsr0_el3, %function
+	msr	afsr0_el3, x0
+	isb
+	ret
+
+
+	/* -----------------------------------------------------
+	 * FAR accessors
+	 * -----------------------------------------------------
+	 */
+read_far:; .type read_far, %function
+	mrs	x0, CurrentEl
+	cmp	x0, #(MODE_EL1 << MODE_EL_SHIFT)
+	b.eq	read_far_el1
+	cmp	x0, #(MODE_EL2 << MODE_EL_SHIFT)
+	b.eq	read_far_el2
+	cmp	x0, #(MODE_EL3 << MODE_EL_SHIFT)
+	b.eq	read_far_el3
+
+
+read_far_el1:; .type read_far_el1, %function
+	mrs	x0, far_el1
+	ret
+
+
+read_far_el2:; .type read_far_el2, %function
+	mrs	x0, far_el2
+	ret
+
+
+read_far_el3:; .type read_far_el3, %function
+	mrs	x0, far_el3
+	ret
+
+
+write_far:; .type write_far, %function
+	mrs	x1, CurrentEl
+	cmp	x1, #(MODE_EL1 << MODE_EL_SHIFT)
+	b.eq	write_far_el1
+	cmp	x1, #(MODE_EL2 << MODE_EL_SHIFT)
+	b.eq	write_far_el2
+	cmp	x1, #(MODE_EL3 << MODE_EL_SHIFT)
+	b.eq	write_far_el3
+
+
+write_far_el1:; .type write_far_el1, %function
+	msr	far_el1, x0
+	isb
+	ret
+
+
+write_far_el2:; .type write_far_el2, %function
+	msr	far_el2, x0
+	isb
+	ret
+
+
+write_far_el3:; .type write_far_el3, %function
+	msr	far_el3, x0
+	isb
+	ret
+
+
+	/* -----------------------------------------------------
+	 * MAIR accessors
+	 * -----------------------------------------------------
+	 */
+read_mair:; .type read_mair, %function
+	mrs	x0, CurrentEl
+	cmp	x0, #(MODE_EL1 << MODE_EL_SHIFT)
+	b.eq	read_mair_el1
+	cmp	x0, #(MODE_EL2 << MODE_EL_SHIFT)
+	b.eq	read_mair_el2
+	cmp	x0, #(MODE_EL3 << MODE_EL_SHIFT)
+	b.eq	read_mair_el3
+
+
+read_mair_el1:; .type read_mair_el1, %function
+	mrs	x0, mair_el1
+	ret
+
+
+read_mair_el2:; .type read_mair_el2, %function
+	mrs	x0, mair_el2
+	ret
+
+
+read_mair_el3:; .type read_mair_el3, %function
+	mrs	x0, mair_el3
+	ret
+
+
+write_mair:; .type write_mair, %function
+	mrs	x1, CurrentEl
+	cmp	x1, #(MODE_EL1 << MODE_EL_SHIFT)
+	b.eq	write_mair_el1
+	cmp	x1, #(MODE_EL2 << MODE_EL_SHIFT)
+	b.eq	write_mair_el2
+	cmp	x1, #(MODE_EL3 << MODE_EL_SHIFT)
+	b.eq	write_mair_el3
+
+
+write_mair_el1:; .type write_mair_el1, %function
+	msr	mair_el1, x0
+	isb
+	ret
+
+
+write_mair_el2:; .type write_mair_el2, %function
+	msr	mair_el2, x0
+	isb
+	ret
+
+
+write_mair_el3:; .type write_mair_el3, %function
+	msr	mair_el3, x0
+	isb
+	ret
+
+
+	/* -----------------------------------------------------
+	 * AMAIR accessors
+	 * -----------------------------------------------------
+	 */
+read_amair:; .type read_amair, %function
+	mrs	x0, CurrentEl
+	cmp	x0, #(MODE_EL1 << MODE_EL_SHIFT)
+	b.eq	read_amair_el1
+	cmp	x0, #(MODE_EL2 << MODE_EL_SHIFT)
+	b.eq	read_amair_el2
+	cmp	x0, #(MODE_EL3 << MODE_EL_SHIFT)
+	b.eq	read_amair_el3
+
+
+read_amair_el1:; .type read_amair_el1, %function
+	mrs	x0, amair_el1
+	ret
+
+
+read_amair_el2:; .type read_amair_el2, %function
+	mrs	x0, amair_el2
+	ret
+
+
+read_amair_el3:; .type read_amair_el3, %function
+	mrs	x0, amair_el3
+	ret
+
+
+write_amair:; .type write_amair, %function
+	mrs	x1, CurrentEl
+	cmp	x1, #(MODE_EL1 << MODE_EL_SHIFT)
+	b.eq	write_amair_el1
+	cmp	x1, #(MODE_EL2 << MODE_EL_SHIFT)
+	b.eq	write_amair_el2
+	cmp	x1, #(MODE_EL3 << MODE_EL_SHIFT)
+	b.eq	write_amair_el3
+
+
+write_amair_el1:; .type write_amair_el1, %function
+	msr	amair_el1, x0
+	isb
+	ret
+
+
+write_amair_el2:; .type write_amair_el2, %function
+	msr	amair_el2, x0
+	isb
+	ret
+
+
+write_amair_el3:; .type write_amair_el3, %function
+	msr	amair_el3, x0
+	isb
+	ret
+
+
+	/* -----------------------------------------------------
+	 * RVBAR accessors
+	 * -----------------------------------------------------
+	 */
+read_rvbar:; .type read_rvbar, %function
+	mrs	x0, CurrentEl
+	cmp	x0, #(MODE_EL1 << MODE_EL_SHIFT)
+	b.eq	read_rvbar_el1
+	cmp	x0, #(MODE_EL2 << MODE_EL_SHIFT)
+	b.eq	read_rvbar_el2
+	cmp	x0, #(MODE_EL3 << MODE_EL_SHIFT)
+	b.eq	read_rvbar_el3
+
+
+read_rvbar_el1:; .type read_rvbar_el1, %function
+	mrs	x0, rvbar_el1
+	ret
+
+
+read_rvbar_el2:; .type read_rvbar_el2, %function
+	mrs	x0, rvbar_el2
+	ret
+
+
+read_rvbar_el3:; .type read_rvbar_el3, %function
+	mrs	x0, rvbar_el3
+	ret
+
+
+	/* -----------------------------------------------------
+	 * RMR accessors
+	 * -----------------------------------------------------
+	 */
+read_rmr:; .type read_rmr, %function
+	mrs	x0, CurrentEl
+	cmp	x0, #(MODE_EL1 << MODE_EL_SHIFT)
+	b.eq	read_rmr_el1
+	cmp	x0, #(MODE_EL2 << MODE_EL_SHIFT)
+	b.eq	read_rmr_el2
+	cmp	x0, #(MODE_EL3 << MODE_EL_SHIFT)
+	b.eq	read_rmr_el3
+
+
+read_rmr_el1:; .type read_rmr_el1, %function
+	mrs	x0, rmr_el1
+	ret
+
+
+read_rmr_el2:; .type read_rmr_el2, %function
+	mrs	x0, rmr_el2
+	ret
+
+
+read_rmr_el3:; .type read_rmr_el3, %function
+	mrs	x0, rmr_el3
+	ret
+
+
+write_rmr:; .type write_rmr, %function
+	mrs	x1, CurrentEl
+	cmp	x1, #(MODE_EL1 << MODE_EL_SHIFT)
+	b.eq	write_rmr_el1
+	cmp	x1, #(MODE_EL2 << MODE_EL_SHIFT)
+	b.eq	write_rmr_el2
+	cmp	x1, #(MODE_EL3 << MODE_EL_SHIFT)
+	b.eq	write_rmr_el3
+
+
+write_rmr_el1:; .type write_rmr_el1, %function
+	msr	rmr_el1, x0
+	isb
+	ret
+
+
+write_rmr_el2:; .type write_rmr_el2, %function
+	msr	rmr_el2, x0
+	isb
+	ret
+
+
+write_rmr_el3:; .type write_rmr_el3, %function
+	msr	rmr_el3, x0
+	isb
+	ret
+
+
+read_afsr1:; .type read_afsr1, %function
+	mrs	x0, CurrentEl
+	cmp	x0, #(MODE_EL1 << MODE_EL_SHIFT)
+	b.eq	read_afsr1_el1
+	cmp	x0, #(MODE_EL2 << MODE_EL_SHIFT)
+	b.eq	read_afsr1_el2
+	cmp	x0, #(MODE_EL3 << MODE_EL_SHIFT)
+	b.eq	read_afsr1_el3
+
+
+	/* -----------------------------------------------------
+	 * AFSR1 accessors
+	 * -----------------------------------------------------
+	 */
+read_afsr1_el1:; .type read_afsr1_el1, %function
+	mrs	x0, afsr1_el1
+	ret
+
+
+read_afsr1_el2:; .type read_afsr1_el2, %function
+	mrs	x0, afsr1_el2
+	ret
+
+
+read_afsr1_el3:; .type read_afsr1_el3, %function
+	mrs	x0, afsr1_el3
+	ret
+
+
+write_afsr1:; .type write_afsr1, %function
+	mrs	x1, CurrentEl
+	cmp	x1, #(MODE_EL1 << MODE_EL_SHIFT)
+	b.eq	write_afsr1_el1
+	cmp	x1, #(MODE_EL2 << MODE_EL_SHIFT)
+	b.eq	write_afsr1_el2
+	cmp	x1, #(MODE_EL3 << MODE_EL_SHIFT)
+	b.eq	write_afsr1_el3
+
+
+write_afsr1_el1:; .type write_afsr1_el1, %function
+	msr	afsr1_el1, x0
+	isb
+	ret
+
+
+write_afsr1_el2:; .type write_afsr1_el2, %function
+	msr	afsr1_el2, x0
+	isb
+	ret
+
+
+write_afsr1_el3:; .type write_afsr1_el3, %function
+	msr	afsr1_el3, x0
+	isb
+	ret
+
+
+	/* -----------------------------------------------------
+	 * SCTLR accessors
+	 * -----------------------------------------------------
+	 */
+read_sctlr:; .type read_sctlr, %function
+	mrs	x0, CurrentEl
+	cmp	x0, #(MODE_EL1 << MODE_EL_SHIFT)
+	b.eq	read_sctlr_el1
+	cmp	x0, #(MODE_EL2 << MODE_EL_SHIFT)
+	b.eq	read_sctlr_el2
+	cmp	x0, #(MODE_EL3 << MODE_EL_SHIFT)
+	b.eq	read_sctlr_el3
+
+
+read_sctlr_el1:; .type read_sctlr_el1, %function
+	mrs	x0, sctlr_el1
+	ret
+
+
+read_sctlr_el2:; .type read_sctlr_el2, %function
+	mrs	x0, sctlr_el2
+	ret
+
+
+read_sctlr_el3:; .type read_sctlr_el3, %function
+	mrs	x0, sctlr_el3
+	ret
+
+
+write_sctlr:; .type write_sctlr, %function
+	mrs	x1, CurrentEl
+	cmp	x1, #(MODE_EL1 << MODE_EL_SHIFT)
+	b.eq	write_sctlr_el1
+	cmp	x1, #(MODE_EL2 << MODE_EL_SHIFT)
+	b.eq	write_sctlr_el2
+	cmp	x1, #(MODE_EL3 << MODE_EL_SHIFT)
+	b.eq	write_sctlr_el3
+
+
+write_sctlr_el1:; .type write_sctlr_el1, %function
+	msr	sctlr_el1, x0
+	dsb	sy
+	isb
+	ret
+
+
+write_sctlr_el2:; .type write_sctlr_el2, %function
+	msr	sctlr_el2, x0
+	dsb	sy
+	isb
+	ret
+
+
+write_sctlr_el3:; .type write_sctlr_el3, %function
+	msr	sctlr_el3, x0
+	dsb	sy
+	isb
+	ret
+
+
+	/* -----------------------------------------------------
+	 * ACTLR accessors
+	 * -----------------------------------------------------
+	 */
+read_actlr:; .type read_actlr, %function
+	mrs	x0, CurrentEl
+	cmp	x0, #(MODE_EL1 << MODE_EL_SHIFT)
+	b.eq	read_actlr_el1
+	cmp	x0, #(MODE_EL2 << MODE_EL_SHIFT)
+	b.eq	read_actlr_el2
+	cmp	x0, #(MODE_EL3 << MODE_EL_SHIFT)
+	b.eq	read_actlr_el3
+
+
+read_actlr_el1:; .type read_actlr_el1, %function
+	mrs	x0, actlr_el1
+	ret
+
+
+read_actlr_el2:; .type read_actlr_el2, %function
+	mrs	x0, actlr_el2
+	ret
+
+
+read_actlr_el3:; .type read_actlr_el3, %function
+	mrs	x0, actlr_el3
+	ret
+
+
+write_actlr:; .type write_actlr, %function
+	mrs	x1, CurrentEl
+	cmp	x1, #(MODE_EL1 << MODE_EL_SHIFT)
+	b.eq	write_actlr_el1
+	cmp	x1, #(MODE_EL2 << MODE_EL_SHIFT)
+	b.eq	write_actlr_el2
+	cmp	x1, #(MODE_EL3 << MODE_EL_SHIFT)
+	b.eq	write_actlr_el3
+
+
+write_actlr_el1:; .type write_actlr_el1, %function
+	msr	actlr_el1, x0
+	dsb	sy
+	isb
+	ret
+
+
+write_actlr_el2:; .type write_actlr_el2, %function
+	msr	actlr_el2, x0
+	dsb	sy
+	isb
+	ret
+
+
+write_actlr_el3:; .type write_actlr_el3, %function
+	msr	actlr_el3, x0
+	dsb	sy
+	isb
+	ret
+
+
+	/* -----------------------------------------------------
+	 * ESR accessors
+	 * -----------------------------------------------------
+	 */
+read_esr:; .type read_esr, %function
+	mrs	x0, CurrentEl
+	cmp	x0, #(MODE_EL1 << MODE_EL_SHIFT)
+	b.eq	read_esr_el1
+	cmp	x0, #(MODE_EL2 << MODE_EL_SHIFT)
+	b.eq	read_esr_el2
+	cmp	x0, #(MODE_EL3 << MODE_EL_SHIFT)
+	b.eq	read_esr_el3
+
+
+read_esr_el1:; .type read_esr_el1, %function
+	mrs	x0, esr_el1
+	ret
+
+
+read_esr_el2:; .type read_esr_el2, %function
+	mrs	x0, esr_el2
+	ret
+
+
+read_esr_el3:; .type read_esr_el3, %function
+	mrs	x0, esr_el3
+	ret
+
+
+write_esr:; .type write_esr, %function
+	mrs	x1, CurrentEl
+	cmp	x1, #(MODE_EL1 << MODE_EL_SHIFT)
+	b.eq	write_esr_el1
+	cmp	x1, #(MODE_EL2 << MODE_EL_SHIFT)
+	b.eq	write_esr_el2
+	cmp	x1, #(MODE_EL3 << MODE_EL_SHIFT)
+	b.eq	write_esr_el3
+
+
+write_esr_el1:; .type write_esr_el1, %function
+	msr	esr_el1, x0
+	dsb	sy
+	isb
+	ret
+
+
+write_esr_el2:; .type write_esr_el2, %function
+	msr	esr_el2, x0
+	dsb	sy
+	isb
+	ret
+
+
+write_esr_el3:; .type write_esr_el3, %function
+	msr	esr_el3, x0
+	dsb	sy
+	isb
+	ret
+
+
+	/* -----------------------------------------------------
+	 * TCR accessors
+	 * -----------------------------------------------------
+	 */
+read_tcr:; .type read_tcr, %function
+	mrs	x0, CurrentEl
+	cmp	x0, #(MODE_EL1 << MODE_EL_SHIFT)
+	b.eq	read_tcr_el1
+	cmp	x0, #(MODE_EL2 << MODE_EL_SHIFT)
+	b.eq	read_tcr_el2
+	cmp	x0, #(MODE_EL3 << MODE_EL_SHIFT)
+	b.eq	read_tcr_el3
+
+
+read_tcr_el1:; .type read_tcr_el1, %function
+	mrs	x0, tcr_el1
+	ret
+
+
+read_tcr_el2:; .type read_tcr_el2, %function
+	mrs	x0, tcr_el2
+	ret
+
+
+read_tcr_el3:; .type read_tcr_el3, %function
+	mrs	x0, tcr_el3
+	ret
+
+
+write_tcr:; .type write_tcr, %function
+	mrs	x1, CurrentEl
+	cmp	x1, #(MODE_EL1 << MODE_EL_SHIFT)
+	b.eq	write_tcr_el1
+	cmp	x1, #(MODE_EL2 << MODE_EL_SHIFT)
+	b.eq	write_tcr_el2
+	cmp	x1, #(MODE_EL3 << MODE_EL_SHIFT)
+	b.eq	write_tcr_el3
+
+
+write_tcr_el1:; .type write_tcr_el1, %function
+	msr	tcr_el1, x0
+	dsb	sy
+	isb
+	ret
+
+
+write_tcr_el2:; .type write_tcr_el2, %function
+	msr	tcr_el2, x0
+	dsb	sy
+	isb
+	ret
+
+
+write_tcr_el3:; .type write_tcr_el3, %function
+	msr	tcr_el3, x0
+	dsb	sy
+	isb
+	ret
+
+
+	/* -----------------------------------------------------
+	 * CPTR accessors
+	 * -----------------------------------------------------
+	 */
+read_cptr:; .type read_cptr, %function
+	mrs	x0, CurrentEl
+	cmp	x0, #(MODE_EL1 << MODE_EL_SHIFT)
+	b.eq	read_cptr_el1
+	cmp	x0, #(MODE_EL2 << MODE_EL_SHIFT)
+	b.eq	read_cptr_el2
+	cmp	x0, #(MODE_EL3 << MODE_EL_SHIFT)
+	b.eq	read_cptr_el3
+
+
+read_cptr_el1:; .type read_cptr_el1, %function
+	b	read_cptr_el1
+	ret
+
+
+read_cptr_el2:; .type read_cptr_el2, %function
+	mrs	x0, cptr_el2
+	ret
+
+
+read_cptr_el3:; .type read_cptr_el3, %function
+	mrs	x0, cptr_el3
+	ret
+
+
+write_cptr:; .type write_cptr, %function
+	mrs	x1, CurrentEl
+	cmp	x1, #(MODE_EL1 << MODE_EL_SHIFT)
+	b.eq	write_cptr_el1
+	cmp	x1, #(MODE_EL2 << MODE_EL_SHIFT)
+	b.eq	write_cptr_el2
+	cmp	x1, #(MODE_EL3 << MODE_EL_SHIFT)
+	b.eq	write_cptr_el3
+
+
+write_cptr_el1:; .type write_cptr_el1, %function
+	b	write_cptr_el1
+
+
+write_cptr_el2:; .type write_cptr_el2, %function
+	msr	cptr_el2, x0
+	dsb	sy
+	isb
+	ret
+
+
+write_cptr_el3:; .type write_cptr_el3, %function
+	msr	cptr_el3, x0
+	dsb	sy
+	isb
+	ret
+
+
+	/* -----------------------------------------------------
+	 * TTBR0 accessors
+	 * -----------------------------------------------------
+	 */
+read_ttbr0:; .type read_ttbr0, %function
+	mrs	x0, CurrentEl
+	cmp	x0, #(MODE_EL1 << MODE_EL_SHIFT)
+	b.eq	read_ttbr0_el1
+	cmp	x0, #(MODE_EL2 << MODE_EL_SHIFT)
+	b.eq	read_ttbr0_el2
+	cmp	x0, #(MODE_EL3 << MODE_EL_SHIFT)
+	b.eq	read_ttbr0_el3
+
+
+read_ttbr0_el1:; .type read_ttbr0_el1, %function
+	mrs	x0, ttbr0_el1
+	ret
+
+
+read_ttbr0_el2:; .type read_ttbr0_el2, %function
+	mrs	x0, ttbr0_el2
+	ret
+
+
+read_ttbr0_el3:; .type read_ttbr0_el3, %function
+	mrs	x0, ttbr0_el3
+	ret
+
+
+write_ttbr0:; .type write_ttbr0, %function
+	mrs	x1, CurrentEl
+	cmp	x1, #(MODE_EL1 << MODE_EL_SHIFT)
+	b.eq	write_ttbr0_el1
+	cmp	x1, #(MODE_EL2 << MODE_EL_SHIFT)
+	b.eq	write_ttbr0_el2
+	cmp	x1, #(MODE_EL3 << MODE_EL_SHIFT)
+	b.eq	write_ttbr0_el3
+
+
+write_ttbr0_el1:; .type write_ttbr0_el1, %function
+	msr	ttbr0_el1, x0
+	isb
+	ret
+
+
+write_ttbr0_el2:; .type write_ttbr0_el2, %function
+	msr	ttbr0_el2, x0
+	isb
+	ret
+
+
+write_ttbr0_el3:; .type write_ttbr0_el3, %function
+	msr	ttbr0_el3, x0
+	isb
+	ret
+
+
+	/* -----------------------------------------------------
+	 * TTBR1 accessors
+	 * -----------------------------------------------------
+	 */
+read_ttbr1:; .type read_ttbr1, %function
+	mrs	x0, CurrentEl
+	cmp	x0, #(MODE_EL1 << MODE_EL_SHIFT)
+	b.eq	read_ttbr1_el1
+	cmp	x0, #(MODE_EL2 << MODE_EL_SHIFT)
+	b.eq	read_ttbr1_el2
+	cmp	x0, #(MODE_EL3 << MODE_EL_SHIFT)
+	b.eq	read_ttbr1_el3
+
+
+read_ttbr1_el1:; .type read_ttbr1_el1, %function
+	mrs	x0, ttbr1_el1
+	ret
+
+
+read_ttbr1_el2:; .type read_ttbr1_el2, %function
+	b	read_ttbr1_el2
+
+
+read_ttbr1_el3:; .type read_ttbr1_el3, %function
+	b	read_ttbr1_el3
+
+
+write_ttbr1:; .type write_ttbr1, %function
+	mrs	x1, CurrentEl
+	cmp	x1, #(MODE_EL1 << MODE_EL_SHIFT)
+	b.eq	write_ttbr1_el1
+	cmp	x1, #(MODE_EL2 << MODE_EL_SHIFT)
+	b.eq	write_ttbr1_el2
+	cmp	x1, #(MODE_EL3 << MODE_EL_SHIFT)
+	b.eq	write_ttbr1_el3
+
+
+write_ttbr1_el1:; .type write_ttbr1_el1, %function
+	msr	ttbr1_el1, x0
+	isb
+	ret
+
+
+write_ttbr1_el2:; .type write_ttbr1_el2, %function
+	b	write_ttbr1_el2
+
+
+write_ttbr1_el3:; .type write_ttbr1_el3, %function
+	b	write_ttbr1_el3
+
+
+read_hcr:; .type read_hcr, %function
+	mrs	x0, hcr_el2
+	ret
+
+
+write_hcr:; .type write_hcr, %function
+	msr	hcr_el2, x0
+	dsb	sy
+	isb
+	ret
+
+
+read_cpacr:; .type read_cpacr, %function
+	mrs	x0, cpacr_el1
+	ret
+
+
+write_cpacr:; .type write_cpacr, %function
+	msr	cpacr_el1, x0
+	ret
+
+
+read_cntfrq_el0:; .type read_cntfrq_el0, %function
+	mrs	x0, cntfrq_el0
+	ret
+
+
+write_cntfrq_el0:; .type write_cntfrq_el0, %function
+	msr	cntfrq_el0, x0
+	ret
+
+
+read_cpuectlr:; .type read_cpuectlr, %function
+	mrs	x0, CPUECTLR_EL1
+	ret
+
+
+write_cpuectlr:; .type write_cpuectlr, %function
+	msr	CPUECTLR_EL1, x0
+	dsb	sy
+	isb
+	ret
+
+
+read_cnthctl_el2:; .type read_cnthctl_el2, %function
+	mrs	x0, cnthctl_el2
+	ret
+
+
+write_cnthctl_el2:; .type write_cnthctl_el2, %function
+	msr	cnthctl_el2, x0
+	ret
+
+
+read_cntfrq:; .type read_cntfrq, %function
+	mrs	x0, cntfrq_el0
+	ret
+
+
+write_cntfrq:; .type write_cntfrq, %function
+	msr	cntfrq_el0, x0
+	ret
+
+
+write_scr:; .type write_scr, %function
+	msr	scr_el3, x0
+	dsb	sy
+	isb
+	ret
+
+
+read_scr:; .type read_scr, %function
+	mrs	x0, scr_el3
+	ret
+
+
+read_midr:; .type read_midr, %function
+	mrs	x0, midr_el1
+	ret
+
+
+read_mpidr:; .type read_mpidr, %function
+	mrs	x0, mpidr_el1
+	ret
+
+
+#if SUPPORT_VFP
+enable_vfp:; .type enable_vfp, %function
+	mrs	x0, cpacr_el1
+	orr	x0, x0, #CPACR_VFP_BITS
+	msr	cpacr_el1, x0
+	mrs	x0, cptr_el3
+	mov	x1, #AARCH64_CPTR_TFP
+	bic	x0, x0, x1
+	msr	cptr_el3, x0
+	ret
+
+
+	// int read_fpexc(void)
+read_fpexc:; .type read_fpexc, %function
+	b	read_fpexc
+	ret
+
+
+	// void write_fpexc(int fpexc)
+write_fpexc:; .type write_fpexc, %function
+	b	write_fpexc
+	ret
+
+#endif
diff --git a/lib/arch/aarch64/tlb_helpers.S b/lib/arch/aarch64/tlb_helpers.S
new file mode 100644
index 0000000..8377f2c
--- /dev/null
+++ b/lib/arch/aarch64/tlb_helpers.S
@@ -0,0 +1,111 @@
+/*
+ * Copyright (c) 2013, ARM Limited. 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.
+ *
+ * Neither the name of ARM nor the names of its contributors may be used
+ * to endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "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 COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <arch_helpers.h>
+
+	.globl	tlbiall
+	.globl	tlbiallis
+	.globl	tlbialle1
+	.globl	tlbialle1is
+	.globl	tlbialle2
+	.globl	tlbialle2is
+	.globl	tlbialle3
+	.globl	tlbialle3is
+	.globl	tlbivmalle1
+
+
+	.section	.text, "ax"
+
+tlbiall:; .type tlbiall, %function
+	mrs	x0, CurrentEl
+	cmp	x0, #(MODE_EL1 << MODE_EL_SHIFT)
+	b.eq	tlbialle1
+	cmp	x0, #(MODE_EL2 << MODE_EL_SHIFT)
+	b.eq	tlbialle2
+	cmp	x0, #(MODE_EL3 << MODE_EL_SHIFT)
+	b.eq	tlbialle3
+
+
+tlbiallis:; .type tlbiallis, %function
+	mrs	x0, CurrentEl
+	cmp	x0, #(MODE_EL1 << MODE_EL_SHIFT)
+	b.eq	tlbialle1is
+	cmp	x0, #(MODE_EL2 << MODE_EL_SHIFT)
+	b.eq	tlbialle2is
+	cmp	x0, #(MODE_EL3 << MODE_EL_SHIFT)
+	b.eq	tlbialle3is
+
+
+tlbialle1:; .type tlbialle1, %function
+	tlbi	alle1
+	dsb	sy
+	isb
+	ret
+
+
+tlbialle1is:; .type tlbialle1is, %function
+	tlbi	alle1is
+	dsb	sy
+	isb
+	ret
+
+
+tlbialle2:; .type tlbialle2, %function
+	tlbi	alle2
+	dsb	sy
+	isb
+	ret
+
+
+tlbialle2is:; .type tlbialle2is, %function
+	tlbi	alle2is
+	dsb	sy
+	isb
+	ret
+
+
+tlbialle3:; .type tlbialle3, %function
+	tlbi	alle3
+	dsb	sy
+	isb
+	ret
+
+
+tlbialle3is:; .type tlbialle3is, %function
+	tlbi	alle3is
+	dsb	sy
+	isb
+	ret
+
+tlbivmalle1:; .type tlbivmalle1, %function
+	tlbi	vmalle1
+	dsb	sy
+	isb
+	ret
diff --git a/lib/mmio.c b/lib/mmio.c
new file mode 100644
index 0000000..bf35e36
--- /dev/null
+++ b/lib/mmio.c
@@ -0,0 +1,41 @@
+/*
+ * Copyright (c) 2013, ARM Limited. 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.
+ *
+ * Neither the name of ARM nor the names of its contributors may be used
+ * to endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "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 COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <stdint.h>
+
+void mmio_write_32(uintptr_t addr, uint32_t value)
+{
+	*(volatile uint32_t*)addr = value;
+}
+
+unsigned mmio_read_32(uintptr_t addr)
+{
+	return *(volatile uint32_t*)addr;
+}
diff --git a/lib/non-semihosting/ctype.h b/lib/non-semihosting/ctype.h
new file mode 100644
index 0000000..88e7da1
--- /dev/null
+++ b/lib/non-semihosting/ctype.h
@@ -0,0 +1,60 @@
+/*-
+ * Copyright (c) 1982, 1988, 1991, 1993
+ *	The Regents of the University of California.  All rights reserved.
+ * (c) UNIX System Laboratories, Inc.
+ * All or some portions of this file are derived from material licensed
+ * to the University of California by American Telephone and Telegraph
+ * Co. or Unix System Laboratories, Inc. and are reproduced herein with
+ * the permission of UNIX System Laboratories, Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``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 REGENTS OR CONTRIBUTORS 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.
+ *
+ * $FreeBSD$
+ */
+
+/*
+ * Portions copyright (c) 2009-2013, ARM Ltd. All rights reserved.
+ * ---------------------------------------------------------------
+ * File: include/lib/ctype.h
+ */
+
+#ifndef _SYS_CTYPE_H_
+#define	_SYS_CTYPE_H_
+
+#define isspace(c)	((c) == ' ' || ((c) >= '\t' && (c) <= '\r'))
+#define isascii(c)	(((c) & ~0x7f) == 0)
+#define isupper(c)	((c) >= 'A' && (c) <= 'Z')
+#define islower(c)	((c) >= 'a' && (c) <= 'z')
+#define isalpha(c)	(isupper(c) || islower(c))
+#define isdigit(c)	((c) >= '0' && (c) <= '9')
+#define isxdigit(c)	(isdigit(c) \
+			  || ((c) >= 'A' && (c) <= 'F') \
+			  || ((c) >= 'a' && (c) <= 'f'))
+#define isprint(c)	((c) >= ' ' && (c) <= '~')
+
+#define toupper(c)	((c) - 0x20 * (((c) >= 'a') && ((c) <= 'z')))
+#define tolower(c)	((c) + 0x20 * (((c) >= 'A') && ((c) <= 'Z')))
+
+#endif /* !_SYS_CTYPE_H_ */
diff --git a/lib/non-semihosting/mem.c b/lib/non-semihosting/mem.c
new file mode 100644
index 0000000..bca9ab5
--- /dev/null
+++ b/lib/non-semihosting/mem.c
@@ -0,0 +1,103 @@
+/*
+ * Copyright (c) 2013, ARM Limited. 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.
+ *
+ * Neither the name of ARM nor the names of its contributors may be used
+ * to endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "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 COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <stddef.h> /* size_t */
+
+/*
+ * Fill @count bytes of memory pointed to by @dst with @val
+ */
+void *memset(void *dst, int val, size_t count)
+{
+	char *ptr = dst;
+
+	while (count--)
+		*ptr++ = val;
+
+	return dst;
+}
+
+/*
+ * Compare @len bytes of @s1 and @s2
+ */
+int memcmp(const void *s1, const void *s2, size_t len)
+{
+	const char *s = s1;
+	const char *d = s2;
+	char dc;
+	char sc;
+
+	while (len--) {
+		sc = *s++;
+		dc = *d++;
+		if (sc - dc)
+			return (sc - dc);
+	}
+
+	return 0;
+}
+
+
+/*
+ * Move @len bytes from @src to @dst
+ */
+void *memmove(void *dst, const void *src, size_t len)
+{
+	const char *s = src;
+	char *d = dst;
+
+	while (len--)
+		*d++ = *s++;
+	return d;
+}
+
+/*
+ * Copy @len bytes from @src to @dst
+ */
+void *memcpy(void *dst, const void *src, size_t len)
+{
+	return memmove(dst, src, len);
+}
+
+
+/*
+ * Scan @len bytes of @src for value @c
+ */
+void *memchr(const void *src, int c, size_t len)
+{
+	const char *s = src;
+
+	while (len--) {
+		if (*s == c)
+			return (void *) s;
+		s++;
+	}
+
+	return NULL;
+}
diff --git a/lib/non-semihosting/std.c b/lib/non-semihosting/std.c
new file mode 100644
index 0000000..ea91d5f
--- /dev/null
+++ b/lib/non-semihosting/std.c
@@ -0,0 +1,106 @@
+/*
+ * Copyright (c) 2013, ARM Limited. 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.
+ *
+ * Neither the name of ARM nor the names of its contributors may be used
+ * to endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "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 COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <stdio.h>
+#include <console.h>
+
+#if defined (__GNUC__)
+
+#include <stdio.h>
+#include <stddef.h> /* size_t */
+#include <stdarg.h> /* va_list */
+
+// Code from VTB.
+#include "mem.c"
+
+// Make mem functions that will operate on DEV mem. "memset_io"?
+
+
+//Code from VTB
+#include "strlen.c"
+
+int puts(const char *s)
+{
+	int count = 0;
+	while(*s)
+	{
+		if (console_putc(*s++)) {
+			count++;
+		} else {
+			count = EOF; // -1 in stdio.h
+			break;
+		}
+	}
+	return count;
+}
+
+// From VTB
+#include "ctype.h"
+#include "subr_prf.c"
+
+ // Choose max of 128 chars for now.
+#define PRINT_BUFFER_SIZE 128
+int printf(const char *fmt, ...)
+{
+	va_list args;
+	va_start(args, fmt);
+	char buf[PRINT_BUFFER_SIZE];
+	vsnprintf(buf, sizeof(buf) - 1, fmt, args);
+	buf[PRINT_BUFFER_SIZE - 1] = '\0';
+	return puts(buf);
+}
+
+
+// I just made this up. Probably make it beter.
+void __assert_func (const char *file, int l, const char *func, const char *error)
+{
+	printf("ASSERT: %s <%d> : %s\n\r", func, l, error);
+	while(1);
+}
+
+extern void __assert_fail (const char *assertion, const char *file,
+			   unsigned int line, const char *function)
+{
+	printf("ASSERT: %s <%d> : %s\n\r", function, line, assertion);
+	while(1);
+}
+
+
+// I just made this up. Probably make it beter.
+void abort (void)
+{
+	printf("ABORT\n\r");
+	while(1);
+}
+
+
+#else
+#error "No standard library binding defined."
+#endif
diff --git a/lib/non-semihosting/strcmp.c b/lib/non-semihosting/strcmp.c
new file mode 100644
index 0000000..e5921ba
--- /dev/null
+++ b/lib/non-semihosting/strcmp.c
@@ -0,0 +1,49 @@
+/*-
+ * Copyright (c) 1990, 1993
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Chris Torek.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``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 REGENTS OR CONTRIBUTORS 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.
+ */
+
+/*
+ * Portions copyright (c) 2009-2013, ARM Ltd. All rights reserved.
+ * ---------------------------------------------------------------
+ * File: lib/strcmp.c
+ */
+
+/*
+ * Compare strings.
+ */
+int
+strcmp(const char *s1, const char *s2)
+{
+	while (*s1 == *s2++)
+		if (*s1++ == '\0')
+			return (0);
+	return (*(const unsigned char *)s1 - *(const unsigned char *)(s2 - 1));
+}
diff --git a/lib/non-semihosting/string.c b/lib/non-semihosting/string.c
new file mode 100644
index 0000000..5bb01a1
--- /dev/null
+++ b/lib/non-semihosting/string.c
@@ -0,0 +1,40 @@
+/*
+ * Copyright (c) 2013, ARM Limited. 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.
+ *
+ * Neither the name of ARM nor the names of its contributors may be used
+ * to endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "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 COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+
+#include "ctype.h"
+
+/* Return pointer to the first non-space character */
+const char *skip_spaces(const char *str)
+{
+	while (isspace(*str))
+		++str;
+	return str;
+}
diff --git a/lib/non-semihosting/strlen.c b/lib/non-semihosting/strlen.c
new file mode 100644
index 0000000..5c1e7a6
--- /dev/null
+++ b/lib/non-semihosting/strlen.c
@@ -0,0 +1,46 @@
+/*-
+ * Copyright (c) 1990, 1993
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``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 REGENTS OR CONTRIBUTORS 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.
+ */
+
+/*
+ * Portions copyright (c) 2009-2013, ARM Ltd. All rights reserved.
+ * ---------------------------------------------------------------
+ * File: lib/strlen.c
+ */
+
+#include <stddef.h>
+
+size_t
+strlen(str)
+	const char *str;
+{
+	register const char *s;
+
+	for (s = str; *s; ++s);
+	return(s - str);
+}
diff --git a/lib/non-semihosting/strncmp.c b/lib/non-semihosting/strncmp.c
new file mode 100644
index 0000000..984b7a0
--- /dev/null
+++ b/lib/non-semihosting/strncmp.c
@@ -0,0 +1,52 @@
+/*
+ * Copyright (c) 1989, 1993
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``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 REGENTS OR CONTRIBUTORS 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.
+ */
+
+/*
+ * Portions copyright (c) 2009-2013, ARM Ltd. All rights reserved.
+ * ---------------------------------------------------------------
+ * File: lib/strncmp.c
+ */
+
+#include "types.h"
+
+int
+strncmp(const char *s1, const char *s2, size_t n)
+{
+
+	if (n == 0)
+		return (0);
+	do {
+		if (*s1 != *s2++)
+			return (*(const unsigned char *)s1 -
+				*(const unsigned char *)(s2 - 1));
+		if (*s1++ == '\0')
+			break;
+	} while (--n != 0);
+	return (0);
+}
diff --git a/lib/non-semihosting/strncpy.c b/lib/non-semihosting/strncpy.c
new file mode 100644
index 0000000..56a8a69
--- /dev/null
+++ b/lib/non-semihosting/strncpy.c
@@ -0,0 +1,62 @@
+/*-
+ * Copyright (c) 1990, 1993
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Chris Torek.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``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 REGENTS OR CONTRIBUTORS 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.
+ */
+
+/*
+ * Portions copyright (c) 2009-2013, ARM Ltd. All rights reserved.
+ * ---------------------------------------------------------------
+ * File: lib/strncpy.c
+ */
+
+#include "types.h"
+
+/*
+ * Copy src to dst, truncating or null-padding to always copy n bytes.
+ * Return dst.
+ */
+char *
+strncpy(char *dst, const char *src, size_t n)
+{
+	if (n != 0) {
+		char *d = dst;
+		const char *s = src;
+
+		do {
+			if ((*d++ = *s++) == '\0') {
+				/* NUL pad the remaining n-1 bytes */
+				while (--n != 0)
+					*d++ = '\0';
+				break;
+			}
+		} while (--n != 0);
+	}
+	return (dst);
+}
diff --git a/lib/non-semihosting/strsep.c b/lib/non-semihosting/strsep.c
new file mode 100644
index 0000000..1f80af4
--- /dev/null
+++ b/lib/non-semihosting/strsep.c
@@ -0,0 +1,74 @@
+/*-
+ * Copyright (c) 1990, 1993
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``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 REGENTS OR CONTRIBUTORS 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.
+ */
+
+/*
+ * Portions copyright (c) 2009-2013, ARM Ltd. All rights reserved.
+ * ---------------------------------------------------------------
+ * File: lib/strsep.c
+ */
+
+#include "types.h"
+
+/*
+ * Get next token from string *stringp, where tokens are possibly-empty
+ * strings separated by characters from delim.
+ *
+ * Writes NULs into the string at *stringp to end tokens.
+ * delim need not remain constant from call to call.
+ * On return, *stringp points past the last NUL written (if there might
+ * be further tokens), or is NULL (if there are definitely no more tokens).
+ *
+ * If *stringp is NULL, strsep returns NULL.
+ */
+char *
+strsep(char **stringp, const char *delim)
+{
+	char *s;
+	const char *spanp;
+	int c, sc;
+	char *tok;
+
+	if ((s = *stringp) == NULL)
+		return (NULL);
+	for (tok = s;;) {
+		c = *s++;
+		spanp = delim;
+		do {
+			if ((sc = *spanp++) == c) {
+				if (c == 0)
+					s = NULL;
+				else
+					s[-1] = 0;
+				*stringp = s;
+				return (tok);
+			}
+		} while (sc != 0);
+	}
+	/* NOTREACHED */
+}
diff --git a/lib/non-semihosting/strtol.c b/lib/non-semihosting/strtol.c
new file mode 100644
index 0000000..4a5a404
--- /dev/null
+++ b/lib/non-semihosting/strtol.c
@@ -0,0 +1,146 @@
+/*-
+ * Copyright (c) 1990, 1993
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Chris Torek.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``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 REGENTS OR CONTRIBUTORS 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.
+ *
+ * From: @(#)strtol.c	8.1 (Berkeley) 6/4/93
+ */
+
+/*
+ * Portions copyright (c) 2009-2013, ARM Ltd. All rights reserved.
+ * ---------------------------------------------------------------
+ * File: lib/strtol.c
+ */
+
+#include "types.h"
+#include "ctype.h"
+#include "limits.h"
+
+/*
+ * Convert a string to a long integer.
+ *
+ * Ignores `locale' stuff.  Assumes that the upper and lower case
+ * alphabets and digits are each contiguous.
+ */
+static long
+bsd_strtol(nptr, endptr, base)
+	const char *nptr;
+	char **endptr;
+	int base;
+{
+	const char *s = nptr;
+	unsigned long acc;
+	unsigned char c;
+	unsigned long cutoff;
+	int neg = 0, any, cutlim;
+
+	/*
+	 * Skip white space and pick up leading +/- sign if any.
+	 * If base is 0, allow 0x for hex and 0 for octal, else
+	 * assume decimal; if base is already 16, allow 0x.
+	 */
+	do {
+		c = *s++;
+	} while (isspace(c));
+	if (c == '-') {
+		neg = 1;
+		c = *s++;
+	} else if (c == '+')
+		c = *s++;
+	if ((base == 0 || base == 16) &&
+	    c == '0' && (*s == 'x' || *s == 'X')) {
+		c = s[1];
+		s += 2;
+		base = 16;
+	}
+	if (base == 0)
+		base = c == '0' ? 8 : 10;
+
+	/*
+	 * Compute the cutoff value between legal numbers and illegal
+	 * numbers.  That is the largest legal value, divided by the
+	 * base.  An input number that is greater than this value, if
+	 * followed by a legal input character, is too big.  One that
+	 * is equal to this value may be valid or not; the limit
+	 * between valid and invalid numbers is then based on the last
+	 * digit.  For instance, if the range for longs is
+	 * [-2147483648..2147483647] and the input base is 10,
+	 * cutoff will be set to 214748364 and cutlim to either
+	 * 7 (neg==0) or 8 (neg==1), meaning that if we have accumulated
+	 * a value > 214748364, or equal but the next digit is > 7 (or 8),
+	 * the number is too big, and we will return a range error.
+	 *
+	 * Set any if any `digits' consumed; make it negative to indicate
+	 * overflow.
+	 */
+	cutoff = neg ? -(unsigned long)LONG_MIN : LONG_MAX;
+	cutlim = cutoff % (unsigned long)base;
+	cutoff /= (unsigned long)base;
+	for (acc = 0, any = 0;; c = *s++) {
+		if (!isascii(c))
+			break;
+		if (isdigit(c))
+			c -= '0';
+		else if (isalpha(c))
+			c -= isupper(c) ? 'A' - 10 : 'a' - 10;
+		else
+			break;
+		if (c >= base)
+			break;
+		if (any < 0 || acc > cutoff || (acc == cutoff && c > cutlim))
+			any = -1;
+		else {
+			any = 1;
+			acc *= base;
+			acc += c;
+		}
+	}
+	if (any < 0) {
+		acc = neg ? LONG_MIN : LONG_MAX;
+	} else if (neg)
+		acc = -acc;
+	if (endptr != 0)
+		*((const char **)endptr) = any ? s - 1 : nptr;
+	return (acc);
+}
+
+int strict_strtol(const char *str, unsigned int base, long *result)
+{
+	if (*str == '-')
+		*result = 0 - bsd_strtol(str + 1, NULL, base);
+	else
+		*result = bsd_strtol(str, NULL, base);
+	return 0;
+}
+
+int strict_strtoul(const char *str, unsigned int base, unsigned long *result)
+{
+	*result = bsd_strtol(str, NULL, base);
+	return 0;
+}
diff --git a/lib/non-semihosting/strtoull.c b/lib/non-semihosting/strtoull.c
new file mode 100644
index 0000000..e46ef4c
--- /dev/null
+++ b/lib/non-semihosting/strtoull.c
@@ -0,0 +1,117 @@
+/*-
+ * Copyright (c) 1992, 1993
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``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 REGENTS OR CONTRIBUTORS 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.
+ */
+
+/*
+ * Portions copyright (c) 2009-2013, ARM Ltd. All rights reserved.
+ * ---------------------------------------------------------------
+ * File: lib/strtoull.c
+ */
+
+#include "types.h"
+#include "ctype.h"
+#include "limits.h"
+
+/*
+ * Convert a string to an unsigned long long integer.
+ *
+ * Assumes that the upper and lower case
+ * alphabets and digits are each contiguous.
+ */
+static unsigned long long
+bsd_strtoull(const char *nptr, char **endptr, int base)
+{
+	const char *s;
+	unsigned long long acc;
+	char c;
+	unsigned long long cutoff;
+	int neg, any, cutlim;
+
+	/*
+	 * See strtoq for comments as to the logic used.
+	 */
+	s = nptr;
+	do {
+		c = *s++;
+	} while (isspace((unsigned char)c));
+	if (c == '-') {
+		neg = 1;
+		c = *s++;
+	} else {
+		neg = 0;
+		if (c == '+')
+			c = *s++;
+	}
+	if ((base == 0 || base == 16) &&
+	    c == '0' && (*s == 'x' || *s == 'X') &&
+	    ((s[1] >= '0' && s[1] <= '9') ||
+	    (s[1] >= 'A' && s[1] <= 'F') ||
+	    (s[1] >= 'a' && s[1] <= 'f'))) {
+		c = s[1];
+		s += 2;
+		base = 16;
+	}
+	if (base == 0)
+		base = c == '0' ? 8 : 10;
+	acc = any = 0;
+
+	cutoff = ULLONG_MAX / base;
+	cutlim = ULLONG_MAX % base;
+	for ( ; ; c = *s++) {
+		if (c >= '0' && c <= '9')
+			c -= '0';
+		else if (c >= 'A' && c <= 'Z')
+			c -= 'A' - 10;
+		else if (c >= 'a' && c <= 'z')
+			c -= 'a' - 10;
+		else
+			break;
+		if (c >= base)
+			break;
+		if (any < 0 || acc > cutoff || (acc == cutoff && c > cutlim))
+			any = -1;
+		else {
+			any = 1;
+			acc *= base;
+			acc += c;
+		}
+	}
+	if (any < 0) {
+		acc = ULLONG_MAX;
+	} else if (neg)
+		acc = -acc;
+	if (endptr != NULL)
+		*endptr = (char *)(any ? s - 1 : nptr);
+	return (acc);
+}
+
+int strict_strtoull(const char *str, unsigned int base, long long *result)
+{
+	*result = bsd_strtoull(str, NULL, base);
+	return 0;
+}
diff --git a/lib/non-semihosting/subr_prf.c b/lib/non-semihosting/subr_prf.c
new file mode 100644
index 0000000..6e2a1ac
--- /dev/null
+++ b/lib/non-semihosting/subr_prf.c
@@ -0,0 +1,557 @@
+/*-
+ * Copyright (c) 1986, 1988, 1991, 1993
+ *	The Regents of the University of California.  All rights reserved.
+ * (c) UNIX System Laboratories, Inc.
+ * All or some portions of this file are derived from material licensed
+ * to the University of California by American Telephone and Telegraph
+ * Co. or Unix System Laboratories, Inc. and are reproduced herein with
+ * the permission of UNIX System Laboratories, Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``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 REGENTS OR CONTRIBUTORS 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.
+ *
+ *	@(#)subr_prf.c	8.3 (Berkeley) 1/21/94
+ */
+
+/*
+ * Portions copyright (c) 2009-2013, ARM Ltd. All rights reserved.
+ * ---------------------------------------------------------------
+ * File: lib/subr_prf.c
+ */
+
+/*
+#include "types.h"
+#include "varargs.h"
+#include "ctype.h"
+#include "string.h"
+*/
+#include <stddef.h>
+#include <sys/types.h>  /* For ssize_t */
+#include <stdint.h>
+#include <string.h>
+
+#include "ctype.h"
+
+typedef uint64_t uintmax_t;
+typedef int64_t intmax_t;
+typedef unsigned char u_char;
+typedef unsigned int u_int;
+typedef int64_t quad_t;
+typedef uint64_t u_quad_t;
+typedef unsigned long u_long;
+typedef unsigned short u_short;
+
+static inline int imax(int a, int b) { return (a > b ? a : b); }
+
+/*
+ * Note that stdarg.h and the ANSI style va_start macro is used for both
+ * ANSI and traditional C compilers.
+ */
+
+#define TOCONS	0x01
+#define TOTTY	0x02
+#define TOLOG	0x04
+
+/* Max number conversion buffer length: a u_quad_t in base 2, plus NUL byte. */
+#define MAXNBUF	(sizeof(intmax_t) * 8 + 1)
+
+struct putchar_arg {
+	int	flags;
+	int	pri;
+	struct	tty *tty;
+	char	*p_bufr;
+	size_t	n_bufr;
+	char	*p_next;
+	size_t	remain;
+};
+
+struct snprintf_arg {
+	char	*str;
+	size_t	remain;
+};
+
+extern	int log_open;
+
+static char *ksprintn(char *nbuf, uintmax_t num, int base, int *len, int upper);
+static void  snprintf_func(int ch, void *arg);
+static int kvprintf(char const *fmt, void (*func)(int, void*), void *arg, int radix, va_list ap);
+
+int vsnprintf(char *str, size_t size, const char *format, va_list ap);
+
+static char const hex2ascii_data[] = "0123456789abcdefghijklmnopqrstuvwxyz";
+#define hex2ascii(hex) (hex2ascii_data[hex])
+
+/*
+ * Scaled down version of sprintf(3).
+ */
+int
+sprintf(char *buf, const char *cfmt, ...)
+{
+	int retval;
+	va_list ap;
+
+	va_start(ap, cfmt);
+	retval = kvprintf(cfmt, NULL, (void *)buf, 10, ap);
+	buf[retval] = '\0';
+	va_end(ap);
+	return (retval);
+}
+
+/*
+ * Scaled down version of vsprintf(3).
+ */
+int
+vsprintf(char *buf, const char *cfmt, va_list ap)
+{
+	int retval;
+
+	retval = kvprintf(cfmt, NULL, (void *)buf, 10, ap);
+	buf[retval] = '\0';
+	return (retval);
+}
+
+/*
+ * Scaled down version of snprintf(3).
+ */
+int
+snprintf(char *str, size_t size, const char *format, ...)
+{
+	int retval;
+	va_list ap;
+
+	va_start(ap, format);
+	retval = vsnprintf(str, size, format, ap);
+	va_end(ap);
+	return(retval);
+}
+
+/*
+ * Scaled down version of vsnprintf(3).
+ */
+int
+vsnprintf(char *str, size_t size, const char *format, va_list ap)
+{
+	struct snprintf_arg info;
+	int retval;
+
+	info.str = str;
+	info.remain = size;
+	retval = kvprintf(format, snprintf_func, &info, 10, ap);
+	if (info.remain >= 1)
+		*info.str++ = '\0';
+	return (retval);
+}
+
+static void
+snprintf_func(int ch, void *arg)
+{
+	struct snprintf_arg *const info = arg;
+
+	if (info->remain >= 2) {
+		*info->str++ = ch;
+		info->remain--;
+	}
+}
+
+
+/*
+ * Kernel version which takes radix argument vsnprintf(3).
+ */
+int
+vsnrprintf(char *str, size_t size, int radix, const char *format, va_list ap)
+{
+	struct snprintf_arg info;
+	int retval;
+
+	info.str = str;
+	info.remain = size;
+	retval = kvprintf(format, snprintf_func, &info, radix, ap);
+	if (info.remain >= 1)
+		*info.str++ = '\0';
+	return (retval);
+}
+
+
+/*
+ * Put a NUL-terminated ASCII number (base <= 36) in a buffer in reverse
+ * order; return an optional length and a pointer to the last character
+ * written in the buffer (i.e., the first character of the string).
+ * The buffer pointed to by `nbuf' must have length >= MAXNBUF.
+ */
+static char *
+ksprintn(char *nbuf, uintmax_t num, int base, int *lenp, int upper)
+{
+	char *p, c;
+
+	p = nbuf;
+	*p = '\0';
+	do {
+		c = hex2ascii(num % base);
+		*++p = upper ? toupper(c) : c;
+	} while (num /= base);
+	if (lenp)
+		*lenp = p - nbuf;
+	return (p);
+}
+
+/*
+ * Scaled down version of printf(3).
+ *
+ * Two additional formats:
+ *
+ * The format %b is supported to decode error registers.
+ * Its usage is:
+ *
+ *	printf("reg=%b\n", regval, "<base><arg>*");
+ *
+ * where <base> is the output base expressed as a control character, e.g.
+ * \10 gives octal; \20 gives hex.  Each arg is a sequence of characters,
+ * the first of which gives the bit number to be inspected (origin 1), and
+ * the next characters (up to a control character, i.e. a character <= 32),
+ * give the name of the register.  Thus:
+ *
+ *	kvprintf("reg=%b\n", 3, "\10\2BITTWO\1BITONE\n");
+ *
+ * would produce output:
+ *
+ *	reg=3<BITTWO,BITONE>
+ *
+ * XXX:  %D  -- Hexdump, takes pointer and separator string:
+ *		("%6D", ptr, ":")   -> XX:XX:XX:XX:XX:XX
+ *		("%*D", len, ptr, " " -> XX XX XX XX ...
+ */
+int
+kvprintf(char const *fmt, void (*func)(int, void*), void *arg, int radix, va_list ap)
+{
+#define PCHAR(c) {int cc=(c); if (func) (*func)(cc,arg); else *d++ = cc; retval++; }
+	char nbuf[MAXNBUF];
+	char *d;
+	const char *p, *percent, *q;
+	u_char *up;
+	int ch, n;
+	uintmax_t num;
+	int base, lflag, qflag, tmp, width, ladjust, sharpflag, neg, sign, dot;
+	int cflag, hflag, jflag, tflag, zflag;
+	int dwidth, upper;
+	char padc;
+	int stop = 0, retval = 0;
+
+	num = 0;
+	if (!func)
+		d = (char *) arg;
+	else
+		d = NULL;
+
+	if (fmt == NULL)
+		fmt = "(fmt null)\n";
+
+	if (radix < 2 || radix > 36)
+		radix = 10;
+
+	for (;;) {
+		padc = ' ';
+		width = 0;
+		while ((ch = (u_char)*fmt++) != '%' || stop) {
+			if (ch == '\0')
+				return (retval);
+			PCHAR(ch);
+		}
+		percent = fmt - 1;
+		qflag = 0; lflag = 0; ladjust = 0; sharpflag = 0; neg = 0;
+		sign = 0; dot = 0; dwidth = 0; upper = 0;
+		cflag = 0; hflag = 0; jflag = 0; tflag = 0; zflag = 0;
+reswitch:	switch (ch = (u_char)*fmt++) {
+		case '.':
+			dot = 1;
+			goto reswitch;
+		case '#':
+			sharpflag = 1;
+			goto reswitch;
+		case '+':
+			sign = 1;
+			goto reswitch;
+		case '-':
+			ladjust = 1;
+			goto reswitch;
+		case '%':
+			PCHAR(ch);
+			break;
+		case '*':
+			if (!dot) {
+				width = va_arg(ap, int);
+				if (width < 0) {
+					ladjust = !ladjust;
+					width = -width;
+				}
+			} else {
+				dwidth = va_arg(ap, int);
+			}
+			goto reswitch;
+		case '0':
+			if (!dot) {
+				padc = '0';
+				goto reswitch;
+			}
+		case '1': case '2': case '3': case '4':
+		case '5': case '6': case '7': case '8': case '9':
+				for (n = 0;; ++fmt) {
+					n = n * 10 + ch - '0';
+					ch = *fmt;
+					if (ch < '0' || ch > '9')
+						break;
+				}
+			if (dot)
+				dwidth = n;
+			else
+				width = n;
+			goto reswitch;
+		case 'b':
+			num = (u_int)va_arg(ap, int);
+			p = va_arg(ap, char *);
+			for (q = ksprintn(nbuf, num, *p++, NULL, 0); *q;)
+				PCHAR(*q--);
+
+			if (num == 0)
+				break;
+
+			for (tmp = 0; *p;) {
+				n = *p++;
+				if (num & (1 << (n - 1))) {
+					PCHAR(tmp ? ',' : '<');
+					for (; (n = *p) > ' '; ++p)
+						PCHAR(n);
+					tmp = 1;
+				} else
+					for (; *p > ' '; ++p)
+						continue;
+			}
+			if (tmp)
+				PCHAR('>');
+			break;
+		case 'c':
+			PCHAR(va_arg(ap, int));
+			break;
+		case 'D':
+			up = va_arg(ap, u_char *);
+			p = va_arg(ap, char *);
+			if (!width)
+				width = 16;
+			while(width--) {
+				PCHAR(hex2ascii(*up >> 4));
+				PCHAR(hex2ascii(*up & 0x0f));
+				up++;
+				if (width)
+					for (q=p;*q;q++)
+						PCHAR(*q);
+			}
+			break;
+		case 'd':
+		case 'i':
+			base = 10;
+			sign = 1;
+			goto handle_sign;
+		case 'h':
+			if (hflag) {
+				hflag = 0;
+				cflag = 1;
+			} else
+				hflag = 1;
+			goto reswitch;
+		case 'j':
+			jflag = 1;
+			goto reswitch;
+		case 'l':
+			if (lflag) {
+				lflag = 0;
+				qflag = 1;
+			} else
+				lflag = 1;
+			goto reswitch;
+		case 'n':
+			if (jflag)
+				*(va_arg(ap, intmax_t *)) = retval;
+			else if (qflag)
+				*(va_arg(ap, quad_t *)) = retval;
+			else if (lflag)
+				*(va_arg(ap, long *)) = retval;
+			else if (zflag)
+				*(va_arg(ap, size_t *)) = retval;
+			else if (hflag)
+				*(va_arg(ap, short *)) = retval;
+			else if (cflag)
+				*(va_arg(ap, char *)) = retval;
+			else
+				*(va_arg(ap, int *)) = retval;
+			break;
+		case 'o':
+			base = 8;
+			goto handle_nosign;
+		case 'p':
+			base = 16;
+			sharpflag = (width == 0);
+			sign = 0;
+			num = (uintptr_t)va_arg(ap, void *);
+			goto number;
+		case 'q':
+			qflag = 1;
+			goto reswitch;
+		case 'r':
+			base = radix;
+			if (sign)
+				goto handle_sign;
+			goto handle_nosign;
+		case 's':
+			p = va_arg(ap, char *);
+			if (p == NULL)
+				p = "(null)";
+			if (!dot)
+				n = strlen (p);
+			else
+				for (n = 0; n < dwidth && p[n]; n++)
+					continue;
+
+			width -= n;
+
+			if (!ladjust && width > 0)
+				while (width--)
+					PCHAR(padc);
+			while (n--)
+				PCHAR(*p++);
+			if (ladjust && width > 0)
+				while (width--)
+					PCHAR(padc);
+			break;
+		case 't':
+			tflag = 1;
+			goto reswitch;
+		case 'u':
+			base = 10;
+			goto handle_nosign;
+		case 'X':
+			upper = 1;
+		case 'x':
+			base = 16;
+			goto handle_nosign;
+		case 'y':
+			base = 16;
+			sign = 1;
+			goto handle_sign;
+		case 'z':
+			zflag = 1;
+			goto reswitch;
+handle_nosign:
+			sign = 0;
+			if (jflag)
+				num = va_arg(ap, uintmax_t);
+			else if (qflag)
+				num = va_arg(ap, u_quad_t);
+			else if (tflag)
+				num = va_arg(ap, ptrdiff_t);
+			else if (lflag)
+				num = va_arg(ap, u_long);
+			else if (zflag)
+				num = va_arg(ap, size_t);
+			else if (hflag)
+				num = (u_short)va_arg(ap, int);
+			else if (cflag)
+				num = (u_char)va_arg(ap, int);
+			else
+				num = va_arg(ap, u_int);
+			goto number;
+handle_sign:
+			if (jflag)
+				num = va_arg(ap, intmax_t);
+			else if (qflag)
+				num = va_arg(ap, quad_t);
+			else if (tflag)
+				num = va_arg(ap, ptrdiff_t);
+			else if (lflag)
+				num = va_arg(ap, long);
+			else if (zflag)
+				num = va_arg(ap, ssize_t);
+			else if (hflag)
+				num = (short)va_arg(ap, int);
+			else if (cflag)
+				num = (char)va_arg(ap, int);
+			else
+				num = va_arg(ap, int);
+number:
+			if (sign && (intmax_t)num < 0) {
+				neg = 1;
+				num = -(intmax_t)num;
+			}
+			p = ksprintn(nbuf, num, base, &n, upper);
+			tmp = 0;
+			if (sharpflag && num != 0) {
+				if (base == 8)
+					tmp++;
+				else if (base == 16)
+					tmp += 2;
+			}
+			if (neg)
+				tmp++;
+
+			if (!ladjust && padc == '0')
+				dwidth = width - tmp;
+			width -= tmp + imax(dwidth, n);
+			dwidth -= n;
+			if (!ladjust)
+				while (width-- > 0)
+					PCHAR(' ');
+			if (neg)
+				PCHAR('-');
+			if (sharpflag && num != 0) {
+				if (base == 8) {
+					PCHAR('0');
+				} else if (base == 16) {
+					PCHAR('0');
+					PCHAR('x');
+				}
+			}
+			while (dwidth-- > 0)
+				PCHAR('0');
+
+			while (*p)
+				PCHAR(*p--);
+
+			if (ladjust)
+				while (width-- > 0)
+					PCHAR(' ');
+
+			break;
+		default:
+			while (percent < fmt)
+				PCHAR(*percent++);
+			/*
+			 * Since we ignore an formatting argument it is no 
+			 * longer safe to obey the remaining formatting
+			 * arguments as the arguments will no longer match
+			 * the format specs.
+			 */
+			stop = 1;
+			break;
+		}
+	}
+#undef PCHAR
+}
diff --git a/lib/semihosting/aarch64/semihosting_call.S b/lib/semihosting/aarch64/semihosting_call.S
new file mode 100644
index 0000000..cc72ec2
--- /dev/null
+++ b/lib/semihosting/aarch64/semihosting_call.S
@@ -0,0 +1,37 @@
+/*
+ * Copyright (c) 2013, ARM Limited. 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.
+ *
+ * Neither the name of ARM nor the names of its contributors may be used
+ * to endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "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 COPYRIGHT HOLDER OR CONTRIBUTORS 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.
+ */
+
+	.globl	semihosting_call
+
+	.section	.text, "ax"
+
+semihosting_call:; .type semihosting_call, %function
+	hlt	#0xf000
+	ret
diff --git a/lib/semihosting/semihosting.c b/lib/semihosting/semihosting.c
new file mode 100644
index 0000000..558973a
--- /dev/null
+++ b/lib/semihosting/semihosting.c
@@ -0,0 +1,234 @@
+/*
+ * Copyright (c) 2013, ARM Limited. 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.
+ *
+ * Neither the name of ARM nor the names of its contributors may be used
+ * to endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "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 COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <assert.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+#include <semihosting.h>
+
+#ifndef SEMIHOSTING_SUPPORTED
+#define SEMIHOSTING_SUPPORTED  1
+#endif
+
+extern int semihosting_call(unsigned int operation,
+			    void *system_block_address);
+
+typedef struct {
+	const char *file_name;
+	unsigned int mode;
+	unsigned int name_length;
+} smh_file_open_block;
+
+typedef struct {
+	int handle;
+	void *buffer;
+	unsigned int length;
+} smh_file_read_write_block;
+
+typedef struct {
+	int handle;
+	unsigned int location;
+} smh_file_seek_block;
+
+typedef struct {
+	char *command_line;
+	unsigned int command_length;
+} smh_system_block;
+
+int semihosting_connection_supported(void)
+{
+	return SEMIHOSTING_SUPPORTED;
+}
+
+int semihosting_file_open(const char *file_name, unsigned int mode)
+{
+	smh_file_open_block open_block;
+
+	open_block.file_name = file_name;
+	open_block.mode = mode;
+	open_block.name_length = strlen(file_name);
+
+	return semihosting_call(SEMIHOSTING_SYS_OPEN,
+				(void *) &open_block);
+}
+
+int semihosting_file_seek(int file_handle, unsigned int offset)
+{
+	smh_file_seek_block seek_block;
+	int result;
+
+	seek_block.handle = file_handle;
+	seek_block.location = offset;
+
+	result = semihosting_call(SEMIHOSTING_SYS_SEEK,
+				  (void *) &seek_block);
+
+	if (result)
+		result = semihosting_call(SEMIHOSTING_SYS_ERRNO, 0);
+
+	return result;
+}
+
+int semihosting_file_read(int file_handle, int *length, void *buffer)
+{
+	smh_file_read_write_block read_block;
+	int result = -EINVAL;
+
+	if ((length == NULL) || (buffer == NULL))
+		return result;
+
+	read_block.handle = file_handle;
+	read_block.buffer = buffer;
+	read_block.length = *length;
+
+	result = semihosting_call(SEMIHOSTING_SYS_READ,
+				  (void *) &read_block);
+
+	if (result == *length) {
+		return -EINVAL;
+	} else if (result < *length) {
+		*length -= result;
+		return 0;
+	} else
+		return result;
+}
+
+int semihosting_file_write(int file_handle, int *length, void *buffer)
+{
+	smh_file_read_write_block write_block;
+
+	if ((length == NULL) || (buffer == NULL))
+		return -EINVAL;
+
+	write_block.handle = file_handle;
+	write_block.buffer = buffer;
+	write_block.length = *length;
+
+	*length = semihosting_call(SEMIHOSTING_SYS_WRITE,
+				   (void *) &write_block);
+
+	return *length;
+}
+
+int semihosting_file_close(int file_handle)
+{
+	return semihosting_call(SEMIHOSTING_SYS_CLOSE,
+				(void *) &file_handle);
+}
+
+int semihosting_file_length(int file_handle)
+{
+	return semihosting_call(SEMIHOSTING_SYS_FLEN,
+				(void *) &file_handle);
+}
+
+char semihosting_read_char(void)
+{
+	return semihosting_call(SEMIHOSTING_SYS_READC, NULL);
+}
+
+void semihosting_write_char(char character)
+{
+	semihosting_call(SEMIHOSTING_SYS_WRITEC, (void *) &character);
+}
+
+void semihosting_write_string(char *string)
+{
+	semihosting_call(SEMIHOSTING_SYS_WRITE0, (void *) string);
+}
+
+int semihosting_system(char *command_line)
+{
+	smh_system_block system_block;
+
+	system_block.command_line = command_line;
+	system_block.command_length = strlen(command_line);
+
+	return semihosting_call(SEMIHOSTING_SYS_SYSTEM,
+				(void *) &system_block);
+}
+
+int semihosting_get_flen(const char *file_name)
+{
+	int file_handle, length;
+
+	assert(semihosting_connection_supported());
+
+	file_handle = semihosting_file_open(file_name, FOPEN_MODE_RB);
+	if (file_handle == -1)
+		return file_handle;
+
+	/* Find the length of the file */
+	length = semihosting_file_length(file_handle);
+
+	return semihosting_file_close(file_handle) ? -1 : length;
+}
+
+int semihosting_download_file(const char *file_name,
+			      int buf_size,
+			      void *buf)
+{
+	int ret = -EINVAL, file_handle, length;
+
+	/* Null pointer check */
+	if (!buf)
+		return ret;
+
+	assert(semihosting_connection_supported());
+
+	file_handle = semihosting_file_open(file_name, FOPEN_MODE_RB);
+	if (file_handle == -1)
+		return ret;
+
+	/* Find the actual length of the file */
+	length = semihosting_file_length(file_handle);
+	if (length == -1)
+		goto semihosting_fail;
+
+	/* Signal error if we do not have enough space for the file */
+	if (length > buf_size)
+		goto semihosting_fail;
+
+	/*
+	 * A successful read will return 0 in which case we pass back
+	 * the actual number of bytes read. Else we pass a negative
+	 * value indicating an error.
+	 */
+	ret = semihosting_file_read(file_handle, &length, buf);
+	if (ret)
+		goto semihosting_fail;
+	else
+		ret = length;
+
+semihosting_fail:
+	semihosting_file_close(file_handle);
+	return ret;
+}
diff --git a/lib/sync/locks/bakery/bakery_lock.c b/lib/sync/locks/bakery/bakery_lock.c
new file mode 100644
index 0000000..d3c780c
--- /dev/null
+++ b/lib/sync/locks/bakery/bakery_lock.c
@@ -0,0 +1,104 @@
+/*
+ * Copyright (c) 2013, ARM Limited. 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.
+ *
+ * Neither the name of ARM nor the names of its contributors may be used
+ * to endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "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 COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <assert.h>
+#include <string.h>
+
+#include <bakery_lock.h>
+
+#define assert_bakery_entry_valid(entry, bakery) do {	\
+	assert(bakery);					\
+	assert(entry < BAKERY_LOCK_MAX_CPUS);		\
+} while(0)
+
+void bakery_lock_init(bakery_lock * bakery)
+{
+	assert(bakery);
+	memset(bakery, 0, sizeof(*bakery));
+	bakery->owner = NO_OWNER;
+}
+
+void bakery_lock_get(unsigned long mpidr, bakery_lock * bakery)
+{
+	unsigned int i, max = 0, my_full_number, his_full_number, entry;
+
+	entry = platform_get_core_pos(mpidr);
+
+	assert_bakery_entry_valid(entry, bakery);
+
+	// Catch recursive attempts to take the lock under the same entry:
+	assert(bakery->owner != entry);
+
+	// Get a ticket
+	bakery->entering[entry] = 1;
+	for (i = 0; i < BAKERY_LOCK_MAX_CPUS; ++i) {
+		if (bakery->number[i] > max) {
+			max = bakery->number[i];
+		}
+	}
+	++max;
+	bakery->number[entry] = max;
+	bakery->entering[entry] = 0;
+
+	// Wait for our turn
+	my_full_number = (max << 8) + entry;
+	for (i = 0; i < BAKERY_LOCK_MAX_CPUS; ++i) {
+		while (bakery->entering[i]) ;	/* Wait */
+		do {
+			his_full_number = bakery->number[i];
+			if (his_full_number) {
+				his_full_number = (his_full_number << 8) + i;
+			}
+		}
+		while (his_full_number && (his_full_number < my_full_number));
+	}
+
+	bakery->owner = entry;
+}
+
+void bakery_lock_release(unsigned long mpidr, bakery_lock * bakery)
+{
+	unsigned int entry = platform_get_core_pos(mpidr);
+
+	assert_bakery_entry_valid(entry, bakery);
+	assert(bakery_lock_held(entry, bakery));
+
+	bakery->owner = NO_OWNER;
+	bakery->number[entry] = 0;
+}
+
+int bakery_lock_held(unsigned long mpidr, const bakery_lock * bakery)
+{
+	unsigned int entry = platform_get_core_pos(mpidr);
+
+	assert_bakery_entry_valid(entry, bakery);
+
+	return bakery->owner == entry;
+}
diff --git a/lib/sync/locks/exclusive/spinlock.S b/lib/sync/locks/exclusive/spinlock.S
new file mode 100644
index 0000000..4269d95
--- /dev/null
+++ b/lib/sync/locks/exclusive/spinlock.S
@@ -0,0 +1,50 @@
+/*
+ * Copyright (c) 2013, ARM Limited. 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.
+ *
+ * Neither the name of ARM nor the names of its contributors may be used
+ * to endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "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 COPYRIGHT HOLDER OR CONTRIBUTORS 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.
+ */
+
+	.globl	spin_lock
+	.globl	spin_unlock
+
+
+	.section	.text, "ax";
+
+spin_lock:; .type spin_lock, %function
+	mov	w2, #1
+	sevl
+l1:	wfe
+l2:	ldaxr	w1, [x0]
+	cbnz	w1, l1
+	stxr	w1, w2, [x0]
+	cbnz	w1, l2
+	ret
+
+
+spin_unlock:; .type spin_unlock, %function
+	stlr	wzr, [x0]
+	ret