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 5 #include "go_asm.h" 6 #include "go_tls.h" 7 #include "textflag.h" 8 9 // void runtimeasmstdcall(void *c); 10 TEXT runtimeasmstdcall(SB),NOSPLIT,$0 11 MOVL fn+0(FP), BX 12 13 // SetLastError(0). 14 MOVL $0, 0x34(FS) 15 16 // Copy args to the stack. 17 MOVL SP, BP 18 MOVL libcall_n(BX), CX // words 19 MOVL CX, AX 20 SALL $2, AX 21 SUBL AX, SP // room for args 22 MOVL SP, DI 23 MOVL libcall_args(BX), SI 24 CLD 25 REP; MOVSL 26 27 // Call stdcall or cdecl function. 28 // DI SI BP BX are preserved, SP is not 29 CALL libcall_fn(BX) 30 MOVL BP, SP 31 32 // Return result. 33 MOVL fn+0(FP), BX 34 MOVL AX, libcall_r1(BX) 35 MOVL DX, libcall_r2(BX) 36 37 // GetLastError(). 38 MOVL 0x34(FS), AX 39 MOVL AX, libcall_err(BX) 40 41 RET 42 43 TEXT runtimebadsignal2(SB),NOSPLIT,$24 44 // stderr 45 MOVL $-12, 0(SP) 46 MOVL SP, BP 47 CALL *runtime_GetStdHandle(SB) 48 MOVL BP, SP 49 50 MOVL AX, 0(SP) // handle 51 MOVL $runtimebadsignalmsg(SB), DX // pointer 52 MOVL DX, 4(SP) 53 MOVL runtimebadsignallen(SB), DX // count 54 MOVL DX, 8(SP) 55 LEAL 20(SP), DX // written count 56 MOVL $0, 0(DX) 57 MOVL DX, 12(SP) 58 MOVL $0, 16(SP) // overlapped 59 CALL *runtime_WriteFile(SB) 60 MOVL BP, SI 61 RET 62 63 // faster get/set last error 64 TEXT runtimegetlasterror(SB),NOSPLIT,$0 65 MOVL 0x34(FS), AX 66 MOVL AX, ret+0(FP) 67 RET 68 69 TEXT runtimesetlasterror(SB),NOSPLIT,$0 70 MOVL err+0(FP), AX 71 MOVL AX, 0x34(FS) 72 RET 73 74 // Called by Windows as a Vectored Exception Handler (VEH). 75 // First argument is pointer to struct containing 76 // exception record and context pointers. 77 // Handler function is stored in AX. 78 // Return 0 for 'not handled', -1 for handled. 79 TEXT runtimesigtramp(SB),NOSPLIT,$0-0 80 MOVL ptrs+0(FP), CX 81 SUBL $40, SP 82 83 // save callee-saved registers 84 MOVL BX, 28(SP) 85 MOVL BP, 16(SP) 86 MOVL SI, 20(SP) 87 MOVL DI, 24(SP) 88 89 MOVL AX, SI // save handler address 90 91 // find g 92 get_tls(DX) 93 CMPL DX, $0 94 JNE 3(PC) 95 MOVL $0, AX // continue 96 JMP done 97 MOVL g(DX), DX 98 CMPL DX, $0 99 JNE 2(PC) 100 CALL runtimebadsignal2(SB) 101 102 // save g and SP in case of stack switch 103 MOVL DX, 32(SP) // g 104 MOVL SP, 36(SP) 105 106 // do we need to switch to the g0 stack? 107 MOVL g_m(DX), BX 108 MOVL m_g0(BX), BX 109 CMPL DX, BX 110 JEQ g0 111 112 // switch to the g0 stack 113 get_tls(BP) 114 MOVL BX, g(BP) 115 MOVL (g_sched+gobuf_sp)(BX), DI 116 // make it look like mstart called us on g0, to stop traceback 117 SUBL $4, DI 118 MOVL $runtimemstart(SB), 0(DI) 119 // traceback will think that we've done SUBL 120 // on this stack, so subtract them here to match. 121 // (we need room for sighandler arguments anyway). 122 // and re-save old SP for restoring later. 123 SUBL $40, DI 124 MOVL SP, 36(DI) 125 MOVL DI, SP 126 127 g0: 128 MOVL 0(CX), BX // ExceptionRecord* 129 MOVL 4(CX), CX // Context* 130 MOVL BX, 0(SP) 131 MOVL CX, 4(SP) 132 MOVL DX, 8(SP) 133 CALL SI // call handler 134 // AX is set to report result back to Windows 135 MOVL 12(SP), AX 136 137 // switch back to original stack and g 138 // no-op if we never left. 139 MOVL 36(SP), SP 140 MOVL 32(SP), DX 141 get_tls(BP) 142 MOVL DX, g(BP) 143 144 done: 145 // restore callee-saved registers 146 MOVL 24(SP), DI 147 MOVL 20(SP), SI 148 MOVL 16(SP), BP 149 MOVL 28(SP), BX 150 151 ADDL $40, SP 152 // RET 4 (return and pop 4 bytes parameters) 153 BYTE $0xC2; WORD $4 154 RET // unreached; make assembler happy 155 156 TEXT runtimeexceptiontramp(SB),NOSPLIT,$0 157 MOVL $runtimeexceptionhandler(SB), AX 158 JMP runtimesigtramp(SB) 159 160 TEXT runtimefirstcontinuetramp(SB),NOSPLIT,$0-0 161 // is never called 162 INT $3 163 164 TEXT runtimelastcontinuetramp(SB),NOSPLIT,$0-0 165 MOVL $runtimelastcontinuehandler(SB), AX 166 JMP runtimesigtramp(SB) 167 168 TEXT runtimectrlhandler(SB),NOSPLIT,$0 169 PUSHL $runtimectrlhandler1(SB) 170 CALL runtimeexternalthreadhandler(SB) 171 MOVL 4(SP), CX 172 ADDL $12, SP 173 JMP CX 174 175 TEXT runtimeprofileloop(SB),NOSPLIT,$0 176 PUSHL $runtimeprofileloop1(SB) 177 CALL runtimeexternalthreadhandler(SB) 178 MOVL 4(SP), CX 179 ADDL $12, SP 180 JMP CX 181 182 TEXT runtimeexternalthreadhandler(SB),NOSPLIT,$0 183 PUSHL BP 184 MOVL SP, BP 185 PUSHL BX 186 PUSHL SI 187 PUSHL DI 188 PUSHL 0x14(FS) 189 MOVL SP, DX 190 191 // setup dummy m, g 192 SUBL $m__size, SP // space for M 193 MOVL SP, 0(SP) 194 MOVL $m__size, 4(SP) 195 CALL runtimememclr(SB) // smashes AX,BX,CX 196 197 LEAL m_tls(SP), CX 198 MOVL CX, 0x14(FS) 199 MOVL SP, BX 200 SUBL $g__size, SP // space for G 201 MOVL SP, g(CX) 202 MOVL SP, m_g0(BX) 203 204 MOVL SP, 0(SP) 205 MOVL $g__size, 4(SP) 206 CALL runtimememclr(SB) // smashes AX,BX,CX 207 LEAL g__size(SP), BX 208 MOVL BX, g_m(SP) 209 LEAL -8192(SP), CX 210 MOVL CX, (g_stack+stack_lo)(SP) 211 ADDL $const__StackGuard, CX 212 MOVL CX, g_stackguard0(SP) 213 MOVL CX, g_stackguard1(SP) 214 MOVL DX, (g_stack+stack_hi)(SP) 215 216 PUSHL AX // room for return value 217 PUSHL 16(BP) // arg for handler 218 CALL 8(BP) 219 POPL CX 220 POPL AX // pass return value to Windows in AX 221 222 get_tls(CX) 223 MOVL g(CX), CX 224 MOVL (g_stack+stack_hi)(CX), SP 225 POPL 0x14(FS) 226 POPL DI 227 POPL SI 228 POPL BX 229 POPL BP 230 RET 231 232 GLOBL runtimecbctxts(SB), NOPTR, $4 233 234 TEXT runtimecallbackasm1+0(SB),NOSPLIT,$0 235 MOVL 0(SP), AX // will use to find our callback context 236 237 // remove return address from stack, we are not returning there 238 ADDL $4, SP 239 240 // address to callback parameters into CX 241 LEAL 4(SP), CX 242 243 // save registers as required for windows callback 244 PUSHL DI 245 PUSHL SI 246 PUSHL BP 247 PUSHL BX 248 249 // determine index into runtimecbctxts table 250 SUBL $runtimecallbackasm(SB), AX 251 MOVL $0, DX 252 MOVL $5, BX // divide by 5 because each call instruction in runtimecallbacks is 5 bytes long 253 DIVL BX 254 255 // find correspondent runtimecbctxts table entry 256 MOVL runtimecbctxts(SB), BX 257 MOVL -4(BX)(AX*4), BX 258 259 // extract callback context 260 MOVL wincallbackcontext_gobody(BX), AX 261 MOVL wincallbackcontext_argsize(BX), DX 262 263 // preserve whatever's at the memory location that 264 // the callback will use to store the return value 265 PUSHL 0(CX)(DX*1) 266 267 // extend argsize by size of return value 268 ADDL $4, DX 269 270 // remember how to restore stack on return 271 MOVL wincallbackcontext_restorestack(BX), BX 272 PUSHL BX 273 274 // call target Go function 275 PUSHL DX // argsize (including return value) 276 PUSHL CX // callback parameters 277 PUSHL AX // address of target Go function 278 CLD 279 CALL runtimecgocallback_gofunc(SB) 280 POPL AX 281 POPL CX 282 POPL DX 283 284 // how to restore stack on return 285 POPL BX 286 287 // return value into AX (as per Windows spec) 288 // and restore previously preserved value 289 MOVL -4(CX)(DX*1), AX 290 POPL -4(CX)(DX*1) 291 292 MOVL BX, CX // cannot use BX anymore 293 294 // restore registers as required for windows callback 295 POPL BX 296 POPL BP 297 POPL SI 298 POPL DI 299 300 // remove callback parameters before return (as per Windows spec) 301 POPL DX 302 ADDL CX, SP 303 PUSHL DX 304 305 CLD 306 307 RET 308 309 // void tstart(M *newm); 310 TEXT runtimetstart(SB),NOSPLIT,$0 311 MOVL newm+4(SP), CX // m 312 MOVL m_g0(CX), DX // g 313 314 // Layout new m scheduler stack on os stack. 315 MOVL SP, AX 316 MOVL AX, (g_stack+stack_hi)(DX) 317 SUBL $(64*1024), AX // stack size 318 MOVL AX, (g_stack+stack_lo)(DX) 319 ADDL $const__StackGuard, AX 320 MOVL AX, g_stackguard0(DX) 321 MOVL AX, g_stackguard1(DX) 322 323 // Set up tls. 324 LEAL m_tls(CX), SI 325 MOVL SI, 0x14(FS) 326 MOVL CX, g_m(DX) 327 MOVL DX, g(SI) 328 329 // Someday the convention will be D is always cleared. 330 CLD 331 332 CALL runtimestackcheck(SB) // clobbers AX,CX 333 CALL runtimemstart(SB) 334 335 RET 336 337 // uint32 tstart_stdcall(M *newm); 338 TEXT runtimetstart_stdcall(SB),NOSPLIT,$0 339 MOVL newm+4(SP), BX 340 341 PUSHL BX 342 CALL runtimetstart(SB) 343 POPL BX 344 345 // Adjust stack for stdcall to return properly. 346 MOVL (SP), AX // save return address 347 ADDL $4, SP // remove single parameter 348 MOVL AX, (SP) // restore return address 349 350 XORL AX, AX // return 0 == success 351 352 RET 353 354 // setldt(int entry, int address, int limit) 355 TEXT runtimesetldt(SB),NOSPLIT,$0 356 MOVL address+4(FP), CX 357 MOVL CX, 0x14(FS) 358 RET 359 360 // Sleep duration is in 100ns units. 361 TEXT runtimeusleep1(SB),NOSPLIT,$0 362 MOVL usec+0(FP), BX 363 MOVL $runtimeusleep2(SB), AX // to hide from 8l 364 365 // Execute call on m->g0 stack, in case we are not actually 366 // calling a system call wrapper, like when running under WINE. 367 get_tls(CX) 368 CMPL CX, $0 369 JNE 3(PC) 370 // Not a Go-managed thread. Do not switch stack. 371 CALL AX 372 RET 373 374 MOVL g(CX), BP 375 MOVL g_m(BP), BP 376 377 // leave pc/sp for cpu profiler 378 MOVL (SP), SI 379 MOVL SI, m_libcallpc(BP) 380 MOVL g(CX), SI 381 MOVL SI, m_libcallg(BP) 382 // sp must be the last, because once async cpu profiler finds 383 // all three values to be non-zero, it will use them 384 LEAL usec+0(FP), SI 385 MOVL SI, m_libcallsp(BP) 386 387 MOVL m_g0(BP), SI 388 CMPL g(CX), SI 389 JNE switch 390 // executing on m->g0 already 391 CALL AX 392 JMP ret 393 394 switch: 395 // Switch to m->g0 stack and back. 396 MOVL (g_sched+gobuf_sp)(SI), SI 397 MOVL SP, -4(SI) 398 LEAL -4(SI), SP 399 CALL AX 400 MOVL 0(SP), SP 401 402 ret: 403 get_tls(CX) 404 MOVL g(CX), BP 405 MOVL g_m(BP), BP 406 MOVL $0, m_libcallsp(BP) 407 RET 408 409 // Runs on OS stack. duration (in 100ns units) is in BX. 410 TEXT runtimeusleep2(SB),NOSPLIT,$20 411 // Want negative 100ns units. 412 NEGL BX 413 MOVL $-1, hi-4(SP) 414 MOVL BX, lo-8(SP) 415 LEAL lo-8(SP), BX 416 MOVL BX, ptime-12(SP) 417 MOVL $0, alertable-16(SP) 418 MOVL $-1, handle-20(SP) 419 MOVL SP, BP 420 MOVL runtime_NtWaitForSingleObject(SB), AX 421 CALL AX 422 MOVL BP, SP 423 RET 424 425 // func now() (sec int64, nsec int32) 426 TEXT timenow(SB),NOSPLIT,$8-12 427 CALL runtimeunixnano(SB) 428 MOVL 0(SP), AX 429 MOVL 4(SP), DX 430 431 MOVL $1000000000, CX 432 DIVL CX 433 MOVL AX, sec+0(FP) 434 MOVL $0, sec+4(FP) 435 MOVL DX, nsec+8(FP) 436 RET 437