| /* |
| * 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 |