Rob Pike | 8e82a67 | 2008-06-30 11:50:36 -0700 | [diff] [blame] | 1 | // 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 Cox | 7343e03 | 2009-06-17 15:12:16 -0700 | [diff] [blame^] | 5 | #include "amd64/asm.h" |
Rob Pike | 8e82a67 | 2008-06-30 11:50:36 -0700 | [diff] [blame] | 6 | |
| 7 | TEXT _rt0_amd64(SB),7,$-8 |
| 8 | |
| 9 | // copy arguments forward on an even stack |
Rob Pike | 8e82a67 | 2008-06-30 11:50:36 -0700 | [diff] [blame] | 10 | MOVQ 0(SP), AX // argc |
| 11 | LEAQ 8(SP), BX // argv |
| 12 | SUBQ $(4*8+7), SP // 2args 2auto |
| 13 | ANDQ $~7, SP |
| 14 | MOVQ AX, 16(SP) |
| 15 | MOVQ BX, 24(SP) |
| 16 | |
Russ Cox | d28acc4 | 2008-08-04 16:43:49 -0700 | [diff] [blame] | 17 | // set the per-goroutine and per-mach registers |
Russ Cox | 7343e03 | 2009-06-17 15:12:16 -0700 | [diff] [blame^] | 18 | LEAQ m0(SB), m |
| 19 | LEAQ g0(SB), g |
| 20 | MOVQ g, m_g0(m) // m has pointer to its g0 |
Rob Pike | 8e82a67 | 2008-06-30 11:50:36 -0700 | [diff] [blame] | 21 | |
Ken Thompson | 751ce3a | 2008-07-11 19:16:39 -0700 | [diff] [blame] | 22 | // create istack out of the given (operating system) stack |
Russ Cox | da0a7d7 | 2008-12-19 03:13:39 -0800 | [diff] [blame] | 23 | LEAQ (-8192+104)(SP), AX |
Russ Cox | 7343e03 | 2009-06-17 15:12:16 -0700 | [diff] [blame^] | 24 | MOVQ AX, g_stackguard(g) |
| 25 | MOVQ SP, g_stackbase(g) |
Rob Pike | 8e82a67 | 2008-06-30 11:50:36 -0700 | [diff] [blame] | 26 | |
Ken Thompson | 8f53bc0 | 2008-12-15 15:07:35 -0800 | [diff] [blame] | 27 | CLD // convention is D is always left cleared |
Rob Pike | 8e82a67 | 2008-06-30 11:50:36 -0700 | [diff] [blame] | 28 | CALL check(SB) |
| 29 | |
Rob Pike | 8e82a67 | 2008-06-30 11:50:36 -0700 | [diff] [blame] | 30 | MOVL 16(SP), AX // copy argc |
| 31 | MOVL AX, 0(SP) |
| 32 | MOVQ 24(SP), AX // copy argv |
| 33 | MOVQ AX, 8(SP) |
| 34 | CALL args(SB) |
Russ Cox | 376898c | 2008-09-09 11:50:14 -0700 | [diff] [blame] | 35 | CALL osinit(SB) |
Russ Cox | d28acc4 | 2008-08-04 16:43:49 -0700 | [diff] [blame] | 36 | CALL schedinit(SB) |
Russ Cox | f7f6329 | 2008-08-05 14:21:42 -0700 | [diff] [blame] | 37 | |
Ken Thompson | 751ce3a | 2008-07-11 19:16:39 -0700 | [diff] [blame] | 38 | // create a new goroutine to start program |
Russ Cox | a67258f | 2008-09-18 15:56:46 -0700 | [diff] [blame] | 39 | PUSHQ $mainstart(SB) // entry |
Russ Cox | 7343e03 | 2009-06-17 15:12:16 -0700 | [diff] [blame^] | 40 | PUSHQ $0 // arg size |
Ken Thompson | 751ce3a | 2008-07-11 19:16:39 -0700 | [diff] [blame] | 41 | CALL sys·newproc(SB) |
Russ Cox | ebd1eef | 2008-09-22 13:47:59 -0700 | [diff] [blame] | 42 | POPQ AX |
| 43 | POPQ AX |
Russ Cox | 79e1db2 | 2008-12-04 08:30:54 -0800 | [diff] [blame] | 44 | |
Russ Cox | ebd1eef | 2008-09-22 13:47:59 -0700 | [diff] [blame] | 45 | // start this M |
Russ Cox | a67258f | 2008-09-18 15:56:46 -0700 | [diff] [blame] | 46 | CALL mstart(SB) |
Rob Pike | 8e82a67 | 2008-06-30 11:50:36 -0700 | [diff] [blame] | 47 | |
Ken Thompson | 751ce3a | 2008-07-11 19:16:39 -0700 | [diff] [blame] | 48 | CALL notok(SB) // never returns |
Rob Pike | 8e82a67 | 2008-06-30 11:50:36 -0700 | [diff] [blame] | 49 | RET |
| 50 | |
Russ Cox | a67258f | 2008-09-18 15:56:46 -0700 | [diff] [blame] | 51 | TEXT mainstart(SB),7,$0 |
Russ Cox | 0183baa | 2009-01-20 14:40:00 -0800 | [diff] [blame] | 52 | CALL main·init(SB) |
Russ Cox | a67258f | 2008-09-18 15:56:46 -0700 | [diff] [blame] | 53 | CALL initdone(SB) |
| 54 | CALL main·main(SB) |
Russ Cox | ebd1eef | 2008-09-22 13:47:59 -0700 | [diff] [blame] | 55 | PUSHQ $0 |
Russ Cox | 918afd94 | 2009-05-08 15:21:41 -0700 | [diff] [blame] | 56 | CALL exit(SB) |
Russ Cox | ebd1eef | 2008-09-22 13:47:59 -0700 | [diff] [blame] | 57 | POPQ AX |
| 58 | CALL notok(SB) |
Russ Cox | a67258f | 2008-09-18 15:56:46 -0700 | [diff] [blame] | 59 | RET |
| 60 | |
Russ Cox | 918afd94 | 2009-05-08 15:21:41 -0700 | [diff] [blame] | 61 | TEXT breakpoint(SB),7,$0 |
Ken Thompson | 751ce3a | 2008-07-11 19:16:39 -0700 | [diff] [blame] | 62 | BYTE $0xcc |
Rob Pike | 8e82a67 | 2008-06-30 11:50:36 -0700 | [diff] [blame] | 63 | RET |
| 64 | |
Ken Thompson | 751ce3a | 2008-07-11 19:16:39 -0700 | [diff] [blame] | 65 | /* |
| 66 | * go-routine |
| 67 | */ |
Rob Pike | d3204ef | 2008-06-30 14:39:47 -0700 | [diff] [blame] | 68 | |
Russ Cox | 7343e03 | 2009-06-17 15:12:16 -0700 | [diff] [blame^] | 69 | // uintptr gosave(Gobuf*) |
| 70 | // save state in Gobuf; setjmp |
Ken Thompson | 751ce3a | 2008-07-11 19:16:39 -0700 | [diff] [blame] | 71 | TEXT gosave(SB), 7, $0 |
| 72 | MOVQ 8(SP), AX // gobuf |
Russ Cox | 7343e03 | 2009-06-17 15:12:16 -0700 | [diff] [blame^] | 73 | LEAQ 8(SP), BX // caller's SP |
| 74 | MOVQ BX, gobuf_sp(AX) |
| 75 | MOVQ 0(SP), BX // caller's PC |
| 76 | MOVQ BX, gobuf_pc(AX) |
| 77 | MOVQ g, gobuf_g(AX) |
Ken Thompson | 751ce3a | 2008-07-11 19:16:39 -0700 | [diff] [blame] | 78 | MOVL $0, AX // return 0 |
| 79 | RET |
| 80 | |
Russ Cox | 7343e03 | 2009-06-17 15:12:16 -0700 | [diff] [blame^] | 81 | // void gogo(Gobuf*, uintptr) |
| 82 | // restore state from Gobuf; longjmp |
| 83 | TEXT gogo(SB), 7, $0 |
| 84 | MOVQ 16(SP), AX // return 2nd arg |
| 85 | MOVQ 8(SP), BX // gobuf |
| 86 | MOVQ gobuf_g(BX), g |
| 87 | MOVQ 0(g), CX // make sure g != nil |
| 88 | MOVQ gobuf_sp(BX), SP // restore SP |
| 89 | MOVQ gobuf_pc(BX), BX |
| 90 | JMP BX |
| 91 | |
| 92 | // void gogocall(Gobuf*, void (*fn)(void)) |
| 93 | // restore state from Gobuf but then call fn. |
| 94 | // (call fn, returning to state in Gobuf) |
| 95 | TEXT gogocall(SB), 7, $0 |
| 96 | MOVQ 16(SP), AX // fn |
| 97 | MOVQ 8(SP), BX // gobuf |
| 98 | MOVQ gobuf_g(BX), g |
| 99 | MOVQ 0(g), CX // make sure g != nil |
| 100 | MOVQ gobuf_sp(BX), SP // restore SP |
| 101 | MOVQ gobuf_pc(BX), BX |
| 102 | PUSHQ BX |
| 103 | JMP AX |
| 104 | POPQ BX // not reached |
| 105 | |
Rob Pike | 2da9783 | 2008-07-12 11:30:53 -0700 | [diff] [blame] | 106 | /* |
| 107 | * support for morestack |
| 108 | */ |
| 109 | |
Russ Cox | 7343e03 | 2009-06-17 15:12:16 -0700 | [diff] [blame^] | 110 | // Called during function prolog when more stack is needed. |
| 111 | TEXT sys·morestack(SB),7,$0 |
| 112 | // Called from f. |
| 113 | // Set m->morebuf to f's caller. |
| 114 | MOVQ 8(SP), AX // f's caller's PC |
| 115 | MOVQ AX, (m_morebuf+gobuf_pc)(m) |
| 116 | LEAQ 16(SP), AX // f's caller's SP |
| 117 | MOVQ AX, (m_morebuf+gobuf_sp)(m) |
| 118 | MOVQ g, (m_morebuf+gobuf_g)(m) |
| 119 | |
| 120 | // Set m->morepc to f's PC. |
| 121 | MOVQ 0(SP), AX |
| 122 | MOVQ AX, m_morepc(m) |
| 123 | |
| 124 | // Call newstack on m's scheduling stack. |
| 125 | MOVQ m_g0(m), g |
| 126 | MOVQ (m_sched+gobuf_sp)(m), SP |
| 127 | CALL newstack(SB) |
| 128 | MOVQ $0, 0x1003 // crash if newstack returns |
| 129 | RET |
| 130 | |
| 131 | // Return point when leaving stack. |
| 132 | TEXT sys·lessstack(SB), 7, $0 |
| 133 | // Save return value in m->cret |
| 134 | MOVQ AX, m_cret(m) |
| 135 | |
| 136 | // Call oldstack on m's scheduling stack. |
| 137 | MOVQ m_g0(m), g |
| 138 | MOVQ (m_sched+gobuf_sp)(m), SP |
| 139 | CALL oldstack(SB) |
| 140 | MOVQ $0, 0x1004 // crash if oldstack returns |
| 141 | RET |
| 142 | |
Ken Thompson | 1ed7f18 | 2009-05-01 18:07:33 -0700 | [diff] [blame] | 143 | // morestack trampolines |
| 144 | TEXT sys·morestack00+0(SB),7,$0 |
| 145 | MOVQ $0, AX |
Russ Cox | 7343e03 | 2009-06-17 15:12:16 -0700 | [diff] [blame^] | 146 | MOVQ AX, m_morearg(m) |
Ken Thompson | 1ed7f18 | 2009-05-01 18:07:33 -0700 | [diff] [blame] | 147 | MOVQ $sys·morestack+0(SB), AX |
| 148 | JMP AX |
| 149 | |
| 150 | TEXT sys·morestack01+0(SB),7,$0 |
| 151 | SHLQ $32, AX |
Russ Cox | 7343e03 | 2009-06-17 15:12:16 -0700 | [diff] [blame^] | 152 | MOVQ AX, m_morearg(m) |
Ken Thompson | 1ed7f18 | 2009-05-01 18:07:33 -0700 | [diff] [blame] | 153 | MOVQ $sys·morestack+0(SB), AX |
| 154 | JMP AX |
| 155 | |
| 156 | TEXT sys·morestack10+0(SB),7,$0 |
| 157 | MOVLQZX AX, AX |
Russ Cox | 7343e03 | 2009-06-17 15:12:16 -0700 | [diff] [blame^] | 158 | MOVQ AX, m_morearg(m) |
Ken Thompson | 1ed7f18 | 2009-05-01 18:07:33 -0700 | [diff] [blame] | 159 | MOVQ $sys·morestack+0(SB), AX |
| 160 | JMP AX |
| 161 | |
| 162 | TEXT sys·morestack11+0(SB),7,$0 |
Russ Cox | 7343e03 | 2009-06-17 15:12:16 -0700 | [diff] [blame^] | 163 | MOVQ AX, m_morearg(m) |
Ken Thompson | 1ed7f18 | 2009-05-01 18:07:33 -0700 | [diff] [blame] | 164 | MOVQ $sys·morestack+0(SB), AX |
| 165 | JMP AX |
| 166 | |
Ken Thompson | 5963f59 | 2009-05-03 19:09:14 -0700 | [diff] [blame] | 167 | // subcases of morestack01 |
| 168 | // with const of 8,16,...48 |
| 169 | TEXT sys·morestack8(SB),7,$0 |
| 170 | PUSHQ $1 |
| 171 | MOVQ $sys·morestackx(SB), AX |
| 172 | JMP AX |
| 173 | |
| 174 | TEXT sys·morestack16(SB),7,$0 |
| 175 | PUSHQ $2 |
| 176 | MOVQ $sys·morestackx(SB), AX |
| 177 | JMP AX |
| 178 | |
| 179 | TEXT sys·morestack24(SB),7,$0 |
| 180 | PUSHQ $3 |
| 181 | MOVQ $sys·morestackx(SB), AX |
| 182 | JMP AX |
| 183 | |
| 184 | TEXT sys·morestack32(SB),7,$0 |
| 185 | PUSHQ $4 |
| 186 | MOVQ $sys·morestackx(SB), AX |
| 187 | JMP AX |
| 188 | |
| 189 | TEXT sys·morestack40(SB),7,$0 |
| 190 | PUSHQ $5 |
| 191 | MOVQ $sys·morestackx(SB), AX |
| 192 | JMP AX |
| 193 | |
| 194 | TEXT sys·morestack48(SB),7,$0 |
| 195 | PUSHQ $6 |
| 196 | MOVQ $sys·morestackx(SB), AX |
| 197 | JMP AX |
| 198 | |
Russ Cox | 7343e03 | 2009-06-17 15:12:16 -0700 | [diff] [blame^] | 199 | TEXT sys·morestackx(SB),7,$0 |
| 200 | POPQ AX |
| 201 | SHLQ $35, AX |
| 202 | MOVQ AX, m_morearg(m) |
| 203 | MOVQ $sys·morestack(SB), AX |
Rob Pike | 2da9783 | 2008-07-12 11:30:53 -0700 | [diff] [blame] | 204 | JMP AX |
| 205 | |
Russ Cox | d28acc4 | 2008-08-04 16:43:49 -0700 | [diff] [blame] | 206 | // bool cas(int32 *val, int32 old, int32 new) |
| 207 | // Atomically: |
| 208 | // if(*val == old){ |
| 209 | // *val = new; |
| 210 | // return 1; |
Ken Thompson | 1e1cc4e | 2009-01-27 12:03:53 -0800 | [diff] [blame] | 211 | // } else |
Russ Cox | d28acc4 | 2008-08-04 16:43:49 -0700 | [diff] [blame] | 212 | // return 0; |
| 213 | TEXT cas(SB), 7, $0 |
| 214 | MOVQ 8(SP), BX |
| 215 | MOVL 16(SP), AX |
| 216 | MOVL 20(SP), CX |
| 217 | LOCK |
| 218 | CMPXCHGL CX, 0(BX) |
| 219 | JZ 3(PC) |
| 220 | MOVL $0, AX |
| 221 | RET |
| 222 | MOVL $1, AX |
| 223 | RET |
Ken Thompson | 1e1cc4e | 2009-01-27 12:03:53 -0800 | [diff] [blame] | 224 | |
Russ Cox | aa3222d8 | 2009-06-02 23:02:12 -0700 | [diff] [blame] | 225 | // void jmpdefer(fn, sp); |
| 226 | // called from deferreturn. |
Ken Thompson | 1e1cc4e | 2009-01-27 12:03:53 -0800 | [diff] [blame] | 227 | // 1. pop the caller |
| 228 | // 2. sub 5 bytes from the callers return |
| 229 | // 3. jmp to the argument |
| 230 | TEXT jmpdefer(SB), 7, $0 |
Russ Cox | aa3222d8 | 2009-06-02 23:02:12 -0700 | [diff] [blame] | 231 | MOVQ 8(SP), AX // fn |
| 232 | MOVQ 16(SP), BX // caller sp |
| 233 | LEAQ -8(BX), SP // caller sp after CALL |
| 234 | SUBQ $5, (SP) // return to CALL again |
| 235 | JMP AX // but first run the deferred function |