Remove building with NOCRYPTO option
[minix.git] / libexec / ld.elf_so / arch / vax / rtld_start.S
blob2979567a73cff8babdd6e19d7535510b7720d2a4
1 /*      $NetBSD: rtld_start.S,v 1.24 2014/08/17 16:57:37 matt Exp $     */
3 /*
4  * Copyright 1996 Matt Thomas <matt@3am-software.com>
5  * Portions copyright 2002, 2003 Charles M. Hannum <root@ihack.net>
6  * All rights reserved.
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions
10  * are met:
11  * 1. Redistributions of source code must retain the above copyright
12  *    notice, this list of conditions and the following disclaimer.
13  * 2. Redistributions in binary form must reproduce the above copyright
14  *    notice, this list of conditions and the following disclaimer in the
15  *    documentation and/or other materials provided with the distribution.
16  * 3. The name of the author may not be used to endorse or promote products
17  *    derived from this software without specific prior written permission.
18  *
19  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
20  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
21  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
22  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
23  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
24  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
28  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29  */
31 #include <machine/asm.h>
33 /* R9 contains the address of PS_STRINGS and since its caller saved,
34  * we can just use it.  R6 has a backup copy of the stack pointer which
35  * we can use as well.
36  */
37 ENTRY(_rtld_start, 0)
38         /* Allocate space on the stack for the cleanup and obj_main
39          * entries that _rtld() will provide for us.
40          */
41         clrl    %fp
42         subl2   $8,%sp
44         movab   _DYNAMIC,%r0
45         subl3   _GLOBAL_OFFSET_TABLE_,%r0,%r10
46         pushl   %r10            /* relocbase */
47         pushl   %r0             /* &_DYNAMIC */
48         calls   $2,_rtld_relocate_nonplt_self
50         pushl   %r10            /* relocbase */
51         pushal  4(%sp)          /* sp */
52         calls   $2,_rtld        /* entry = _rtld(sp, relocbase) */
54         movq    (%sp)+,%r7      /* grab cleanup and obj_main into %r7/%r8 */
55         jmp     2(%r0)          /* jump to entry point + 2 */
56 END(_rtld_start)
59  * Lazy binding entry point, called via PLT via JMP into pltgot[1].
60  * SP+4: address to relocation offset
61  * SP+0: obj entry points
62  */
63 ALTENTRY(_rtld_bind_start)
64         pushl   %r1             /* need to preserve r1 */
65         movq    -8(%fp),%r0     /* get addresses of plt.got & reloc index */
66         pushl   (%r1)           /* push relocation offset */
67         pushl   %r0             /* push address of obj entry */
68         calls   $2,_rtld_bind
70         /*
71          * This code checks to see if we got called via a call{s,g} $n,*pcrel32
72          * This is by far the most common case (a call indirectly via the PLT).
73          */
74         subl3   $7,16(%fp),%r1  /* return address */
75         bicb3   $1,(%r1),%r2    /* fetch opcode of instruction */
76         cmpb    $0xfa,%r2       /* is it calls/callg */
77         jneq    20f             /*   no it isn't */
78         cmpb    $0xff,2(%r1)    /* and deferred 32-bit PC displacement? */
79         jneq    20f             /*   no it isn't */
81         /*
82          * This makes sure the longword with the PLT's address has been updated
83          * to point to the routine's address.  If it hasn't, then returning
84          * would put us in an infinite loop.  Instead we punt and fake up a
85          * callframe.
86          */
87         movl    3(%r1),%r3      /* get displacement */
88         addl2   16(%fp),%r3     /* add ending location */
89         cmpl    (%r3),%r0       /* does it contain the routine address? */
90 #ifdef DEBUG
91         jneq    30f             /*   no it doesn't, die */
92 #else
93         jneq    20f             /*   no it doesn't, go fake a new callframe */
94 #endif
96 11:     movl    %r1,16(%fp)     /* backup to the calls/callg */
97         jbc     $29,4(%fp),12f  /* skip if this was a callg */
98         clrl    (%ap)           /* clear argument count */
99 12:     movl    (%sp)+,%r1      /* restore r1 */
100         ret                     /* return and redo the call */
102 #if 1
104         /*
105          * Since the calling standard says only r6-r11 should be saved,
106          * that simplies things for us.  That means we can use r0-r5 as
107          * temporaries without worrying about preserving them.  This means
108          * can hold the current fixed callframe in r2-r5 as we build the
109          * callframe without having to worry about overwriting the existing
110          * callframe.
111          */
112         extzv   $0,$12,(%r0),%r1/* get routine's save mask */
113         bitw    $0x3f,%r1       /* does the routine use r0-r5? */
114         jneq    30f             /*   yes, that sucks */
115         jbc     $29,4(%fp),27f  /* handle callg */
116         movq    4(%fp),%r2      /* fetch callframe status & saved AP */
117         movq    12(%fp),%r4     /* fetch callframe saved FP & PC */
118         insv    %r1,$16,$12,%r2 /* update save mask */
119         movl    (%sp)+,%fp      /* use fp to keep saved r1 */
120         movl    %ap,%sp         /* reset stack to top of callframe */
121 22:     pushr   %r1             /* push registers */
122         movq    %r4,-(%sp)      /* push callframe saved FP & PC */
123         movq    %r2,-(%sp)      /* push callframe status & saved AP */
124         pushl   $0              /* push condition handler */
125         movl    %fp,%r1         /* restore r1 */
126         movl    %sp,%fp         /* sp == fp now */
127 #if 1
128         jmp     2(%r0)          /* jump past entry mask */
129 #else
130         /*
131          * More correct but IV/DV are never set so ignore doing this for now.
132          */
133         movpsl  -(%sp)          /* push PSL */
134         clrb    (%sp)           /* clear user flags */
135         jbc     $14,(%r0),24f   /* IV need to be set? */
136         bisb2   $0x20,(%sp)     /*   yes, set it. */
137 24:     jbc     $15,(%r0),25f   /* DV need to be set? */
138         bisb2   $0x80,(%sp)     /*   yes, set it. */
139 25:     pushab  2(%r0)          /* push address of first instruction */
140         rei                     /* and go to it (updating PSW) */
141 #endif
143         /*
144          * Count how many registers are being used for callg.
145          */
146 27:     movl    $0x32212110,%r3 /* bit counts */
147         extzv   $6,$3,%r1,%r2   /* extract bits 6-8 */
148         ashl    $2,%r2,%r2      /* shift by 2 */
149         extzv   %r2,$4,%r3,%r4  /* extract count */
150         extzv   $9,$3,%r1,%r2   /* extract bits 9-11 */
151         ashl    $2,%r2,%r2      /* shift by 2 */
152         extzv   %r2,$4,%r3,%r5  /* extract count */
153         movq    4(%fp),%r2      /* fetch callframe status & saved AP */
154         insv    %r1,$16,$12,%r2 /* update save mask */
155         addl3   %r4,%r5,%r1     /* add counts and discard them */
156         movq    12(%fp),%r4     /* fetch callframe saved FP & PC */
157         moval   20(%fp)[%r1],%sp/* pop callframe */
158         extzv   $16,$12,%r2,%r1 /* get save mask back */
159         jbr     22b             /* now build the new callframe */
161 30:     
162         calls   $0,_C_LABEL(_rtld_die)
163 #else
164         /*
165          * Check to see if called via call? $n,w^off(reg)
166          */
167 20:     addl2   $2,%r1          /* 16-bit displacement */
168         bicb3   $1,(%r1),%r2    /* fetch opcode of instruction */
169         cmpb    $0xfa,%r2       /* is it calls/callg */
170         jneq    30f             /*   no it isn't */
171         bicb3   $0x1f,2(%r1),%r3/* extract addressing mode */
172         cmpb    $0xc0,%r3       /* 16-bit displacement? */
173         jeql    11b             /*   yes, redo the call */
174         halt
176         /*
177          * Check to see if called via call? $n,b^off(reg)
178          */
179 30:     incl    %r1             /* 8-bit displacement */
180         bicb3   $1,(%r1),%r2    /* fetch opcode of instruction */
181         cmpb    $0xfa,%r2       /* is it calls/callg */
182         jneq    40f             /*   no it isn't */
183         bicb3   $0x1f,2(%r1),%r3/* extract addressing mode */
184         cmpb    $0xa0,%r3       /* 8-bit displacement? */
185         jeql    11b             /*   yes, redo the call */
186         halt
188         /*
189          * Check to see if called via call? $n,(reg)
190          */
191 40:     incl    %r1             /* no displacement */
192         bicb3   $1,(%r1),%r2    /* fetch opcode of instruction */
193         cmpb    $0xfa,%r2       /* is it calls/callg */
194         jeql    41f             /*   yes it is */
195         halt                    /*   no, die die die */
196 41:     bicb3   $0x0f,2(%r1),%r2/* extract addressing mode */
197         bicb3   $0xf0,2(%r1),%r3/* extract register */
198         extzv   $0,$12,6(%fp),%r4/* extract saved mask */
199         cmpb    $0x60,%r2       /* register deferred? */
200         jeql    42f             /*   yes, deal with it */
201         cmpb    $0x90,%r2       /* autoincrement deferred? */
202         jeql    70f             /*   yes, deal with it */
203         halt                    /*   no, die die die */
205 42:     cmpw    %r4,$0xffc      /* did we save r2-r11? */
206         jneq    50f             /*   no, deal with it */
207         jbc     %r3,%r4,43f     /* is the register in the saved mask? */
209         /*
210          * We saved r2-r11, so it's easy to replace the saved register with
211          * the right value by indexing into saved register (offset by 8).
212          */
213         movl    %r0,(20-8)(%fp)[%r3] /* replace address in saved registers */
214         jbr     11b             /* go back and redo call */
215         /*
216          * Must have been called via r0 or r1 which are saved locally.
217          * So move the routine address in the appropriate slot on the stack.
218          */
219 43:     movl    %r0,(%sp)[%r3]
220         jbr     11b             /* go back and redo call */
222 50:     jbs     %r3,%r4,60f     /* is the register in the saved mask? */
223         jbs     %r3,$0x3f,43b   /* is it r0-r5? */
224         /*
225          * The register used for the call was not saved so we need to move
226          * the new function address into it so the re-call will use the new
227          * address.
228          */
229         pushl   %r0             /* save function address on the stack */
230         ashl    %r5,$1,%r0      /* create a bitmask for the register */
231         popr    %r0             /* pop it off the stack. */
232         jbr     11b             /* and redo the call */
234 60:     clrl    %r2             /* starting offset into saved registers */
235         clrl    %r5             /* start with register 0 */
237 61:     cmpl    %r2,%r3         /* is the register to save? */
238         jneq    62f             /*   no, advance to next */
239         movl    %r0,20(%fp)[%r5]/*   yes, save return address in saved reg */
240         jbr     11b             /*        and return the call */
241 62:     jbc     %r5,%r4,63f     /* is this register saved? */
242         incl    %r5             /*   yes, account for it */
243 63:     incl    %r2             /* increment register number */
244         jbr     61b             /* and loop */
246 70:     cmpb    %r3,$12
247         blss    71f
248         halt
250 71:     cmpw    %r4,$0xffc      /* did we save r2-r11? */
251         jneq    72f             /*   no, deal with it */
252         subl2   $4,(20-8)(%fp)[%r3] /* backup incremented register */
253         jbr     11b             /* and redo the call.
255 72:     jbs     %r3,%r4,80f
256         jbs     %r3,%3f,74f
257         ashl    %r5,$1,%r0      /* create a bitmask for the register */
258         pushr   %r0             /* pop it off the stack. */
259         subl2   $4,(%sp)        /* backup incremented register */
260         popr    %r0             /* pop it off the stack. */
261         jbr     11b             /* and redo the call.
263 73:     subl2   %4,(%sp)[%r3]   /* backup incremented register */
264         jbr     11b             /* and redo the call.
266 80:     clrl    %r2             /* starting offset into saved registers */
267         clrl    %r5             /* start with register 0 */
269 81:     cmpl    %r2,%r3         /* is the register to save? */
270         jneq    82f             /*   no, advance to next */
271         subl    $4,20(%fp)[%r5] /*   yes, backup incremented register */
272         jbr     11b             /*        and return the call */
273 82:     jbc     %r5,%r4,83f     /* is this register saved? */
274         incl    %r5             /*   yes, account for it */
275 83:     incl    %r2             /* increment register number */
276         jbr     81b             /* and loop */
277 #endif
278 END(_rtld_bind_start)