annotate dyncall/dyncall_call_x86_8a.s @ 457:90b1d927912a

- suite_aggrs: make sure random memory used doesn't ever result in NaN fp values (for every possible address), as this messes with result comparison
author Tassilo Philipp
date Fri, 28 Jan 2022 14:11:21 +0100
parents 3e629dc19168
children
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
0
3e629dc19168 initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
1 /*
3e629dc19168 initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
2
3e629dc19168 initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
3 Package: dyncall
3e629dc19168 initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
4 Library: dyncall
3e629dc19168 initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
5 File: dyncall/dyncall_call_x86_8a.s
3e629dc19168 initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
6 Description: All x86 abi call kernel implementations in Plan9's assembler
3e629dc19168 initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
7 License:
3e629dc19168 initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
8
3e629dc19168 initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
9 Copyright (c) 2007-2011 Daniel Adler <dadler@uni-goettingen.de>,
3e629dc19168 initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
10 Tassilo Philipp <tphilipp@potion-studios.com>
3e629dc19168 initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
11
3e629dc19168 initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
12 Permission to use, copy, modify, and distribute this software for any
3e629dc19168 initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
13 purpose with or without fee is hereby granted, provided that the above
3e629dc19168 initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
14 copyright notice and this permission notice appear in all copies.
3e629dc19168 initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
15
3e629dc19168 initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
16 THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
3e629dc19168 initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
17 WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
3e629dc19168 initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
18 MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
3e629dc19168 initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
19 ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
3e629dc19168 initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
20 WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
3e629dc19168 initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
21 ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
3e629dc19168 initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
22 OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
3e629dc19168 initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
23
3e629dc19168 initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
24 */
3e629dc19168 initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
25
3e629dc19168 initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
26
3e629dc19168 initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
27
3e629dc19168 initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
28 /* 64 bit integer return value calls require caller to create space for return
3e629dc19168 initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
29 value, and pass a pointer to it as 1st argument. This main function handles
3e629dc19168 initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
30 all cases (32 and 64 bit integers, as well as floats and doubles), however,
3e629dc19168 initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
31 it has to be called through the 2 corresponding functions at the end of
3e629dc19168 initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
32 this file.
3e629dc19168 initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
33 In order to keep things simple, we basically put the pointer to the
3e629dc19168 initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
34 return value in EDX and call the other assembler code, above. If EDX
3e629dc19168 initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
35 is not null, then the code below will push it to the stack as first
3e629dc19168 initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
36 argument.
3e629dc19168 initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
37 */
3e629dc19168 initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
38
3e629dc19168 initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
39 call_main:
3e629dc19168 initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
40
3e629dc19168 initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
41 /* Since all registers except SP are scratch, and we have a variable
3e629dc19168 initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
42 argument size depending on the function to call, we have to find
3e629dc19168 initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
43 a way to store and restore SP.
3e629dc19168 initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
44 The idea is to replace the return address with a custom one on the
3e629dc19168 initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
45 stack, and to put some logic there, jumping back to the real
3e629dc19168 initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
46 return address. This allows us, to put the SP somewhere next to
3e629dc19168 initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
47 the fake return address on the stack, so that we can get it back
3e629dc19168 initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
48 with a fixed offset (relative to the program counter, in our case).
3e629dc19168 initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
49
3e629dc19168 initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
50 The only real issue with this approach would be a non-executable
3e629dc19168 initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
51 stack. However, Plan9 doesn't support w^x at the time of writing.
3e629dc19168 initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
52 */
3e629dc19168 initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
53
3e629dc19168 initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
54 /* On the stack at this point:
3e629dc19168 initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
55 RETADDR 0(SP)
3e629dc19168 initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
56 FUNPTR 4(SP)
3e629dc19168 initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
57 ARGS 8(SP)
3e629dc19168 initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
58 SIZE 12(SP)
3e629dc19168 initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
59 */
3e629dc19168 initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
60
3e629dc19168 initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
61 MOVL SP, BP /* base pointer for convenience */
3e629dc19168 initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
62 PUSHL SP /* save stack pointer */
3e629dc19168 initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
63
3e629dc19168 initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
64 MOVL 8(BP), SI /* SI = pointer on args */
3e629dc19168 initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
65 MOVL 12(BP), CX /* CX = size of args */
3e629dc19168 initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
66
3e629dc19168 initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
67 SUBL $16, SP /* Make some room for our SP-refetch logic */
3e629dc19168 initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
68 MOVL SP, BX /* Copy address to new, executable stack space to BX */
3e629dc19168 initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
69
3e629dc19168 initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
70 /* This part fills our executable stack space with instructions. We
3e629dc19168 initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
71 need to get the program counter, first, with a little hack. */
3e629dc19168 initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
72 MOVL $0x000003e8, 0(SP) /* Copy 'call (cur ip+8)' */
3e629dc19168 initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
73 MOVL $0x00000000, 4(SP) /* '00' for call address, rest is garbage */
3e629dc19168 initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
74 MOVL $0x5a909090, 8(SP) /* 'nop, nop, nop, pop edx' to get eip+5 in edx */
3e629dc19168 initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
75 MOVL $0xc30b628b,12(SP) /* Restore stack ptr and return: 'mov [edx+11] to esp, ret' */
3e629dc19168 initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
76
3e629dc19168 initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
77 SUBL CX, SP /* allocate 'size' bytes on stack for args */
3e629dc19168 initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
78 MOVL SP, DI /* DI = stack args */
3e629dc19168 initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
79
3e629dc19168 initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
80 SHRL $2, SP /* Align stack. */
3e629dc19168 initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
81 SHLL $2, SP /* " " */
3e629dc19168 initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
82
3e629dc19168 initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
83 /* I didn't figure out how to use MOVSB with the 8a syntax. The following
3e629dc19168 initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
84 can probably be written in a better way. */
3e629dc19168 initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
85 JMP copy_loop_cmp
3e629dc19168 initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
86 copy_loop:
3e629dc19168 initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
87 MOVL 0(SI), AX /* Copy args. */
3e629dc19168 initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
88 MOVL AX, 0(DI)
3e629dc19168 initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
89 SUBL $4, CX
3e629dc19168 initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
90 ADDL $4, SI
3e629dc19168 initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
91 ADDL $4, DI
3e629dc19168 initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
92 copy_loop_cmp:
3e629dc19168 initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
93 CMPL CX, $0
3e629dc19168 initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
94 JGT copy_loop
3e629dc19168 initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
95
3e629dc19168 initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
96 /* Check if we need to push a pointer to long long that might be used as
3e629dc19168 initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
97 container for 64-bit return values. */
3e629dc19168 initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
98 CMPL DX, $0
3e629dc19168 initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
99 JEQ call_ffi
3e629dc19168 initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
100 PUSHL DX
3e629dc19168 initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
101
3e629dc19168 initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
102 /* Now we try to fake a call, meaning setting up our fake return address,
3e629dc19168 initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
103 and then jumping to the FFI call. This should call the function, but
3e629dc19168 initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
104 the return will jump into our stack space we reserved above. */
3e629dc19168 initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
105 call_ffi:
3e629dc19168 initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
106 PUSHL BX
3e629dc19168 initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
107 MOVL 4(BP), BX
3e629dc19168 initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
108 JMP BX
3e629dc19168 initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
109
3e629dc19168 initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
110 /* Note that there is no return here, b/c the return is in the asm code
3e629dc19168 initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
111 above, that has been generated on the fly. */
3e629dc19168 initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
112
3e629dc19168 initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
113
3e629dc19168 initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
114 /* Main call for 32 bit integer return values and floating point arguments.
3e629dc19168 initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
115 See call_main for explanation. */
3e629dc19168 initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
116 TEXT dcCall_x86_plan9(SB), $0
3e629dc19168 initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
117
3e629dc19168 initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
118 MOVL $0, DX
3e629dc19168 initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
119 JMP call_main
3e629dc19168 initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
120
3e629dc19168 initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
121
3e629dc19168 initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
122 /* Call for 64 bit integer return values.
3e629dc19168 initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
123 See call_main for explanation. */
3e629dc19168 initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
124 TEXT dcCall_x86_plan9_ll(SB), $0
3e629dc19168 initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
125
3e629dc19168 initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
126 MOVL 16(SP), DX /* Copy pointer to variable for return value. */
3e629dc19168 initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
127 JMP call_main