root/exec/loader-mipsel.s

/* [<][>][^][v][top][bottom][index][help] */
     1 # Copyright (C) 2023 Free Software Foundation, Inc.
     2 #
     3 # This file is part of GNU Emacs.
     4 #
     5 # GNU Emacs is free software: you can redistribute it and/or modify
     6 # it under the terms of the GNU General Public License as published
     7 # by the Free Software Foundation, either version 3 of the License,
     8 # or (at your option) any later version.
     9 #
    10 # GNU Emacs is distributed in the hope that it will be useful, but
    11 # WITHOUT ANY WARRANTY; without even the implied warranty of
    12 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
    13 # General Public License for more details.
    14 #
    15 # You should have received a copy of the GNU General Public License
    16 # along with GNU Emacs.  If not, see <https://www.gnu.org/licenses/>.
    17 
    18 include(`config-mips.m4')
    19 
    20 # Make sure not to use t4 through t7, in order to maintain portability
    21 # with N32 ABI systems.
    22 
    23         .set noreorder                  # delay slots managed by hand
    24         .section .text
    25         .global __start
    26 __start:
    27 dnl     li      $v0, SYSCALL_nanosleep  # SYS_nanosleep
    28 dnl     la      $a0, .timespec          # rqtp
    29 dnl     li      $a1, 0                  # rmtp
    30 dnl     syscall                         # syscall
    31         lw      $s6, ($sp)              # original stack pointer
    32         addi    $s0, $sp, 8             # start of load area
    33         addi    $sp, -8                 # primary fd, secondary fd
    34         li      $t0, -1                 # secondary fd
    35         sw      $t0, 4($sp)             # initialize secondary fd
    36 .next_action:
    37         lw      $s2, ($s0)              # action number
    38         nop                             # delay slot
    39         andi    $t0, $s2, 15            # t0 = s2 & 15
    40         beqz    $t0, .open_file         # open file?
    41         li      $t1, 3                  # t1 = 3, delay slot
    42         beq     $t0, $t1, .rest_of_exec # jump to code
    43         li      $t1, 4                  # t1 = 4, delay slot
    44         beq     $t0, $t1, .do_mmap_anon # anonymous mmap
    45 .do_mmap:
    46         lw      $a0, 4($s0)             # vm_address, delay slot
    47         lw      $v1, 8($s0)             # file_offset
    48         lw      $a2, 12($s0)            # protection
    49         lw      $a1, 16($s0)            # length
    50         lw      $a3, 20($s0)            # flags
    51         lw      $v0, ($sp)              # primary fd
    52         andi    $t1, $s2, 16            # t1 = s2 & 16
    53         beqz    $t1, .do_mmap_1         # secondary fd?
    54         nop                             # delay slot
    55         lw      $v0, 4($sp)             # secondary fd
    56         nop                             # delay slot
    57 .do_mmap_1:
    58 SYSCALL(`$v0',`$v1',`$zero',`$zero')    # syscall args
    59         li      $v0, SYSCALL_mmap       # SYS_mmap
    60         syscall                         # syscall
    61         bne     $a3, $zero, .perror     # perror
    62 RESTORE()                               # delay slot, restore sp
    63         lw      $s5, 24($s0)            # clear
    64         add     $t0, $a0, $a1           # t0 = length + vm_address, delay slot
    65         sub     $t1, $t0, $s5           # t1 = t0 - clear
    66 .align:
    67         beq     $t0, $t1, .continue     # already finished?
    68         nop                             # delay slot
    69         andi    $t2, $t1, 3             # t1 & 3?
    70         bnez    $t2, .fillw             # start filling longs
    71         nop                             # delay slot
    72         sb      $zero, ($t1)            # clear byte
    73         addi    $t1, $t1, 1             # t1++
    74         j       .align                  # continue
    75         nop                             # delay slot
    76 .fillw:
    77         sub     $t2, $t0, $t1           # t2 = t0 - t1
    78         sltiu   $t2, $t2, 32            # r2 < 32?
    79         bne     $t2, $zero, .fillb      # fill bytes
    80         nop                             # delay slot
    81         sw      $zero, ($t1)            # zero word
    82         addi    $t1, $t1, 4             # next word
    83         sw      $zero, ($t1)            # zero word
    84         addi    $t1, $t1, 4             # next word
    85         sw      $zero, ($t1)            # zero word
    86         addi    $t1, $t1, 4             # next word
    87         sw      $zero, ($t1)            # zero word
    88         addi    $t1, $t1, 4             # next word
    89         sw      $zero, ($t1)            # zero word
    90         addi    $t1, $t1, 4             # next word
    91         sw      $zero, ($t1)            # zero word
    92         addi    $t1, $t1, 4             # next word
    93         sw      $zero, ($t1)            # zero word
    94         addi    $t1, $t1, 4             # next word
    95         sw      $zero, ($t1)            # zero word
    96         addi    $t1, $t1, 4             # next word
    97         j       .fillw                  # fill either word or byte
    98         nop                             # delay slot
    99 .fillb:
   100         beq     $t0, $t1, .continue     # already finished?
   101         nop                             # delay slot
   102         sb      $zero, ($t1)            # clear byte
   103         addi    $t1, $t1, 1             # t1++
   104 .continue:
   105         addi    $s0, $s0, 28            # s0 = next action
   106         j       .next_action            # next action
   107         nop                             # delay slot
   108 .do_mmap_anon:
   109         lw      $v1, 8($s0)             # file_offset
   110         lw      $a2, 12($s0)            # protection
   111         lw      $a1, 16($s0)            # length
   112         lw      $a3, 20($s0)            # flags
   113         li      $t4, -1                 # fd
   114         j       .do_mmap_1              # do mmap
   115         nop                             # delay slot
   116 .open_file:
   117         li      $v0, SYSCALL_open       # SYS_open
   118         addi    $a0, $s0, 4             # start of name
   119         move    $a1, $zero              # flags = O_RDONLY
   120         move    $a2, $zero              # mode = 0
   121         syscall                         # syscall
   122         bne     $a3, $zero, .perror     # perror
   123         addi    $s0, $s0, 4             # start of string, delay slot
   124         move    $t3, $s0                # t3 = char past separator
   125 .nextc:
   126         lb      $t0, ($s0)              # load byte
   127         addi    $s0, $s0, 1             # s0++
   128         li      $t1, 47                 # directory separator `/'
   129         bne     $t0, $t1, .nextc1       # is separator char?
   130         nop                             # delay slot
   131         move    $t3, $s0                # t3 = char past separator
   132 .nextc1:
   133         bnez    $t0, .nextc             # next character?
   134         nop                             # delay slot
   135         addi    $s0, $s0, 3             # adjust for round
   136         li      $t2, -4                 # t2 = -4
   137         and     $s0, $s0, $t2           # mask for round
   138         andi    $t0, $s2, 16            # t1 = s2 & 16
   139         beqz    $t0, .primary           # primary fd?
   140         move    $t0, $sp                # address of primary fd, delay slot
   141         addi    $t0, $t0, 4             # address of secondary fd
   142         j       .next_action            # next action
   143 .primary:
   144         sw      $v0, ($t0)              # store fd, delay slot
   145         li      $v0, SYSCALL_prctl      # SYS_prctl
   146         li      $a0, 15                 # PR_SET_NAME
   147         move    $a1, $t3                # name
   148         move    $a2, $zero              # arg1
   149         move    $a3, $zero              # arg2
   150 SYSCALL(`$a2',`$a2',`$a2',`$a2')        # syscall args
   151         syscall                         # syscall
   152 RESTORE()                               # restore sp
   153         j       .next_action            # next action
   154         nop                             # delay slot
   155 .perror:
   156         move    $a0, $v0                # errno
   157         li      $v0, SYSCALL_exit       # SYS_exit
   158         syscall                         # syscall
   159 .rest_of_exec:
   160         move    $s1, $s6                # s1 = original SP
   161         lw      $t0, ($s1)              # argc
   162         nop                             # delay slot
   163         sll     $t0, $t0, 2             # argc *= 4
   164         addi    $t0, $t0, 8             # argc += 8
   165         add     $s1, $s1, $t0           # s1 = start of envp
   166 .skipenv:
   167         lw      $t0, ($s1)              # t0 = *s1
   168         addi    $s1, $s1, 4             # s1++
   169         bne     $t0, $zero, .skipenv    # skip again
   170         nop                             # delay slot
   171         la      $s2, .auxvtab           # address of auxv table
   172 .one_auxv:
   173         lw      $t0, ($s1)              # t0 = auxv type
   174         li      $t1, 10                 # t1 = 10, delay slot
   175         beqz    $t0, .finish            # is AT_IGNORE?
   176         sltu    $t1, $t0, $t1           # t1 = t0 < num offsets, delay slot
   177         beq     $t1, $zero, .next       # next auxv
   178         sll     $t1, $t0, 2             # t1 = t0 * 4, delay slot
   179         add     $t1, $s2, $t1           # t1 = .auxvtab + t1
   180         lw      $t2, ($t1)              # t2 = *t1
   181         nop                             # delay slot
   182         beqz    $t2, .next              # skip auxv
   183         add     $t2, $s0, $t2           # t2 = s0 + t2
   184         lw      $t2, ($t2)              # t2 = *t2
   185         nop                             # delay slot
   186         sw      $t2, 4($s1)             # set auxv value
   187 .next:
   188         addi    $s1, $s1, 8             # next auxv
   189         j       .one_auxv               # next auxv
   190         nop                             # delay slot
   191 .finish:
   192         lw      $t0, 4($sp)             # secondary fd
   193         lw      $s1, ($sp)              # primary fd, delay slot, preserved
   194         li      $t2, -1                 # immediate -1
   195         beq     $t0, $t2, .finish1      # secondary fd set?
   196         li      $v0, SYSCALL_close      # SYS_close, delay slot
   197         move    $a0, $t0                # fd
   198         syscall                         # syscall
   199         li      $v0, SYSCALL_close      # SYS_close
   200 .finish1:
   201         move    $a0, $s1                # primary fd
   202         syscall                         # syscall
   203         li      $v0, SYSCALL_prctl      # SYS_prctl
   204         li      $a0, 45                 # PR_SET_FP_MODE
   205         lw      $a1, 28($s0)            # fpu_mode
   206         move    $a2, $zero              # arg3
   207         move    $a3, $zero              # arg4
   208 SYSCALL(`$a2',`$a2',`$a2',`$a2')        # syscall args
   209         syscall                         # syscall
   210 RESTORE()                               # restore sp
   211 .jump:
   212         move    $v0, $zero              # rtld_fini
   213         lw      $t0, 4($s0)             # entry
   214         move    $sp, $s6                # restore stack pointer, delay slot
   215         jr      $t0                     # enter
   216         nop                             # delay slot
   217 
   218 .auxvtab:
   219         .long   0                       # 0
   220         .long   0                       # 1
   221         .long   0                       # 2
   222         .long   20                      # 3 AT_PHDR
   223         .long   12                      # 4 AT_PHENT
   224         .long   16                      # 5 AT_PHNUM
   225         .long   0                       # 6
   226         .long   24                      # 7 AT_BASE
   227         .long   0                       # 8
   228         .long   8                       # 9 AT_ENTRY
   229 
   230 .timespec:
   231         .long   10
   232         .long   10
   233 
   234 # Local Variables:
   235 # asm-comment-char: 35
   236 # End:

/* [<][>][^][v][top][bottom][index][help] */