blob: f6771cbc81af74c85ad6151951ab5feedba90702 [file] [log] [blame]
/*
* Minimal Nios2 system boot code.
*
* Copyright Linaro Ltd 2022
* SPDX-License-Identifier: GPL-2.0-or-later
*/
#include "semicall.h"
.text
.set noat
_start:
/* Linker script defines stack at end of ram. */
movia sp, __stack
/* Install trampoline to _fast_tlb_miss at hardcoded vector. */
movia r4, 0xc0000100
movia r5, _ftm_tramp
movi r6, .L__ftm_end - _ftm_tramp
call memcpy
/* Zero the bss to satisfy C. */
movia r4, __bss_start
movia r6, __bss_end
sub r6, r6, r4
movi r5, 0
call memset
/* Test! */
call main
/* Exit with main's return value. */
movi r4, HOSTED_EXIT
mov r5, r2
semihosting_call
.globl _start
.type _start, @function
.size _start, . - _start
_ftm_tramp:
movia et, _fast_tlb_miss
jmp et
.L__ftm_end:
.type _ftm_tramp, @function
.size _ftm_tramp, . - _ftm_tramp
#define dst r4
#define src r5
#define len r6
memcpy:
/* Store return value right away, per API */
mov r2, dst
/* Check for both dst and src aligned. */
or at, dst, src
andi at, at, 3
bne at, zero, .L_mc_test1
/* Copy blocks of 8. */
movi at, 8
bltu len, at, .L_mc_test4
.L_mc_loop8:
ldw r8, 0(src)
ldw r9, 4(src)
addi src, src, 8
addi dst, dst, 8
subi len, len, 8
stw r8, -8(dst)
stw r9, -4(dst)
bgeu len, at, .L_mc_loop8
/* Copy final aligned block of 4. */
.L_mc_test4:
movi at, 4
bltu len, at, .L_mc_test1
ldw r8, 0(src)
addi src, src, 4
addi dst, dst, 4
subi len, len, 4
stw r8, -4(dst)
/* Copy single bytes to finish. */
.L_mc_test1:
beq len, zero, .L_mc_done
.L_mc_loop1:
ldb r8, 0(src)
addi src, src, 1
addi dst, dst, 1
subi len, len, 1
stb r8, -1(dst)
bne len, zero, .L_mc_loop1
.L_mc_done:
ret
#undef dst
#undef src
#undef len
.global memcpy
.type memcpy, @function
.size memcpy, . - memcpy
#define dst r4
#define val r5
#define len r6
memset:
/* Store return value right away, per API */
mov r2, dst
/* Check for small blocks; fall back to bytewise. */
movi r3, 8
bltu len, r3, .L_ms_test1
/* Replicate the byte across the word. */
andi val, val, 0xff
slli at, val, 8
or val, val, at
slli at, val, 16
or val, val, at
/* Check for destination alignment; realign if needed. */
andi at, dst, 3
bne at, zero, .L_ms_align
/* Set blocks of 8. */
.L_ms_loop8:
stw val, 0(dst)
stw val, 4(dst)
addi dst, dst, 8
subi len, len, 8
bgeu len, r3, .L_ms_loop8
/* Set final aligned block of 4. */
.L_ms_test4:
movi at, 4
bltu len, at, .L_ms_test1
stw r8, 0(dst)
addi dst, dst, 4
subi len, len, 4
stw r8, -4(dst)
/* Set single bytes to finish. */
.L_ms_test1:
beq len, zero, .L_ms_done
.L_ms_loop1:
stb r8, 0(dst)
addi dst, dst, 1
subi len, len, 1
bne len, zero, .L_ms_loop1
.L_ms_done:
ret
/* Realign for a large block, len >= 8. */
.L_ms_align:
andi at, dst, 1
beq at, zero, 2f
stb val, 0(dst)
addi dst, dst, 1
subi len, len, 1
2: andi at, dst, 2
beq at, zero, 4f
sth val, 0(dst)
addi dst, dst, 2
subi len, len, 2
4: bgeu len, r3, .L_ms_loop8
br .L_ms_test4
#undef dst
#undef val
#undef len
.global memset
.type memset, @function
.size memset, . - memset
/*
* void __sys_outc(char c);
*/
__sys_outc:
subi sp, sp, 16
stb r4, 0(sp) /* buffer[0] = c */
movi at, 1
stw at, 4(sp) /* STDOUT_FILENO */
stw sp, 8(sp) /* buffer */
stw at, 12(sp) /* len */
movi r4, HOSTED_WRITE
addi r5, sp, 4
semihosting_call
addi sp, sp, 16
ret
.global __sys_outc
.type __sys_outc, @function
.size __sys_outc, . - __sys_outc