1/* 2 * Minimal Nios2 system boot code. 3 * 4 * Copyright Linaro Ltd 2022 5 * SPDX-License-Identifier: GPL-2.0-or-later 6 */ 7 8#include "semicall.h" 9 10 .text 11 .set noat 12 13_start: 14 /* Linker script defines stack at end of ram. */ 15 movia sp, __stack 16 17 /* Install trampoline to _fast_tlb_miss at hardcoded vector. */ 18 movia r4, 0xc0000100 19 movia r5, _ftm_tramp 20 movi r6, .L__ftm_end - _ftm_tramp 21 call memcpy 22 23 /* Zero the bss to satisfy C. */ 24 movia r4, __bss_start 25 movia r6, __bss_end 26 sub r6, r6, r4 27 movi r5, 0 28 call memset 29 30 /* Test! */ 31 call main 32 33 /* Exit with main's return value. */ 34 movi r4, HOSTED_EXIT 35 mov r5, r2 36 semihosting_call 37 38 .globl _start 39 .type _start, @function 40 .size _start, . - _start 41 42_ftm_tramp: 43 movia et, _fast_tlb_miss 44 jmp et 45.L__ftm_end: 46 47 .type _ftm_tramp, @function 48 .size _ftm_tramp, . - _ftm_tramp 49 50#define dst r4 51#define src r5 52#define len r6 53 54memcpy: 55 /* Store return value right away, per API */ 56 mov r2, dst 57 58 /* Check for both dst and src aligned. */ 59 or at, dst, src 60 andi at, at, 3 61 bne at, zero, .L_mc_test1 62 63 /* Copy blocks of 8. */ 64 65 movi at, 8 66 bltu len, at, .L_mc_test4 67 68.L_mc_loop8: 69 ldw r8, 0(src) 70 ldw r9, 4(src) 71 addi src, src, 8 72 addi dst, dst, 8 73 subi len, len, 8 74 stw r8, -8(dst) 75 stw r9, -4(dst) 76 bgeu len, at, .L_mc_loop8 77 78 /* Copy final aligned block of 4. */ 79 80.L_mc_test4: 81 movi at, 4 82 bltu len, at, .L_mc_test1 83 84 ldw r8, 0(src) 85 addi src, src, 4 86 addi dst, dst, 4 87 subi len, len, 4 88 stw r8, -4(dst) 89 90 /* Copy single bytes to finish. */ 91 92.L_mc_test1: 93 beq len, zero, .L_mc_done 94 95.L_mc_loop1: 96 ldb r8, 0(src) 97 addi src, src, 1 98 addi dst, dst, 1 99 subi len, len, 1 100 stb r8, -1(dst) 101 bne len, zero, .L_mc_loop1 102 103.L_mc_done: 104 ret 105 106#undef dst 107#undef src 108#undef len 109 110 .global memcpy 111 .type memcpy, @function 112 .size memcpy, . - memcpy 113 114#define dst r4 115#define val r5 116#define len r6 117 118memset: 119 /* Store return value right away, per API */ 120 mov r2, dst 121 122 /* Check for small blocks; fall back to bytewise. */ 123 movi r3, 8 124 bltu len, r3, .L_ms_test1 125 126 /* Replicate the byte across the word. */ 127 andi val, val, 0xff 128 slli at, val, 8 129 or val, val, at 130 slli at, val, 16 131 or val, val, at 132 133 /* Check for destination alignment; realign if needed. */ 134 andi at, dst, 3 135 bne at, zero, .L_ms_align 136 137 /* Set blocks of 8. */ 138 139.L_ms_loop8: 140 stw val, 0(dst) 141 stw val, 4(dst) 142 addi dst, dst, 8 143 subi len, len, 8 144 bgeu len, r3, .L_ms_loop8 145 146 /* Set final aligned block of 4. */ 147 148.L_ms_test4: 149 movi at, 4 150 bltu len, at, .L_ms_test1 151 152 stw r8, 0(dst) 153 addi dst, dst, 4 154 subi len, len, 4 155 stw r8, -4(dst) 156 157 /* Set single bytes to finish. */ 158 159.L_ms_test1: 160 beq len, zero, .L_ms_done 161 162.L_ms_loop1: 163 stb r8, 0(dst) 164 addi dst, dst, 1 165 subi len, len, 1 166 bne len, zero, .L_ms_loop1 167 168.L_ms_done: 169 ret 170 171 /* Realign for a large block, len >= 8. */ 172.L_ms_align: 173 andi at, dst, 1 174 beq at, zero, 2f 175 176 stb val, 0(dst) 177 addi dst, dst, 1 178 subi len, len, 1 179 1802: andi at, dst, 2 181 beq at, zero, 4f 182 183 sth val, 0(dst) 184 addi dst, dst, 2 185 subi len, len, 2 186 1874: bgeu len, r3, .L_ms_loop8 188 br .L_ms_test4 189 190#undef dst 191#undef val 192#undef len 193 194 .global memset 195 .type memset, @function 196 .size memset, . - memset 197 198/* 199 * void __sys_outc(char c); 200 */ 201__sys_outc: 202 subi sp, sp, 16 203 stb r4, 0(sp) /* buffer[0] = c */ 204 movi at, 1 205 stw at, 4(sp) /* STDOUT_FILENO */ 206 stw sp, 8(sp) /* buffer */ 207 stw at, 12(sp) /* len */ 208 209 movi r4, HOSTED_WRITE 210 addi r5, sp, 4 211 semihosting_call 212 213 addi sp, sp, 16 214 ret 215 216 .global __sys_outc 217 .type __sys_outc, @function 218 .size __sys_outc, . - __sys_outc 219