aboutsummaryrefslogtreecommitdiff
path: root/libgo/go/reflect/makefunc_amd64.S
blob: 88302eee1b22641c018577fbc6febc9a282decd3 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
# Copyright 2013 The Go Authors. All rights reserved.
# Use of this source code is governed by a BSD-style
# license that can be found in the LICENSE file.

# MakeFunc amd64 assembly code.

#include "config.h"

	.global	reflect.makeFuncStub

#ifdef __ELF__
	.type	reflect.makeFuncStub,@function
#endif

reflect.makeFuncStub:
.LFB1:

	# Store all the parameter registers in a struct that looks
	# like:
	# struct {
	#   rax uint64		// 0x0
	#   rdi uint64		// 0x8
	#   rsi uint64		// 0x10
	#   rdx uint64		// 0x18
	#   rcx uint64		// 0x20
	#   r8 uint64		// 0x28
	#   r9 uint64		// 0x30
	#   rsp uint64		// 0x38 Pointer to arguments on stack.
	#   xmm0 [2]uint64	// 0x40
	#   xmm1 [2]uint64	// 0x50
	#   xmm2 [2]uint64	// 0x60
	#   xmm3 [2]uint64	// 0x70
	#   xmm4 [2]uint64	// 0x80
	#   xmm5 [2]uint64	// 0x90
	#   xmm6 [2]uint64	// 0xa0
	#   xmm7 [2]uint64	// 0xb0
	# };

	pushq	%rbp
.LCFI0:
	movq	%rsp, %rbp
.LCFI1:

	subq	$0xc0, %rsp		# Space for struct on stack.

	movq	%rax, 0x0(%rsp)
	movq	%rdi, 0x8(%rsp)
	movq	%rsi, 0x10(%rsp)
	movq	%rdx, 0x18(%rsp)
	movq	%rcx, 0x20(%rsp)
	movq	%r8, 0x28(%rsp)
	movq	%r9, 0x30(%rsp)
	leaq	16(%rbp), %rax
	movq	%rax, 0x38(%rsp)
	movdqa	%xmm0, 0x40(%rsp)
	movdqa	%xmm1, 0x50(%rsp)
	movdqa	%xmm2, 0x60(%rsp)
	movdqa	%xmm3, 0x70(%rsp)
	movdqa	%xmm4, 0x80(%rsp)
	movdqa	%xmm5, 0x90(%rsp)
	movdqa	%xmm6, 0xa0(%rsp)
	movdqa	%xmm7, 0xb0(%rsp)

	/* For MakeFunc functions that call recover.  */
	movq	8(%rbp), %rdi
#ifdef __PIC__
	call	__go_makefunc_can_recover@PLT
#else
	call	__go_makefunc_can_recover
#endif

	# Get function type.
#ifdef __PIC__
	call	__go_get_closure@PLT
#else
	call	__go_get_closure
#endif
	movq	%rax, %rsi

	movq	%rsp, %rdi

#ifdef __PIC__
	call	reflect.MakeFuncStubGo@PLT
#else
	call	reflect.MakeFuncStubGo
#endif

	/* MakeFunc functions can no longer call recover.  */
#ifdef __PIC__
	call __go_makefunc_returning@PLT
#else
	call __go_makefunc_returning
#endif

	# The structure will be updated with any return values.  Load
	# all possible return registers before returning to the caller.

	movq	0x0(%rsp), %rax
	movq	0x18(%rsp), %rdx
	movq	0x8(%rsp), %rdi
	movq	0x10(%rsp), %rsi
	movdqa	0x40(%rsp), %xmm0
	movdqa	0x50(%rsp), %xmm1

	# long double values are returned on the floating point stack,
	# but we don't worry about that since Go doesn't have a long
	# double type.

	leave
.LCFI2:

	ret
.LFE1:

#ifdef __ELF__
	.size	reflect.makeFuncStub, . - reflect.makeFuncStub
#endif

#ifdef __ELF__
#ifdef HAVE_AS_X86_64_UNWIND_SECTION_TYPE
	.section	.eh_frame,"a",@unwind
#else
	.section	.eh_frame,"a",@progbits
#endif
.Lframe1:
	.long	.LECIE1-.LSCIE1	/* Length of Common Information Entry */
.LSCIE1:
	.long	0x0		/* CIE Identifier Tag */
	.byte	0x1		/* CIE Version */
	.ascii "zR\0"		/* CIE Augmentation */
	.uleb128 1		/* CIE Code Alignment Factor */
	.sleb128 -8		/* CIE Data Alignment Factor */
	.byte	0x10		/* CIE RA Column */
	.uleb128 1		/* Augmentation size */
	.byte	0x1b		/* FDE Encoding (pcrel sdata4) */
	.byte	0xc		/* DW_CFA_def_cfa, %rsp offset 8 */
	.uleb128 7
	.uleb128 8
	.byte	0x80+16		/* DW_CFA_offset, %rip offset 1*-8 */
	.uleb128 1
	.align 8
.LECIE1:
.LSFDE1:
	.long	.LEFDE1-.LASFDE1	/* FDE Length */
.LASFDE1:
	.long	.LASFDE1-.Lframe1	/* FDE CIE offset */
#if HAVE_AS_X86_PCREL
	.long	.LFB1-.			/* FDE initial location */
#else
	.long	.LFB1@rel
#endif
	.long	.LFE1-.LFB1		/* FDE address range */
	.uleb128 0x0			/* Augmentation size */
	.byte	0x4			/* DW_CFA_advance_loc4 */
	.long	.LCFI0-.LFB1
	.byte	0xe			/* DW_CFA_def_cfa_offset */
	.uleb128 16
	.byte	0x86			/* DW_CFA_offset, column 0x6 */
	.uleb128 2
	.byte	0x4			/* DW_CFA_advance_loc4 */
	.long	.LCFI1-.LCFI0
	.byte	0xd			/* DW_CFA_def_cfa_register */
	.uleb128 6
	.byte	0x2			/* DW_CFA_advance_loc1 */
	.byte	.LCFI2-.LCFI1
	.byte	0xc			/* DW_CFA_def_cfa */
	.uleb128 7
	.uleb128 8
	.align 8
.LEFDE1:
#endif /* __ELF__ */

#if defined(__ELF__) && defined(__linux__)
	.section	.note.GNU-stack,"",@progbits
	.section	.note.GNU-split-stack,"",@progbits
	.section	.note.GNU-no-split-stack,"",@progbits
#endif