qemu/tests/tcg/nios2/boot.S
<<
>>
Prefs
   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