/* * Startup Code for MIPS CPU * * Copyright (C) 2011 Antony Pavlov * Used code copyrighted (C) 2009 by Shinya Kuribayashi * * This file is part of barebox. * See file CREDITS for list of people who contributed to this project. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 * as published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include #include #include #include /* * ADR macro instruction (inspired by ARM) * * ARM architecture doesn't have PC-relative jump instruction * like MIPS' B/BAL insns. When ARM makes PC-relative jumps, * it uses ADR insn. ADR is used to get a destination address * of 'label' against current PC. With this, ARM can safely * make PC-relative jumps. */ .macro ADR rd label temp .set push .set noreorder move \temp, ra # preserve ra beforehand bal _pc nop _pc: addiu \rd, ra, \label - _pc # label is assumed to be move ra, \temp # within pc +/- 32KB .set pop .endm .set noreorder .text .section ".text_bare_init" .align 4 EXPORT(_start) /* disable watchpoints */ mtc0 zero, CP0_WATCHLO mtc0 zero, CP0_WATCHHI /* disable interrupts */ mfc0 k0, CP0_STATUS li k1, ~ST0_IE and k0, k1 mtc0 k0, CP0_STATUS /* copy barebox to link location */ ADR a0, _start, t1 /* a0 <- pc-relative position of _start */ la a1, _start /* link (RAM) _start address */ beq a0, a1, clear_bss nop la t0, _start la t1, __bss_start subu t2, t1, t0 /* t2 <- size of barebox */ addu a2, a0, t2 /* a2 <- source end address */ #define LONGSIZE 4 copy_loop: /* copy from source address [a0] */ lw t4, LONGSIZE * 0(a0) lw t5, LONGSIZE * 1(a0) lw t6, LONGSIZE * 2(a0) lw t7, LONGSIZE * 3(a0) /* copy fo target address [a1] */ sw t4, LONGSIZE * 0(a1) sw t5, LONGSIZE * 1(a1) sw t6, LONGSIZE * 2(a1) sw t7, LONGSIZE * 3(a1) addi a0, LONGSIZE * 4 subu t3, a0, a2 blez t3, copy_loop addi a1, LONGSIZE * 4 clear_bss: la t0, __bss_start sw zero, (t0) la t1, _end - 4 1: addiu t0, LONGSIZE sw zero, (t0) bne t0, t1, 1b nop /* * Dominic Sweetman, See MIPS Run, Morgan Kaufmann, 2nd edition, 2006 * * 11.2.2 Stack Argument Structure in o32 * ... * At the point where a function is called, sp must be * eight-byte-aligned, matching the alignment of the largest * basic types -- a long long integer or a floating-point double. * The eight-byte alignment is not required by 32-bit MIPS integer * hardware, but it's essential for compatibility with CPUs with * 64-bit registers, and thus part of the rules. Subroutines fit * in with this by always adjusting the stack pointer by a multiple * of eight. * ... * SGI's n32 and n64 standards call for the stack to be maintained * with 16-byte alignment. * */ #if (STACK_BASE + STACK_SIZE) % 16 != 0 #error stack pointer must be 16-byte-aligned #endif stack_setup: la sp, STACK_BASE + STACK_SIZE /* reserve four 32-bit argument slots */ addiu sp, -16 la v0, start_barebox jal v0 nop /* No return */ __error: b __error nop