blob: 5aa73a6b8f73b228463068ca5c1d2d93fadb6093 [file] [log] [blame]
Russ Cox0d3a0432009-03-30 00:01:07 -07001// Copyright 2009 The Go Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style
3// license that can be found in the LICENSE file.
4
Russ Cox8522a472009-06-17 15:15:55 -07005#include "386/asm.h"
6
Russ Cox0d3a0432009-03-30 00:01:07 -07007TEXT _rt0_386(SB),7,$0
8 // copy arguments forward on an even stack
9 MOVL 0(SP), AX // argc
10 LEAL 4(SP), BX // argv
11 SUBL $128, SP // plenty of scratch
Russ Cox133a1582009-10-03 10:37:12 -070012 ANDL $~15, SP
Russ Cox0d3a0432009-03-30 00:01:07 -070013 MOVL AX, 120(SP) // save argc, argv away
14 MOVL BX, 124(SP)
15
Russ Cox133a1582009-10-03 10:37:12 -070016 // if there is an initcgo, call it to let it
17 // initialize and to set up GS. if not,
18 // we set up GS ourselves.
19 MOVL initcgo(SB), AX
20 TESTL AX, AX
21 JZ 3(PC)
22 CALL AX
23 JMP ok
24
Russ Cox1b14bdb2009-09-22 16:28:32 -070025 // set up %gs
Russ Cox0d3a0432009-03-30 00:01:07 -070026 CALL ldt0setup(SB)
27
Russ Cox0d3a0432009-03-30 00:01:07 -070028 // store through it, to make sure it works
Russ Coxbbcb91a2009-09-21 15:46:50 -070029 MOVL $0x123, 0(GS)
Russ Cox0d3a0432009-03-30 00:01:07 -070030 MOVL tls0(SB), AX
31 CMPL AX, $0x123
32 JEQ ok
Russ Cox133a1582009-10-03 10:37:12 -070033 MOVL AX, 0 // abort
Russ Cox0d3a0432009-03-30 00:01:07 -070034ok:
Russ Cox0d3a0432009-03-30 00:01:07 -070035 // set up m and g "registers"
Russ Cox0d3a0432009-03-30 00:01:07 -070036 LEAL g0(SB), CX
Russ Cox8522a472009-06-17 15:15:55 -070037 MOVL CX, g
Russ Cox0d3a0432009-03-30 00:01:07 -070038 LEAL m0(SB), AX
Russ Cox8522a472009-06-17 15:15:55 -070039 MOVL AX, m
Russ Cox0d3a0432009-03-30 00:01:07 -070040
41 // save m->g0 = g0
Russ Cox8522a472009-06-17 15:15:55 -070042 MOVL CX, m_g0(AX)
Russ Cox0d3a0432009-03-30 00:01:07 -070043
44 // create istack out of the OS stack
45 LEAL (-8192+104)(SP), AX // TODO: 104?
Russ Cox8522a472009-06-17 15:15:55 -070046 MOVL AX, g_stackguard(CX)
47 MOVL SP, g_stackbase(CX)
Russ Cox0d3a0432009-03-30 00:01:07 -070048 CALL emptyfunc(SB) // fault if stack check is wrong
49
50 // convention is D is always cleared
51 CLD
52
53 CALL check(SB)
54
55 // saved argc, argv
56 MOVL 120(SP), AX
57 MOVL AX, 0(SP)
58 MOVL 124(SP), AX
59 MOVL AX, 4(SP)
60 CALL args(SB)
61 CALL osinit(SB)
62 CALL schedinit(SB)
63
64 // create a new goroutine to start program
65 PUSHL $mainstart(SB) // entry
Russ Cox8522a472009-06-17 15:15:55 -070066 PUSHL $0 // arg size
Russ Cox0d3a0432009-03-30 00:01:07 -070067 CALL sys·newproc(SB)
68 POPL AX
69 POPL AX
70
71 // start this M
72 CALL mstart(SB)
73
74 INT $3
75 RET
76
77TEXT mainstart(SB),7,$0
78 CALL main·init(SB)
79 CALL initdone(SB)
80 CALL main·main(SB)
81 PUSHL $0
Russ Cox918afd942009-05-08 15:21:41 -070082 CALL exit(SB)
Russ Cox0d3a0432009-03-30 00:01:07 -070083 POPL AX
84 INT $3
85 RET
86
Russ Cox918afd942009-05-08 15:21:41 -070087TEXT breakpoint(SB),7,$0
Russ Cox1b14bdb2009-09-22 16:28:32 -070088 INT $3
Russ Cox0d3a0432009-03-30 00:01:07 -070089 RET
90
Russ Cox8522a472009-06-17 15:15:55 -070091/*
92 * go-routine
93 */
Russ Cox0d3a0432009-03-30 00:01:07 -070094
Russ Cox8522a472009-06-17 15:15:55 -070095// uintptr gosave(Gobuf*)
96// save state in Gobuf; setjmp
Russ Cox0d3a0432009-03-30 00:01:07 -070097TEXT gosave(SB), 7, $0
Russ Cox8522a472009-06-17 15:15:55 -070098 MOVL 4(SP), AX // gobuf
99 LEAL 4(SP), BX // caller's SP
100 MOVL BX, gobuf_sp(AX)
101 MOVL 0(SP), BX // caller's PC
102 MOVL BX, gobuf_pc(AX)
103 MOVL g, BX
104 MOVL BX, gobuf_g(AX)
105 MOVL $0, AX // return 0
Russ Cox0d3a0432009-03-30 00:01:07 -0700106 RET
107
Russ Cox8522a472009-06-17 15:15:55 -0700108// void gogo(Gobuf*, uintptr)
109// restore state from Gobuf; longjmp
110TEXT gogo(SB), 7, $0
111 MOVL 8(SP), AX // return 2nd arg
112 MOVL 4(SP), BX // gobuf
113 MOVL gobuf_g(BX), DX
114 MOVL 0(DX), CX // make sure g != nil
115 MOVL DX, g
116 MOVL gobuf_sp(BX), SP // restore SP
117 MOVL gobuf_pc(BX), BX
Russ Cox0d3a0432009-03-30 00:01:07 -0700118 JMP BX
Russ Cox8522a472009-06-17 15:15:55 -0700119
120// void gogocall(Gobuf*, void (*fn)(void))
121// restore state from Gobuf but then call fn.
122// (call fn, returning to state in Gobuf)
123TEXT gogocall(SB), 7, $0
124 MOVL 8(SP), AX // fn
125 MOVL 4(SP), BX // gobuf
126 MOVL gobuf_g(BX), DX
127 MOVL DX, g
128 MOVL 0(DX), CX // make sure g != nil
129 MOVL gobuf_sp(BX), SP // restore SP
130 MOVL gobuf_pc(BX), BX
131 PUSHL BX
132 JMP AX
133 POPL BX // not reached
134
135/*
136 * support for morestack
137 */
138
139// Called during function prolog when more stack is needed.
140TEXT sys·morestack(SB),7,$0
141 // Cannot grow scheduler stack (m->g0).
142 MOVL m, BX
143 MOVL m_g0(BX), SI
144 CMPL g, SI
145 JNE 2(PC)
146 INT $3
147
148 // frame size in DX
149 // arg size in AX
150 // Save in m.
151 MOVL DX, m_moreframe(BX)
152 MOVL AX, m_moreargs(BX)
153
154 // Called from f.
155 // Set m->morebuf to f's caller.
156 MOVL 4(SP), DI // f's caller's PC
157 MOVL DI, (m_morebuf+gobuf_pc)(BX)
158 LEAL 8(SP), CX // f's caller's SP
159 MOVL CX, (m_morebuf+gobuf_sp)(BX)
Russ Coxbba278a2009-07-08 18:16:09 -0700160 MOVL CX, (m_morefp)(BX)
Russ Cox8522a472009-06-17 15:15:55 -0700161 MOVL g, SI
162 MOVL SI, (m_morebuf+gobuf_g)(BX)
163
164 // Set m->morepc to f's PC.
165 MOVL 0(SP), AX
166 MOVL AX, m_morepc(BX)
167
168 // Call newstack on m's scheduling stack.
169 MOVL m_g0(BX), BP
170 MOVL BP, g
171 MOVL (m_sched+gobuf_sp)(BX), SP
172 CALL newstack(SB)
173 MOVL $0, 0x1003 // crash if newstack returns
Russ Cox0d3a0432009-03-30 00:01:07 -0700174 RET
175
Russ Coxbba278a2009-07-08 18:16:09 -0700176// Called from reflection library. Mimics morestack,
177// reuses stack growth code to create a frame
178// with the desired args running the desired function.
179//
180// func call(fn *byte, arg *byte, argsize uint32).
181TEXT reflect·call(SB), 7, $0
182 MOVL m, BX
183
184 // Save our caller's state as the PC and SP to
185 // restore when returning from f.
186 MOVL 0(SP), AX // our caller's PC
187 MOVL AX, (m_morebuf+gobuf_pc)(BX)
188 LEAL 4(SP), AX // our caller's SP
189 MOVL AX, (m_morebuf+gobuf_sp)(BX)
190 MOVL g, AX
191 MOVL AX, (m_morebuf+gobuf_g)(BX)
192
193 // Set up morestack arguments to call f on a new stack.
194 // We set f's frame size to zero, meaning
195 // allocate a standard sized stack segment.
196 // If it turns out that f needs a larger frame than this,
197 // f's usual stack growth prolog will allocate
198 // a new segment (and recopy the arguments).
199 MOVL 4(SP), AX // fn
200 MOVL 8(SP), DX // arg frame
201 MOVL 12(SP), CX // arg size
202
203 MOVL AX, m_morepc(BX) // f's PC
204 MOVL DX, m_morefp(BX) // argument frame pointer
205 MOVL CX, m_moreargs(BX) // f's argument size
206 MOVL $0, m_moreframe(BX) // f's frame size
207
208 // Call newstack on m's scheduling stack.
209 MOVL m_g0(BX), BP
210 MOVL BP, g
211 MOVL (m_sched+gobuf_sp)(BX), SP
212 CALL newstack(SB)
213 MOVL $0, 0x1103 // crash if newstack returns
214 RET
215
216
Russ Cox8522a472009-06-17 15:15:55 -0700217// Return point when leaving stack.
218TEXT sys·lessstack(SB), 7, $0
219 // Save return value in m->cret
220 MOVL m, BX
221 MOVL AX, m_cret(BX)
222
223 // Call oldstack on m's scheduling stack.
224 MOVL m_g0(BX), DX
225 MOVL DX, g
226 MOVL (m_sched+gobuf_sp)(BX), SP
227 CALL oldstack(SB)
228 MOVL $0, 0x1004 // crash if oldstack returns
229 RET
230
231
Russ Cox0d3a0432009-03-30 00:01:07 -0700232// bool cas(int32 *val, int32 old, int32 new)
233// Atomically:
234// if(*val == old){
235// *val = new;
236// return 1;
237// }else
238// return 0;
239TEXT cas(SB), 7, $0
240 MOVL 4(SP), BX
241 MOVL 8(SP), AX
242 MOVL 12(SP), CX
243 LOCK
244 CMPXCHGL CX, 0(BX)
245 JZ 3(PC)
246 MOVL $0, AX
247 RET
248 MOVL $1, AX
249 RET
250
Russ Coxaa3222d82009-06-02 23:02:12 -0700251// void jmpdefer(fn, sp);
252// called from deferreturn.
Russ Cox0d3a0432009-03-30 00:01:07 -0700253// 1. pop the caller
254// 2. sub 5 bytes from the callers return
255// 3. jmp to the argument
256TEXT jmpdefer(SB), 7, $0
Russ Coxaa3222d82009-06-02 23:02:12 -0700257 MOVL 4(SP), AX // fn
258 MOVL 8(SP), BX // caller sp
259 LEAL -4(BX), SP // caller sp after CALL
260 SUBL $5, (SP) // return to CALL again
261 JMP AX // but first run the deferred function
Russ Cox0d3a0432009-03-30 00:01:07 -0700262
263TEXT sys·memclr(SB),7,$0
264 MOVL 4(SP), DI // arg 1 addr
265 MOVL 8(SP), CX // arg 2 count
266 ADDL $3, CX
267 SHRL $2, CX
268 MOVL $0, AX
269 CLD
270 REP
271 STOSL
272 RET
273
274TEXT sys·getcallerpc+0(SB),7,$0
275 MOVL x+0(FP),AX // addr of first arg
276 MOVL -4(AX),AX // get calling pc
277 RET
278
279TEXT sys·setcallerpc+0(SB),7,$0
280 MOVL x+0(FP),AX // addr of first arg
281 MOVL x+4(FP), BX
282 MOVL BX, -4(AX) // set calling pc
283 RET
284
285TEXT ldt0setup(SB),7,$16
286 // set up ldt 7 to point at tls0
287 // ldt 1 would be fine on Linux, but on OS X, 7 is as low as we can go.
Russ Cox1b14bdb2009-09-22 16:28:32 -0700288 // the entry number is just a hint. setldt will set up GS with what it used.
Russ Cox0d3a0432009-03-30 00:01:07 -0700289 MOVL $7, 0(SP)
290 LEAL tls0(SB), AX
291 MOVL AX, 4(SP)
292 MOVL $32, 8(SP) // sizeof(tls array)
293 CALL setldt(SB)
294 RET
295
Russ Cox0d3a0432009-03-30 00:01:07 -0700296TEXT emptyfunc(SB),0,$0
297 RET
298
299TEXT abort(SB),7,$0
300 INT $0x3
Russ Cox133a1582009-10-03 10:37:12 -0700301
302// runcgo(void(*fn)(void*), void *arg)
303// Just call fn(arg), but first align the stack
304// appropriately for the gcc ABI.
305TEXT runcgo(SB),7,$16
306 MOVL fn+0(FP), AX
307 MOVL arg+4(FP), BX
308 MOVL SP, CX
309 ANDL $~15, SP // alignment for gcc ABI
310 MOVL CX, 4(SP)
311 MOVL BX, 0(SP)
312 CALL AX
313 MOVL 4(SP), SP
314 RET
315
316
317GLOBL m0(SB), $1024
318GLOBL g0(SB), $1024
319GLOBL tls0(SB), $32
320GLOBL initcgo(SB), $4
321