Wei Guangjing | f83609f | 2011-06-29 17:37:56 +1000 | [diff] [blame] | 1 | // Copyright 2011 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 | 15ced2d | 2014-11-11 17:06:22 -0500 | [diff] [blame] | 5 | #include "go_asm.h" |
| 6 | #include "go_tls.h" |
Russ Cox | cb040d5 | 2014-09-04 23:05:18 -0400 | [diff] [blame] | 7 | #include "textflag.h" |
Wei Guangjing | f83609f | 2011-06-29 17:37:56 +1000 | [diff] [blame] | 8 | |
Alex Brainman | fbdec64 | 2011-11-29 12:57:20 +1100 | [diff] [blame] | 9 | // maxargs should be divisible by 2, as Windows stack |
| 10 | // must be kept 16-byte aligned on syscall entry. |
| 11 | #define maxargs 16 |
Wei Guangjing | f83609f | 2011-06-29 17:37:56 +1000 | [diff] [blame] | 12 | |
Alex Brainman | 2a80882 | 2011-08-27 23:17:00 +1000 | [diff] [blame] | 13 | // void runtime·asmstdcall(void *c); |
Keith Randall | 0273dc1 | 2013-08-07 12:20:05 -0700 | [diff] [blame] | 14 | TEXT runtime·asmstdcall(SB),NOSPLIT,$0 |
Alex Brainman | 2a80882 | 2011-08-27 23:17:00 +1000 | [diff] [blame] | 15 | // asmcgocall will put first argument into CX. |
| 16 | PUSHQ CX // save for later |
Aram Hăvărneanu | a46b434 | 2014-01-17 17:58:10 +1300 | [diff] [blame] | 17 | MOVQ libcall_fn(CX), AX |
| 18 | MOVQ libcall_args(CX), SI |
| 19 | MOVQ libcall_n(CX), CX |
Alex Brainman | 2a80882 | 2011-08-27 23:17:00 +1000 | [diff] [blame] | 20 | |
| 21 | // SetLastError(0). |
| 22 | MOVQ 0x30(GS), DI |
| 23 | MOVL $0, 0x68(DI) |
| 24 | |
| 25 | SUBQ $(maxargs*8), SP // room for args |
| 26 | |
| 27 | // Fast version, do not store args on the stack. |
| 28 | CMPL CX, $4 |
| 29 | JLE loadregs |
| 30 | |
| 31 | // Check we have enough room for args. |
| 32 | CMPL CX, $maxargs |
| 33 | JLE 2(PC) |
| 34 | INT $3 // not enough room -> crash |
| 35 | |
| 36 | // Copy args to the stack. |
Wei Guangjing | f83609f | 2011-06-29 17:37:56 +1000 | [diff] [blame] | 37 | MOVQ SP, DI |
Wei Guangjing | f83609f | 2011-06-29 17:37:56 +1000 | [diff] [blame] | 38 | CLD |
| 39 | REP; MOVSQ |
Alex Brainman | 2a80882 | 2011-08-27 23:17:00 +1000 | [diff] [blame] | 40 | MOVQ SP, SI |
| 41 | |
| 42 | loadregs: |
| 43 | // Load first 4 args into correspondent registers. |
| 44 | MOVQ 0(SI), CX |
| 45 | MOVQ 8(SI), DX |
| 46 | MOVQ 16(SI), R8 |
| 47 | MOVQ 24(SI), R9 |
Wei Guangjing | f83609f | 2011-06-29 17:37:56 +1000 | [diff] [blame] | 48 | |
| 49 | // Call stdcall function. |
| 50 | CALL AX |
Alex Brainman | 2a80882 | 2011-08-27 23:17:00 +1000 | [diff] [blame] | 51 | |
| 52 | ADDQ $(maxargs*8), SP |
| 53 | |
| 54 | // Return result. |
| 55 | POPQ CX |
Aram Hăvărneanu | a46b434 | 2014-01-17 17:58:10 +1300 | [diff] [blame] | 56 | MOVQ AX, libcall_r1(CX) |
Alex Brainman | 2a80882 | 2011-08-27 23:17:00 +1000 | [diff] [blame] | 57 | |
| 58 | // GetLastError(). |
| 59 | MOVQ 0x30(GS), DI |
| 60 | MOVL 0x68(DI), AX |
Aram Hăvărneanu | a46b434 | 2014-01-17 17:58:10 +1300 | [diff] [blame] | 61 | MOVQ AX, libcall_err(CX) |
Wei Guangjing | f83609f | 2011-06-29 17:37:56 +1000 | [diff] [blame] | 62 | |
| 63 | RET |
| 64 | |
Keith Randall | 0273dc1 | 2013-08-07 12:20:05 -0700 | [diff] [blame] | 65 | TEXT runtime·badsignal2(SB),NOSPLIT,$48 |
Russ Cox | b236911 | 2012-03-12 15:55:18 -0400 | [diff] [blame] | 66 | // stderr |
| 67 | MOVQ $-12, CX // stderr |
| 68 | MOVQ CX, 0(SP) |
Alex Brainman | b27c061 | 2014-11-19 11:55:15 +1100 | [diff] [blame] | 69 | MOVQ runtime·_GetStdHandle(SB), AX |
Russ Cox | b236911 | 2012-03-12 15:55:18 -0400 | [diff] [blame] | 70 | CALL AX |
| 71 | |
| 72 | MOVQ AX, CX // handle |
| 73 | MOVQ CX, 0(SP) |
| 74 | MOVQ $runtime·badsignalmsg(SB), DX // pointer |
| 75 | MOVQ DX, 8(SP) |
| 76 | MOVL $runtime·badsignallen(SB), R8 // count |
| 77 | MOVQ R8, 16(SP) |
| 78 | LEAQ 40(SP), R9 // written count |
| 79 | MOVQ $0, 0(R9) |
| 80 | MOVQ R9, 24(SP) |
| 81 | MOVQ $0, 32(SP) // overlapped |
Alex Brainman | b27c061 | 2014-11-19 11:55:15 +1100 | [diff] [blame] | 82 | MOVQ runtime·_WriteFile(SB), AX |
Russ Cox | b236911 | 2012-03-12 15:55:18 -0400 | [diff] [blame] | 83 | CALL AX |
| 84 | |
| 85 | RET |
| 86 | |
Wei Guangjing | f83609f | 2011-06-29 17:37:56 +1000 | [diff] [blame] | 87 | // faster get/set last error |
Keith Randall | 0273dc1 | 2013-08-07 12:20:05 -0700 | [diff] [blame] | 88 | TEXT runtime·getlasterror(SB),NOSPLIT,$0 |
Wei Guangjing | f83609f | 2011-06-29 17:37:56 +1000 | [diff] [blame] | 89 | MOVQ 0x30(GS), AX |
| 90 | MOVL 0x68(AX), AX |
Russ Cox | 25f6b02 | 2014-08-27 11:32:17 -0400 | [diff] [blame] | 91 | MOVL AX, ret+0(FP) |
Wei Guangjing | f83609f | 2011-06-29 17:37:56 +1000 | [diff] [blame] | 92 | RET |
| 93 | |
Keith Randall | 0273dc1 | 2013-08-07 12:20:05 -0700 | [diff] [blame] | 94 | TEXT runtime·setlasterror(SB),NOSPLIT,$0 |
Wei Guangjing | f83609f | 2011-06-29 17:37:56 +1000 | [diff] [blame] | 95 | MOVL err+0(FP), AX |
| 96 | MOVQ 0x30(GS), CX |
| 97 | MOVL AX, 0x68(CX) |
| 98 | RET |
| 99 | |
Alex Brainman | a837347 | 2014-03-26 11:13:50 +1100 | [diff] [blame] | 100 | // Called by Windows as a Vectored Exception Handler (VEH). |
| 101 | // First argument is pointer to struct containing |
| 102 | // exception record and context pointers. |
Alex Brainman | e9ecd4a | 2014-10-15 11:11:11 +1100 | [diff] [blame] | 103 | // Handler function is stored in AX. |
Alex Brainman | a837347 | 2014-03-26 11:13:50 +1100 | [diff] [blame] | 104 | // Return 0 for 'not handled', -1 for handled. |
| 105 | TEXT runtime·sigtramp(SB),NOSPLIT,$0-0 |
| 106 | // CX: PEXCEPTION_POINTERS ExceptionInfo |
Hector Chu | 9b01150 | 2011-09-03 18:27:16 +1000 | [diff] [blame] | 107 | |
Alex Brainman | a837347 | 2014-03-26 11:13:50 +1100 | [diff] [blame] | 108 | // DI SI BP BX R12 R13 R14 R15 registers and DF flag are preserved |
| 109 | // as required by windows callback convention. |
| 110 | PUSHFQ |
Russ Cox | 201cfe4 | 2014-09-08 16:56:46 -0400 | [diff] [blame] | 111 | SUBQ $112, SP |
Alex Brainman | a837347 | 2014-03-26 11:13:50 +1100 | [diff] [blame] | 112 | MOVQ DI, 80(SP) |
| 113 | MOVQ SI, 72(SP) |
| 114 | MOVQ BP, 64(SP) |
| 115 | MOVQ BX, 56(SP) |
| 116 | MOVQ R12, 48(SP) |
| 117 | MOVQ R13, 40(SP) |
| 118 | MOVQ R14, 32(SP) |
Russ Cox | c548cc2 | 2014-08-27 14:43:07 -0400 | [diff] [blame] | 119 | MOVQ R15, 88(SP) |
Hector Chu | 9b01150 | 2011-09-03 18:27:16 +1000 | [diff] [blame] | 120 | |
Alex Brainman | e9ecd4a | 2014-10-15 11:11:11 +1100 | [diff] [blame] | 121 | MOVQ AX, R15 // save handler address |
| 122 | |
Russ Cox | 201cfe4 | 2014-09-08 16:56:46 -0400 | [diff] [blame] | 123 | // find g |
Alex Brainman | a837347 | 2014-03-26 11:13:50 +1100 | [diff] [blame] | 124 | get_tls(DX) |
Shenghou Ma | a1778ec | 2014-07-09 23:55:35 -0400 | [diff] [blame] | 125 | CMPQ DX, $0 |
| 126 | JNE 3(PC) |
| 127 | MOVQ $0, AX // continue |
| 128 | JMP done |
Russ Cox | 89f185f | 2014-06-26 11:54:39 -0400 | [diff] [blame] | 129 | MOVQ g(DX), DX |
| 130 | CMPQ DX, $0 |
Russ Cox | b236911 | 2012-03-12 15:55:18 -0400 | [diff] [blame] | 131 | JNE 2(PC) |
Shenghou Ma | 4a4d483 | 2013-07-12 05:06:43 +0800 | [diff] [blame] | 132 | CALL runtime·badsignal2(SB) |
Russ Cox | 201cfe4 | 2014-09-08 16:56:46 -0400 | [diff] [blame] | 133 | |
| 134 | // save g and SP in case of stack switch |
| 135 | MOVQ DX, 96(SP) // g |
| 136 | MOVQ SP, 104(SP) |
| 137 | |
| 138 | // do we need to switch to the g0 stack? |
| 139 | MOVQ g_m(DX), BX |
| 140 | MOVQ m_g0(BX), BX |
| 141 | CMPQ DX, BX |
Russ Cox | b55791e | 2014-10-28 21:50:16 -0400 | [diff] [blame] | 142 | JEQ g0 |
Russ Cox | 201cfe4 | 2014-09-08 16:56:46 -0400 | [diff] [blame] | 143 | |
| 144 | // switch to g0 stack |
| 145 | get_tls(BP) |
| 146 | MOVQ BX, g(BP) |
| 147 | MOVQ (g_sched+gobuf_sp)(BX), DI |
| 148 | // make it look like mstart called us on g0, to stop traceback |
| 149 | SUBQ $8, DI |
| 150 | MOVQ $runtime·mstart(SB), SI |
| 151 | MOVQ SI, 0(DI) |
| 152 | // traceback will think that we've done PUSHFQ and SUBQ |
| 153 | // on this stack, so subtract them here to match. |
| 154 | // (we need room for sighandler arguments anyway). |
| 155 | // and re-save old SP for restoring later. |
| 156 | SUBQ $(112+8), DI |
| 157 | // save g, save old stack pointer. |
| 158 | MOVQ SP, 104(DI) |
| 159 | MOVQ DI, SP |
| 160 | |
Russ Cox | b55791e | 2014-10-28 21:50:16 -0400 | [diff] [blame] | 161 | g0: |
Russ Cox | 201cfe4 | 2014-09-08 16:56:46 -0400 | [diff] [blame] | 162 | MOVQ 0(CX), BX // ExceptionRecord* |
| 163 | MOVQ 8(CX), CX // Context* |
Alex Brainman | a837347 | 2014-03-26 11:13:50 +1100 | [diff] [blame] | 164 | MOVQ BX, 0(SP) |
| 165 | MOVQ CX, 8(SP) |
| 166 | MOVQ DX, 16(SP) |
Alex Brainman | e9ecd4a | 2014-10-15 11:11:11 +1100 | [diff] [blame] | 167 | CALL R15 // call handler |
Alex Brainman | a837347 | 2014-03-26 11:13:50 +1100 | [diff] [blame] | 168 | // AX is set to report result back to Windows |
Russ Cox | c548cc2 | 2014-08-27 14:43:07 -0400 | [diff] [blame] | 169 | MOVL 24(SP), AX |
Hector Chu | 9b01150 | 2011-09-03 18:27:16 +1000 | [diff] [blame] | 170 | |
Russ Cox | 201cfe4 | 2014-09-08 16:56:46 -0400 | [diff] [blame] | 171 | // switch back to original stack and g |
| 172 | // no-op if we never left. |
| 173 | MOVQ 104(SP), SP |
| 174 | MOVQ 96(SP), DX |
| 175 | get_tls(BP) |
| 176 | MOVQ DX, g(BP) |
| 177 | |
Shenghou Ma | a1778ec | 2014-07-09 23:55:35 -0400 | [diff] [blame] | 178 | done: |
Alex Brainman | a837347 | 2014-03-26 11:13:50 +1100 | [diff] [blame] | 179 | // restore registers as required for windows callback |
Russ Cox | c548cc2 | 2014-08-27 14:43:07 -0400 | [diff] [blame] | 180 | MOVQ 88(SP), R15 |
Alex Brainman | a837347 | 2014-03-26 11:13:50 +1100 | [diff] [blame] | 181 | MOVQ 32(SP), R14 |
| 182 | MOVQ 40(SP), R13 |
| 183 | MOVQ 48(SP), R12 |
| 184 | MOVQ 56(SP), BX |
| 185 | MOVQ 64(SP), BP |
| 186 | MOVQ 72(SP), SI |
| 187 | MOVQ 80(SP), DI |
Russ Cox | 201cfe4 | 2014-09-08 16:56:46 -0400 | [diff] [blame] | 188 | ADDQ $112, SP |
Alex Brainman | a837347 | 2014-03-26 11:13:50 +1100 | [diff] [blame] | 189 | POPFQ |
Russ Cox | 2d3cc97 | 2012-03-12 16:48:16 -0400 | [diff] [blame] | 190 | |
Hector Chu | 9b01150 | 2011-09-03 18:27:16 +1000 | [diff] [blame] | 191 | RET |
| 192 | |
Alex Brainman | e9ecd4a | 2014-10-15 11:11:11 +1100 | [diff] [blame] | 193 | TEXT runtime·exceptiontramp(SB),NOSPLIT,$0 |
| 194 | MOVQ $runtime·exceptionhandler(SB), AX |
| 195 | JMP runtime·sigtramp(SB) |
| 196 | |
| 197 | TEXT runtime·firstcontinuetramp(SB),NOSPLIT,$0-0 |
| 198 | MOVQ $runtime·firstcontinuehandler(SB), AX |
| 199 | JMP runtime·sigtramp(SB) |
| 200 | |
| 201 | TEXT runtime·lastcontinuetramp(SB),NOSPLIT,$0-0 |
| 202 | MOVQ $runtime·lastcontinuehandler(SB), AX |
| 203 | JMP runtime·sigtramp(SB) |
| 204 | |
Keith Randall | 0273dc1 | 2013-08-07 12:20:05 -0700 | [diff] [blame] | 205 | TEXT runtime·ctrlhandler(SB),NOSPLIT,$8 |
Hector Chu | 9fd2687 | 2011-09-17 17:57:59 +1000 | [diff] [blame] | 206 | MOVQ CX, 16(SP) // spill |
| 207 | MOVQ $runtime·ctrlhandler1(SB), CX |
| 208 | MOVQ CX, 0(SP) |
| 209 | CALL runtime·externalthreadhandler(SB) |
| 210 | RET |
| 211 | |
Keith Randall | 0273dc1 | 2013-08-07 12:20:05 -0700 | [diff] [blame] | 212 | TEXT runtime·profileloop(SB),NOSPLIT,$8 |
Hector Chu | 9fd2687 | 2011-09-17 17:57:59 +1000 | [diff] [blame] | 213 | MOVQ $runtime·profileloop1(SB), CX |
| 214 | MOVQ CX, 0(SP) |
| 215 | CALL runtime·externalthreadhandler(SB) |
| 216 | RET |
| 217 | |
Keith Randall | 0273dc1 | 2013-08-07 12:20:05 -0700 | [diff] [blame] | 218 | TEXT runtime·externalthreadhandler(SB),NOSPLIT,$0 |
Wei Guangjing | acfb0a1 | 2011-08-18 12:37:42 -0400 | [diff] [blame] | 219 | PUSHQ BP |
| 220 | MOVQ SP, BP |
| 221 | PUSHQ BX |
| 222 | PUSHQ SI |
| 223 | PUSHQ DI |
Wei Guangjing | 9569c67 | 2012-01-09 11:23:07 +1100 | [diff] [blame] | 224 | PUSHQ 0x28(GS) |
Hector Chu | 9fd2687 | 2011-09-17 17:57:59 +1000 | [diff] [blame] | 225 | MOVQ SP, DX |
Wei Guangjing | acfb0a1 | 2011-08-18 12:37:42 -0400 | [diff] [blame] | 226 | |
| 227 | // setup dummy m, g |
Keith Randall | 1dd0163 | 2015-01-06 20:38:44 -0800 | [diff] [blame] | 228 | SUBQ $m__size, SP // space for M |
Hector Chu | 9fd2687 | 2011-09-17 17:57:59 +1000 | [diff] [blame] | 229 | MOVQ SP, 0(SP) |
Keith Randall | 1dd0163 | 2015-01-06 20:38:44 -0800 | [diff] [blame] | 230 | MOVQ $m__size, 8(SP) |
Hector Chu | 9fd2687 | 2011-09-17 17:57:59 +1000 | [diff] [blame] | 231 | CALL runtime·memclr(SB) // smashes AX,BX,CX |
| 232 | |
Wei Guangjing | acfb0a1 | 2011-08-18 12:37:42 -0400 | [diff] [blame] | 233 | LEAQ m_tls(SP), CX |
Wei Guangjing | 9569c67 | 2012-01-09 11:23:07 +1100 | [diff] [blame] | 234 | MOVQ CX, 0x28(GS) |
Hector Chu | 9fd2687 | 2011-09-17 17:57:59 +1000 | [diff] [blame] | 235 | MOVQ SP, BX |
Keith Randall | 1dd0163 | 2015-01-06 20:38:44 -0800 | [diff] [blame] | 236 | SUBQ $g__size, SP // space for G |
Wei Guangjing | acfb0a1 | 2011-08-18 12:37:42 -0400 | [diff] [blame] | 237 | MOVQ SP, g(CX) |
Hector Chu | 9fd2687 | 2011-09-17 17:57:59 +1000 | [diff] [blame] | 238 | MOVQ SP, m_g0(BX) |
| 239 | |
| 240 | MOVQ SP, 0(SP) |
Keith Randall | 1dd0163 | 2015-01-06 20:38:44 -0800 | [diff] [blame] | 241 | MOVQ $g__size, 8(SP) |
Hector Chu | 9fd2687 | 2011-09-17 17:57:59 +1000 | [diff] [blame] | 242 | CALL runtime·memclr(SB) // smashes AX,BX,CX |
Keith Randall | 1dd0163 | 2015-01-06 20:38:44 -0800 | [diff] [blame] | 243 | LEAQ g__size(SP), BX |
Russ Cox | 89f185f | 2014-06-26 11:54:39 -0400 | [diff] [blame] | 244 | MOVQ BX, g_m(SP) |
| 245 | |
Wei Guangjing | acfb0a1 | 2011-08-18 12:37:42 -0400 | [diff] [blame] | 246 | LEAQ -8192(SP), CX |
Russ Cox | 8ac35be | 2014-09-09 14:02:37 -0400 | [diff] [blame] | 247 | MOVQ CX, (g_stack+stack_lo)(SP) |
Alex Brainman | b27c061 | 2014-11-19 11:55:15 +1100 | [diff] [blame] | 248 | ADDQ $const__StackGuard, CX |
Russ Cox | e6d3511 | 2015-01-05 16:29:21 +0000 | [diff] [blame] | 249 | MOVQ CX, g_stackguard0(SP) |
| 250 | MOVQ CX, g_stackguard1(SP) |
Russ Cox | 8ac35be | 2014-09-09 14:02:37 -0400 | [diff] [blame] | 251 | MOVQ DX, (g_stack+stack_hi)(SP) |
Wei Guangjing | acfb0a1 | 2011-08-18 12:37:42 -0400 | [diff] [blame] | 252 | |
Alex Brainman | 9402e49 | 2015-04-14 10:48:05 +1000 | [diff] [blame] | 253 | PUSHQ AX // room for return value |
Hector Chu | 9fd2687 | 2011-09-17 17:57:59 +1000 | [diff] [blame] | 254 | PUSHQ 32(BP) // arg for handler |
| 255 | CALL 16(BP) |
Wei Guangjing | acfb0a1 | 2011-08-18 12:37:42 -0400 | [diff] [blame] | 256 | POPQ CX |
Alex Brainman | 9402e49 | 2015-04-14 10:48:05 +1000 | [diff] [blame] | 257 | POPQ AX // pass return value to Windows in AX |
Wei Guangjing | acfb0a1 | 2011-08-18 12:37:42 -0400 | [diff] [blame] | 258 | |
| 259 | get_tls(CX) |
| 260 | MOVQ g(CX), CX |
Russ Cox | 8ac35be | 2014-09-09 14:02:37 -0400 | [diff] [blame] | 261 | MOVQ (g_stack+stack_hi)(CX), SP |
Wei Guangjing | 9569c67 | 2012-01-09 11:23:07 +1100 | [diff] [blame] | 262 | POPQ 0x28(GS) |
Wei Guangjing | acfb0a1 | 2011-08-18 12:37:42 -0400 | [diff] [blame] | 263 | POPQ DI |
| 264 | POPQ SI |
| 265 | POPQ BX |
| 266 | POPQ BP |
Hector Chu | 0f5902d | 2011-08-29 22:12:56 +1000 | [diff] [blame] | 267 | RET |
Jaroslavas Počepko | c586b5b | 2011-08-30 22:02:02 +1000 | [diff] [blame] | 268 | |
Russ Cox | 3c94b1d | 2014-09-24 19:04:06 -0400 | [diff] [blame] | 269 | GLOBL runtime·cbctxts(SB), NOPTR, $8 |
Alex Brainman | 05a5de3 | 2013-06-24 17:17:45 +1000 | [diff] [blame] | 270 | |
Keith Randall | 0273dc1 | 2013-08-07 12:20:05 -0700 | [diff] [blame] | 271 | TEXT runtime·callbackasm1(SB),NOSPLIT,$0 |
Jaroslavas Počepko | c586b5b | 2011-08-30 22:02:02 +1000 | [diff] [blame] | 272 | // Construct args vector for cgocallback(). |
| 273 | // By windows/amd64 calling convention first 4 args are in CX, DX, R8, R9 |
| 274 | // args from the 5th on are on the stack. |
| 275 | // In any case, even if function has 0,1,2,3,4 args, there is reserved |
| 276 | // but uninitialized "shadow space" for the first 4 args. |
| 277 | // The values are in registers. |
Alex Brainman | 05a5de3 | 2013-06-24 17:17:45 +1000 | [diff] [blame] | 278 | MOVQ CX, (16+0)(SP) |
| 279 | MOVQ DX, (16+8)(SP) |
| 280 | MOVQ R8, (16+16)(SP) |
| 281 | MOVQ R9, (16+24)(SP) |
| 282 | |
| 283 | // remove return address from stack, we are not returning there |
| 284 | MOVQ 0(SP), AX |
| 285 | ADDQ $8, SP |
| 286 | |
| 287 | // determine index into runtime·cbctxts table |
Russ Cox | 3e9c7a8 | 2014-08-18 22:12:51 -0400 | [diff] [blame] | 288 | MOVQ $runtime·callbackasm(SB), DX |
| 289 | SUBQ DX, AX |
Alex Brainman | 05a5de3 | 2013-06-24 17:17:45 +1000 | [diff] [blame] | 290 | MOVQ $0, DX |
| 291 | MOVQ $5, CX // divide by 5 because each call instruction in runtime·callbacks is 5 bytes long |
Alex Brainman | 201b124 | 2015-02-17 16:48:31 +1100 | [diff] [blame] | 292 | DIVL CX |
Alex Brainman | 05a5de3 | 2013-06-24 17:17:45 +1000 | [diff] [blame] | 293 | |
| 294 | // find correspondent runtime·cbctxts table entry |
| 295 | MOVQ runtime·cbctxts(SB), CX |
| 296 | MOVQ -8(CX)(AX*8), AX |
| 297 | |
| 298 | // extract callback context |
Alex Brainman | b27c061 | 2014-11-19 11:55:15 +1100 | [diff] [blame] | 299 | MOVQ wincallbackcontext_argsize(AX), DX |
| 300 | MOVQ wincallbackcontext_gobody(AX), AX |
Jaroslavas Počepko | c586b5b | 2011-08-30 22:02:02 +1000 | [diff] [blame] | 301 | |
| 302 | // preserve whatever's at the memory location that |
| 303 | // the callback will use to store the return value |
| 304 | LEAQ 8(SP), CX // args vector, skip return address |
| 305 | PUSHQ 0(CX)(DX*1) // store 8 bytes from just after the args array |
| 306 | ADDQ $8, DX // extend argsize by size of return value |
| 307 | |
| 308 | // DI SI BP BX R12 R13 R14 R15 registers and DF flag are preserved |
| 309 | // as required by windows callback convention. |
Jaroslavas Počepko | c586b5b | 2011-08-30 22:02:02 +1000 | [diff] [blame] | 310 | PUSHFQ |
| 311 | SUBQ $64, SP |
| 312 | MOVQ DI, 56(SP) |
| 313 | MOVQ SI, 48(SP) |
| 314 | MOVQ BP, 40(SP) |
| 315 | MOVQ BX, 32(SP) |
| 316 | MOVQ R12, 24(SP) |
| 317 | MOVQ R13, 16(SP) |
| 318 | MOVQ R14, 8(SP) |
| 319 | MOVQ R15, 0(SP) |
| 320 | |
Russ Cox | 8a1b3d5 | 2012-03-08 15:53:11 -0500 | [diff] [blame] | 321 | // prepare call stack. use SUBQ to hide from stack frame checks |
Russ Cox | 3d2dfc5 | 2013-02-22 16:08:56 -0500 | [diff] [blame] | 322 | // cgocallback(Go func, void *frame, uintptr framesize) |
Russ Cox | 8a1b3d5 | 2012-03-08 15:53:11 -0500 | [diff] [blame] | 323 | SUBQ $24, SP |
Alex Brainman | 05a5de3 | 2013-06-24 17:17:45 +1000 | [diff] [blame] | 324 | MOVQ DX, 16(SP) // argsize (including return value) |
| 325 | MOVQ CX, 8(SP) // callback parameters |
| 326 | MOVQ AX, 0(SP) // address of target Go function |
Jaroslavas Počepko | c586b5b | 2011-08-30 22:02:02 +1000 | [diff] [blame] | 327 | CLD |
Alex Brainman | 05a5de3 | 2013-06-24 17:17:45 +1000 | [diff] [blame] | 328 | CALL runtime·cgocallback_gofunc(SB) |
Russ Cox | 8a1b3d5 | 2012-03-08 15:53:11 -0500 | [diff] [blame] | 329 | MOVQ 0(SP), AX |
| 330 | MOVQ 8(SP), CX |
| 331 | MOVQ 16(SP), DX |
| 332 | ADDQ $24, SP |
Jaroslavas Počepko | c586b5b | 2011-08-30 22:02:02 +1000 | [diff] [blame] | 333 | |
| 334 | // restore registers as required for windows callback |
Jaroslavas Počepko | c586b5b | 2011-08-30 22:02:02 +1000 | [diff] [blame] | 335 | MOVQ 0(SP), R15 |
| 336 | MOVQ 8(SP), R14 |
| 337 | MOVQ 16(SP), R13 |
| 338 | MOVQ 24(SP), R12 |
| 339 | MOVQ 32(SP), BX |
| 340 | MOVQ 40(SP), BP |
| 341 | MOVQ 48(SP), SI |
| 342 | MOVQ 56(SP), DI |
| 343 | ADDQ $64, SP |
| 344 | POPFQ |
| 345 | |
| 346 | MOVL -8(CX)(DX*1), AX // return value |
| 347 | POPQ -8(CX)(DX*1) // restore bytes just after the args |
Wei Guangjing | f83609f | 2011-06-29 17:37:56 +1000 | [diff] [blame] | 348 | RET |
| 349 | |
Hector Chu | 0f5902d | 2011-08-29 22:12:56 +1000 | [diff] [blame] | 350 | // uint32 tstart_stdcall(M *newm); |
Keith Randall | 0273dc1 | 2013-08-07 12:20:05 -0700 | [diff] [blame] | 351 | TEXT runtime·tstart_stdcall(SB),NOSPLIT,$0 |
Hector Chu | 0f5902d | 2011-08-29 22:12:56 +1000 | [diff] [blame] | 352 | // CX contains first arg newm |
Wei Guangjing | f83609f | 2011-06-29 17:37:56 +1000 | [diff] [blame] | 353 | MOVQ m_g0(CX), DX // g |
| 354 | |
Wei Guangjing | f83609f | 2011-06-29 17:37:56 +1000 | [diff] [blame] | 355 | // Layout new m scheduler stack on os stack. |
| 356 | MOVQ SP, AX |
Russ Cox | 8ac35be | 2014-09-09 14:02:37 -0400 | [diff] [blame] | 357 | MOVQ AX, (g_stack+stack_hi)(DX) |
Hector Chu | 0f5902d | 2011-08-29 22:12:56 +1000 | [diff] [blame] | 358 | SUBQ $(64*1024), AX // stack size |
Russ Cox | 8ac35be | 2014-09-09 14:02:37 -0400 | [diff] [blame] | 359 | MOVQ AX, (g_stack+stack_lo)(DX) |
Alex Brainman | b27c061 | 2014-11-19 11:55:15 +1100 | [diff] [blame] | 360 | ADDQ $const__StackGuard, AX |
Russ Cox | e6d3511 | 2015-01-05 16:29:21 +0000 | [diff] [blame] | 361 | MOVQ AX, g_stackguard0(DX) |
| 362 | MOVQ AX, g_stackguard1(DX) |
Wei Guangjing | f83609f | 2011-06-29 17:37:56 +1000 | [diff] [blame] | 363 | |
| 364 | // Set up tls. |
| 365 | LEAQ m_tls(CX), SI |
Wei Guangjing | 9569c67 | 2012-01-09 11:23:07 +1100 | [diff] [blame] | 366 | MOVQ SI, 0x28(GS) |
Russ Cox | 89f185f | 2014-06-26 11:54:39 -0400 | [diff] [blame] | 367 | MOVQ CX, g_m(DX) |
Wei Guangjing | f83609f | 2011-06-29 17:37:56 +1000 | [diff] [blame] | 368 | MOVQ DX, g(SI) |
| 369 | |
| 370 | // Someday the convention will be D is always cleared. |
| 371 | CLD |
| 372 | |
Hector Chu | 0f5902d | 2011-08-29 22:12:56 +1000 | [diff] [blame] | 373 | CALL runtime·stackcheck(SB) // clobbers AX,CX |
Russ Cox | e6a3e22 | 2013-03-01 11:44:43 -0500 | [diff] [blame] | 374 | CALL runtime·mstart(SB) |
Wei Guangjing | f83609f | 2011-06-29 17:37:56 +1000 | [diff] [blame] | 375 | |
Wei Guangjing | f83609f | 2011-06-29 17:37:56 +1000 | [diff] [blame] | 376 | XORL AX, AX // return 0 == success |
Wei Guangjing | f83609f | 2011-06-29 17:37:56 +1000 | [diff] [blame] | 377 | RET |
| 378 | |
Wei Guangjing | f83609f | 2011-06-29 17:37:56 +1000 | [diff] [blame] | 379 | // set tls base to DI |
Keith Randall | 0273dc1 | 2013-08-07 12:20:05 -0700 | [diff] [blame] | 380 | TEXT runtime·settls(SB),NOSPLIT,$0 |
Wei Guangjing | 9569c67 | 2012-01-09 11:23:07 +1100 | [diff] [blame] | 381 | MOVQ DI, 0x28(GS) |
Wei Guangjing | f83609f | 2011-06-29 17:37:56 +1000 | [diff] [blame] | 382 | RET |
Alex Brainman | afe0e97 | 2012-05-30 15:10:54 +1000 | [diff] [blame] | 383 | |
Alex Brainman | 45cff65 | 2013-07-16 12:36:05 +1000 | [diff] [blame] | 384 | // Sleep duration is in 100ns units. |
Keith Randall | 0273dc1 | 2013-08-07 12:20:05 -0700 | [diff] [blame] | 385 | TEXT runtime·usleep1(SB),NOSPLIT,$0 |
Russ Cox | 25f6b02 | 2014-08-27 11:32:17 -0400 | [diff] [blame] | 386 | MOVL usec+0(FP), BX |
Alex Brainman | 45cff65 | 2013-07-16 12:36:05 +1000 | [diff] [blame] | 387 | MOVQ $runtime·usleep2(SB), AX // to hide from 6l |
| 388 | |
| 389 | // Execute call on m->g0 stack, in case we are not actually |
| 390 | // calling a system call wrapper, like when running under WINE. |
| 391 | get_tls(R15) |
| 392 | CMPQ R15, $0 |
| 393 | JNE 3(PC) |
| 394 | // Not a Go-managed thread. Do not switch stack. |
Russ Cox | 8aafb44 | 2013-03-07 09:18:48 -0500 | [diff] [blame] | 395 | CALL AX |
| 396 | RET |
| 397 | |
Russ Cox | 89f185f | 2014-06-26 11:54:39 -0400 | [diff] [blame] | 398 | MOVQ g(R15), R13 |
| 399 | MOVQ g_m(R13), R13 |
Dmitriy Vyukov | 5e72fae | 2014-02-12 22:31:36 +0400 | [diff] [blame] | 400 | |
| 401 | // leave pc/sp for cpu profiler |
| 402 | MOVQ (SP), R12 |
| 403 | MOVQ R12, m_libcallpc(R13) |
Dmitriy Vyukov | eca55f5 | 2014-02-14 09:20:51 +0400 | [diff] [blame] | 404 | MOVQ g(R15), R12 |
| 405 | MOVQ R12, m_libcallg(R13) |
| 406 | // sp must be the last, because once async cpu profiler finds |
| 407 | // all three values to be non-zero, it will use them |
Russ Cox | 25f6b02 | 2014-08-27 11:32:17 -0400 | [diff] [blame] | 408 | LEAQ usec+0(FP), R12 |
Dmitriy Vyukov | 5e72fae | 2014-02-12 22:31:36 +0400 | [diff] [blame] | 409 | MOVQ R12, m_libcallsp(R13) |
Dmitriy Vyukov | 5e72fae | 2014-02-12 22:31:36 +0400 | [diff] [blame] | 410 | |
| 411 | MOVQ m_g0(R13), R14 |
Alex Brainman | 45cff65 | 2013-07-16 12:36:05 +1000 | [diff] [blame] | 412 | CMPQ g(R15), R14 |
Russ Cox | b55791e | 2014-10-28 21:50:16 -0400 | [diff] [blame] | 413 | JNE switch |
Alex Brainman | 45cff65 | 2013-07-16 12:36:05 +1000 | [diff] [blame] | 414 | // executing on m->g0 already |
| 415 | CALL AX |
Russ Cox | b55791e | 2014-10-28 21:50:16 -0400 | [diff] [blame] | 416 | JMP ret |
Alex Brainman | 45cff65 | 2013-07-16 12:36:05 +1000 | [diff] [blame] | 417 | |
Russ Cox | b55791e | 2014-10-28 21:50:16 -0400 | [diff] [blame] | 418 | switch: |
Alex Brainman | 45cff65 | 2013-07-16 12:36:05 +1000 | [diff] [blame] | 419 | // Switch to m->g0 stack and back. |
| 420 | MOVQ (g_sched+gobuf_sp)(R14), R14 |
| 421 | MOVQ SP, -8(R14) |
| 422 | LEAQ -8(R14), SP |
| 423 | CALL AX |
| 424 | MOVQ 0(SP), SP |
Dmitriy Vyukov | 5e72fae | 2014-02-12 22:31:36 +0400 | [diff] [blame] | 425 | |
Russ Cox | b55791e | 2014-10-28 21:50:16 -0400 | [diff] [blame] | 426 | ret: |
Dmitriy Vyukov | 5e72fae | 2014-02-12 22:31:36 +0400 | [diff] [blame] | 427 | MOVQ $0, m_libcallsp(R13) |
Alex Brainman | 45cff65 | 2013-07-16 12:36:05 +1000 | [diff] [blame] | 428 | RET |
| 429 | |
| 430 | // Runs on OS stack. duration (in 100ns units) is in BX. |
Alex Brainman | 418b39d | 2014-07-10 14:23:50 +1000 | [diff] [blame] | 431 | TEXT runtime·usleep2(SB),NOSPLIT,$16 |
| 432 | MOVQ SP, AX |
| 433 | ANDQ $~15, SP // alignment as per Windows requirement |
| 434 | MOVQ AX, 8(SP) |
Alex Brainman | 45cff65 | 2013-07-16 12:36:05 +1000 | [diff] [blame] | 435 | // Want negative 100ns units. |
Russ Cox | 8aafb44 | 2013-03-07 09:18:48 -0500 | [diff] [blame] | 436 | NEGQ BX |
| 437 | MOVQ SP, R8 // ptime |
| 438 | MOVQ BX, (R8) |
| 439 | MOVQ $-1, CX // handle |
| 440 | MOVQ $0, DX // alertable |
Alex Brainman | b27c061 | 2014-11-19 11:55:15 +1100 | [diff] [blame] | 441 | MOVQ runtime·_NtWaitForSingleObject(SB), AX |
Russ Cox | 8aafb44 | 2013-03-07 09:18:48 -0500 | [diff] [blame] | 442 | CALL AX |
Alex Brainman | 418b39d | 2014-07-10 14:23:50 +1000 | [diff] [blame] | 443 | MOVQ 8(SP), SP |
Russ Cox | 8aafb44 | 2013-03-07 09:18:48 -0500 | [diff] [blame] | 444 | RET |
Russ Cox | 13d0b82 | 2014-09-07 23:40:59 -0400 | [diff] [blame] | 445 | |
| 446 | // func now() (sec int64, nsec int32) |
| 447 | TEXT time·now(SB),NOSPLIT,$8-12 |
| 448 | CALL runtime·unixnano(SB) |
| 449 | MOVQ 0(SP), AX |
| 450 | |
| 451 | // generated code for |
| 452 | // func f(x uint64) (uint64, uint64) { return x/1000000000, x%100000000 } |
| 453 | // adapted to reduce duplication |
| 454 | MOVQ AX, CX |
| 455 | MOVQ $1360296554856532783, AX |
| 456 | MULQ CX |
| 457 | ADDQ CX, DX |
| 458 | RCRQ $1, DX |
| 459 | SHRQ $29, DX |
| 460 | MOVQ DX, sec+0(FP) |
| 461 | IMULQ $1000000000, DX |
| 462 | SUBQ DX, CX |
| 463 | MOVL CX, nsec+8(FP) |
| 464 | RET |
| 465 | |