github.com/aloncn/graphics-go@v0.0.1/src/runtime/sys_windows_386.s (about) 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 runtime·asmstdcall(void *c); 10 TEXT runtime·asmstdcall(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 runtime·badsignal2(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 $runtime·badsignalmsg(SB), DX // pointer 52 MOVL DX, 4(SP) 53 MOVL runtime·badsignallen(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 runtime·getlasterror(SB),NOSPLIT,$0 65 MOVL 0x34(FS), AX 66 MOVL AX, ret+0(FP) 67 RET 68 69 TEXT runtime·setlasterror(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 runtime·sigtramp(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 runtime·badsignal2(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 $runtime·mstart(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 runtime·exceptiontramp(SB),NOSPLIT,$0 157 MOVL $runtime·exceptionhandler(SB), AX 158 JMP runtime·sigtramp(SB) 159 160 TEXT runtime·firstcontinuetramp(SB),NOSPLIT,$0-0 161 // is never called 162 INT $3 163 164 TEXT runtime·lastcontinuetramp(SB),NOSPLIT,$0-0 165 MOVL $runtime·lastcontinuehandler(SB), AX 166 JMP runtime·sigtramp(SB) 167 168 TEXT runtime·ctrlhandler(SB),NOSPLIT,$0 169 PUSHL $runtime·ctrlhandler1(SB) 170 CALL runtime·externalthreadhandler(SB) 171 MOVL 4(SP), CX 172 ADDL $12, SP 173 JMP CX 174 175 TEXT runtime·profileloop(SB),NOSPLIT,$0 176 PUSHL $runtime·profileloop1(SB) 177 CALL runtime·externalthreadhandler(SB) 178 MOVL 4(SP), CX 179 ADDL $12, SP 180 JMP CX 181 182 TEXT runtime·externalthreadhandler(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 runtime·memclr(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 runtime·memclr(SB) // smashes AX,BX,CX 207 LEAL g__size(SP), BX 208 MOVL BX, g_m(SP) 209 210 LEAL -32768(SP), CX // must be less than SizeOfStackReserve set by linker 211 MOVL CX, (g_stack+stack_lo)(SP) 212 ADDL $const__StackGuard, CX 213 MOVL CX, g_stackguard0(SP) 214 MOVL CX, g_stackguard1(SP) 215 MOVL DX, (g_stack+stack_hi)(SP) 216 217 PUSHL AX // room for return value 218 PUSHL 16(BP) // arg for handler 219 CALL 8(BP) 220 POPL CX 221 POPL AX // pass return value to Windows in AX 222 223 get_tls(CX) 224 MOVL g(CX), CX 225 MOVL (g_stack+stack_hi)(CX), SP 226 POPL 0x14(FS) 227 POPL DI 228 POPL SI 229 POPL BX 230 POPL BP 231 RET 232 233 GLOBL runtime·cbctxts(SB), NOPTR, $4 234 235 TEXT runtime·callbackasm1+0(SB),NOSPLIT,$0 236 MOVL 0(SP), AX // will use to find our callback context 237 238 // remove return address from stack, we are not returning there 239 ADDL $4, SP 240 241 // address to callback parameters into CX 242 LEAL 4(SP), CX 243 244 // save registers as required for windows callback 245 PUSHL DI 246 PUSHL SI 247 PUSHL BP 248 PUSHL BX 249 250 // determine index into runtime·cbctxts table 251 SUBL $runtime·callbackasm(SB), AX 252 MOVL $0, DX 253 MOVL $5, BX // divide by 5 because each call instruction in runtime·callbacks is 5 bytes long 254 DIVL BX 255 256 // find correspondent runtime·cbctxts table entry 257 MOVL runtime·cbctxts(SB), BX 258 MOVL -4(BX)(AX*4), BX 259 260 // extract callback context 261 MOVL wincallbackcontext_gobody(BX), AX 262 MOVL wincallbackcontext_argsize(BX), DX 263 264 // preserve whatever's at the memory location that 265 // the callback will use to store the return value 266 PUSHL 0(CX)(DX*1) 267 268 // extend argsize by size of return value 269 ADDL $4, DX 270 271 // remember how to restore stack on return 272 MOVL wincallbackcontext_restorestack(BX), BX 273 PUSHL BX 274 275 // call target Go function 276 PUSHL DX // argsize (including return value) 277 PUSHL CX // callback parameters 278 PUSHL AX // address of target Go function 279 CLD 280 CALL runtime·cgocallback_gofunc(SB) 281 POPL AX 282 POPL CX 283 POPL DX 284 285 // how to restore stack on return 286 POPL BX 287 288 // return value into AX (as per Windows spec) 289 // and restore previously preserved value 290 MOVL -4(CX)(DX*1), AX 291 POPL -4(CX)(DX*1) 292 293 MOVL BX, CX // cannot use BX anymore 294 295 // restore registers as required for windows callback 296 POPL BX 297 POPL BP 298 POPL SI 299 POPL DI 300 301 // remove callback parameters before return (as per Windows spec) 302 POPL DX 303 ADDL CX, SP 304 PUSHL DX 305 306 CLD 307 308 RET 309 310 // void tstart(M *newm); 311 TEXT runtime·tstart(SB),NOSPLIT,$0 312 MOVL newm+4(SP), CX // m 313 MOVL m_g0(CX), DX // g 314 315 // Layout new m scheduler stack on os stack. 316 MOVL SP, AX 317 MOVL AX, (g_stack+stack_hi)(DX) 318 SUBL $(64*1024), AX // stack size 319 MOVL AX, (g_stack+stack_lo)(DX) 320 ADDL $const__StackGuard, AX 321 MOVL AX, g_stackguard0(DX) 322 MOVL AX, g_stackguard1(DX) 323 324 // Set up tls. 325 LEAL m_tls(CX), SI 326 MOVL SI, 0x14(FS) 327 MOVL CX, g_m(DX) 328 MOVL DX, g(SI) 329 330 // Someday the convention will be D is always cleared. 331 CLD 332 333 CALL runtime·stackcheck(SB) // clobbers AX,CX 334 CALL runtime·mstart(SB) 335 336 RET 337 338 // uint32 tstart_stdcall(M *newm); 339 TEXT runtime·tstart_stdcall(SB),NOSPLIT,$0 340 MOVL newm+4(SP), BX 341 342 PUSHL BX 343 CALL runtime·tstart(SB) 344 POPL BX 345 346 // Adjust stack for stdcall to return properly. 347 MOVL (SP), AX // save return address 348 ADDL $4, SP // remove single parameter 349 MOVL AX, (SP) // restore return address 350 351 XORL AX, AX // return 0 == success 352 353 RET 354 355 // setldt(int entry, int address, int limit) 356 TEXT runtime·setldt(SB),NOSPLIT,$0 357 MOVL address+4(FP), CX 358 MOVL CX, 0x14(FS) 359 RET 360 361 // Sleep duration is in 100ns units. 362 TEXT runtime·usleep1(SB),NOSPLIT,$0 363 MOVL usec+0(FP), BX 364 MOVL $runtime·usleep2(SB), AX // to hide from 8l 365 366 // Execute call on m->g0 stack, in case we are not actually 367 // calling a system call wrapper, like when running under WINE. 368 get_tls(CX) 369 CMPL CX, $0 370 JNE 3(PC) 371 // Not a Go-managed thread. Do not switch stack. 372 CALL AX 373 RET 374 375 MOVL g(CX), BP 376 MOVL g_m(BP), BP 377 378 // leave pc/sp for cpu profiler 379 MOVL (SP), SI 380 MOVL SI, m_libcallpc(BP) 381 MOVL g(CX), SI 382 MOVL SI, m_libcallg(BP) 383 // sp must be the last, because once async cpu profiler finds 384 // all three values to be non-zero, it will use them 385 LEAL usec+0(FP), SI 386 MOVL SI, m_libcallsp(BP) 387 388 MOVL m_g0(BP), SI 389 CMPL g(CX), SI 390 JNE switch 391 // executing on m->g0 already 392 CALL AX 393 JMP ret 394 395 switch: 396 // Switch to m->g0 stack and back. 397 MOVL (g_sched+gobuf_sp)(SI), SI 398 MOVL SP, -4(SI) 399 LEAL -4(SI), SP 400 CALL AX 401 MOVL 0(SP), SP 402 403 ret: 404 get_tls(CX) 405 MOVL g(CX), BP 406 MOVL g_m(BP), BP 407 MOVL $0, m_libcallsp(BP) 408 RET 409 410 // Runs on OS stack. duration (in 100ns units) is in BX. 411 TEXT runtime·usleep2(SB),NOSPLIT,$20 412 // Want negative 100ns units. 413 NEGL BX 414 MOVL $-1, hi-4(SP) 415 MOVL BX, lo-8(SP) 416 LEAL lo-8(SP), BX 417 MOVL BX, ptime-12(SP) 418 MOVL $0, alertable-16(SP) 419 MOVL $-1, handle-20(SP) 420 MOVL SP, BP 421 MOVL runtime·_NtWaitForSingleObject(SB), AX 422 CALL AX 423 MOVL BP, SP 424 RET 425 426 // func now() (sec int64, nsec int32) 427 TEXT time·now(SB),NOSPLIT,$8-12 428 CALL runtime·unixnano(SB) 429 MOVL 0(SP), AX 430 MOVL 4(SP), DX 431 432 MOVL $1000000000, CX 433 DIVL CX 434 MOVL AX, sec+0(FP) 435 MOVL $0, sec+4(FP) 436 MOVL DX, nsec+8(FP) 437 RET