root/exec/loader-mips64el.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         .set noreorder                  # delay slots managed by hand
    21         .set noat                       # no assembler macros
    22         .section .text
    23         .global __start
    24 __start:
    25 dnl     li      $v0, 5034               # SYS_nanosleep
    26 dnl     dla     $a0, .timespec          # rqtp
    27 dnl     li      $a1, 0                  # rmtp
    28 dnl     syscall                         # syscall
    29         ld      $s2, ($sp)              # original stack pointer
    30         DADDI3( $s0, $sp, 16)           # start of load area
    31         DADDI2( $sp, -16)               # primary fd, secondary fd
    32         li      $t0, -1                 # secondary fd
    33         sd      $t0, 8($sp)             # initialize secondary fd
    34 .next_action:
    35         ld      $s1, ($s0)              # action number
    36         andi    $t0, $s1, 15            # t0 = action number & 15
    37         beqz    $t0, .open_file         # open file?
    38         nop                             # delay slot
    39         DADDI2( $t0, -3)                # t0 -= 3
    40         beqz    $t0, .rest_of_exec      # jump to code
    41         nop                             # delay slot
    42         li      $t1, 1
    43         beq     $t0, $t1, .do_mmap_anon # anonymous mmap?
    44         nop                             # delay slot
    45 .do_mmap:
    46         ld      $t0, 8($s0)             # vm address
    47         ld      $t1, 16($s0)            # file_offset
    48         ld      $t2, 24($s0)            # protection
    49         ld      $t3, 32($s0)            # length
    50         ld      $v0, 40($s0)            # flags
    51         ld      $v1, ($sp)              # primary fd
    52         andi    $s3, $s1, 16            # s1 & 16?
    53         beqz    $s3, .do_mmap_1         # secondary fd?
    54         nop                             # delay slot
    55         ld      $v1, 8($sp)             # secondary fd
    56 .do_mmap_1:
    57         move    $a0, $t0                # syscall arg
    58         move    $a1, $t3                # syscall arg
    59         move    $a2, $t2                # syscall arg
    60         move    $a3, $v0                # syscall arg
    61         move    $a4, $v1                # syscall arg
    62         move    $a5, $t1                # syscall arg
    63         li      $v0, 5009               # SYS_mmap
    64         syscall                         # syscall
    65         bne     $a3, $zero, .perror     # perror?
    66         nop                             # delay slot
    67         ld      $t1, 48($s0)            # clear
    68         dadd    $t0, $a0, $a1           # t0 = end of mapping
    69         dsub    $t1, $t0, $t1           # t1 = t0 - clear
    70 .align:
    71         beq     $t0, $t1, .continue     # already finished
    72         nop                             # delay slot
    73         andi    $t2, $t1, 7             # t1 & 7?
    74         bnez    $t2, .filld             # start filling longs
    75         nop                             # delay slot
    76 .filld:
    77         dsub    $t2, $t0, $t1           # t2 = t0 - t1
    78         sltiu   $t2, $t2, 64            # t2 < 64?
    79         bne     $t2, $zero, .fillb      # fill bytes
    80         nop                             # delay slot
    81         sd      $zero, ($t1)            # zero doubleword
    82         DADDI2( $t1, 8)                 # next doubleword
    83         sd      $zero, ($t1)            # zero doubleword
    84         DADDI2( $t1, 8)                 # next doubleword
    85         sd      $zero, ($t1)            # zero doubleword
    86         DADDI2( $t1, 8)                 # next doubleword
    87         sd      $zero, ($t1)            # zero doubleword
    88         DADDI2( $t1, 8)                 # next doubleword
    89         sd      $zero, ($t1)            # zero doubleword
    90         DADDI2( $t1, 8)                 # next doubleword
    91         sd      $zero, ($t1)            # zero doubleword
    92         DADDI2( $t1, 8)                 # next doubleword
    93         sd      $zero, ($t1)            # zero doubleword
    94         DADDI2( $t1, 8)                 # next doubleword
    95         sd      $zero, ($t1)            # zero doubleword
    96         DADDI2( $t1, 8)                 # next doubleword
    97         j       .filld                  # fill either doubleword 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         DADDI2( $t1, 1)                 # t1++
   104 .continue:
   105         DADDI2( $s0, 56)                # s0 = next action
   106         j       .next_action            # next action
   107         nop                             # delay slot
   108 .do_mmap_anon:
   109         ld      $t0, 8($s0)             # vm address
   110         ld      $t1, 16($s0)            # file_offset
   111         ld      $t2, 24($s0)            # protection
   112         ld      $t3, 32($s0)            # length
   113         ld      $v0, 40($s0)            # flags
   114         li      $v1, -1                 # fd
   115         j       .do_mmap_1              # do mmap
   116         nop                             # branch delay slot
   117 .open_file:
   118         li      $v0, 5002               # SYS_open
   119         DADDI3( $a0, $s0, 8)            # start of name
   120         move    $a1, $zero              # flags = O_RDONLY
   121         move    $a2, $zero              # mode = 0
   122         syscall                         # syscall
   123         bne     $a3, $zero, .perror     # perror
   124         nop                             # delay slot
   125         DADDI2( $s0, 8)                 # start of string
   126         move    $t3, $s0                # t3 = s0
   127 .nextc:
   128         lb      $t0, ($s0)              # load byte
   129         DADDI2( $s0, 1)                 # s0++
   130         li      $t1, 47                 # directory separator `/'
   131         bne     $t0, $t1, .nextc1       # is separator char?
   132         nop                             # delay slot
   133         move    $t3, $s0                # t3 = char past separator
   134 .nextc1:
   135         bnez    $t0, .nextc             # next character?
   136         nop                             # delay slot
   137         DADDI2( $s0, 7)                 # adjust for round
   138         li      $t2, -8                 # t2 = -8
   139         and     $s0, $s0, $t2           # mask for round
   140         andi    $t0, $s1, 16            # t1 = s1 & 16
   141         move    $t1, $sp                # address of primary fd
   142         beqz    $t0, .primary           # primary fd?
   143         nop                             # delay slot
   144         DADDI2( $t1, 8)                 # address of secondary fd
   145         sd      $v0, ($t1)              # store fd
   146         j       .next_action            # next action
   147         nop                             # delay slot
   148 .primary:
   149         sd      $v0, ($t1)              # store fd
   150         li      $v0, 5153               # SYS_prctl
   151         li      $a0, 15                 # PR_SET_NAME
   152         move    $a1, $t3                # char past separator
   153         move    $a2, $zero              # a2
   154         move    $a3, $zero              # a3
   155         move    $a4, $zero              # a4
   156         move    $a5, $zero              # a5
   157         syscall                         # syscall
   158         j       .next_action            # next action
   159         nop                             # delay slot
   160 .perror:
   161         move    $a0, $v0                # errno
   162         li      $v0, 5058               # SYS_exit
   163         syscall                         # syscall
   164 .rest_of_exec:
   165         move    $s1, $s2                # original SP
   166         ld      $t0, ($s1)              # argc
   167         dsll    $t0, $t0, 3             # argc *= 8
   168         DADDI2( $t0, 16)                # argc += 16
   169         dadd    $s1, $s1, $t0           # s1 = start of envp
   170 .skipenv:
   171         ld      $t0, ($s1)              # t0 = *s1
   172         DADDI2( $s1, 8)                 # s1++
   173         bne     $t0, $zero, .skipenv    # skip again
   174         nop                             # delay slot
   175         dla     $t3, .auxvtab           # address of auxv table
   176 .one_auxv:
   177         ld      $t0, ($s1)              # t0 = auxv type
   178         li      $t1, 10                 # t1 = 10
   179         beqz    $t0, .finish            # is AT_IGNORE?
   180         nop                             # delay slot
   181         sltu    $t1, $t0, $t1           # t1 = t0 < num offsets
   182         beqz    $t1, .next              # next auxv
   183         nop                             # delay slot
   184         dsll    $t1, $t0, 2             # t1 = t0 * 4
   185         dadd    $t1, $t3, $t1           # t1 = .auxvtab + t1
   186         lw      $t2, ($t1)              # t2 = *t1
   187         beqz    $t2, .next              # skip auxv
   188         nop                             # delay slot
   189         dadd    $t2, $s0, $t2           # t2 = s0 + t2
   190         ld      $t2, ($t2)              # t2 = *t2
   191         sd      $t2, 8($s1)             # set auxv value
   192 .next:
   193         DADDI2( $s1, 16)                # next auxv
   194         j       .one_auxv               # next auxv
   195         nop                             # delay slot
   196 .finish:
   197         ld      $t0, 8($sp)             # secondary fd
   198         li      $t1, -1                 # t1 = -1
   199         ld      $s1, ($sp)              # s1 = primary fd
   200         li      $v0, 5003               # SYS_close
   201         beq     $t0, $t2, .finish1      # secondary fd set?
   202         nop                             # delay slot
   203         move    $a0, $t0                # secondary fd
   204         syscall                         # syscall
   205         li      $v0, 5003               # SYS_close
   206 .finish1:
   207         move    $a0, $s1                # primary fd
   208         syscall                         # syscall
   209 .jump:
   210         move    $v0, $zero              # rtld_fini
   211         ld      $t0, 8($s0)             # entry
   212         move    $sp, $s2                # restore stack pointer, delay slot
   213         jr      $t0                     # enter
   214         nop                             # delay slot
   215 
   216 .auxvtab:
   217         .long   0                       # 0
   218         .long   0                       # 1
   219         .long   0                       # 2
   220         .long   40                      # 3 AT_PHDR
   221         .long   24                      # 4 AT_PHENT
   222         .long   32                      # 5 AT_PHNUM
   223         .long   0                       # 6
   224         .long   48                      # 7 AT_BASE
   225         .long   0                       # 8
   226         .long   16                      # 9 AT_ENTRY
   227 
   228 .timespec:
   229         .quad   10
   230         .quad   10
   231 
   232 # Local Variables:
   233 # asm-comment-char: 35
   234 # End:

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