github.com/twelsh-aw/go/src@v0.0.0-20230516233729-a56fe86a7c81/runtime/sys_windows_arm.s (about)

     1  // Copyright 2018 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  #include "time_windows.h"
     9  
    10  // Note: For system ABI, R0-R3 are args, R4-R11 are callee-save.
    11  
    12  // void runtime·asmstdcall(void *c);
    13  TEXT runtime·asmstdcall(SB),NOSPLIT|NOFRAME,$0
    14  	MOVM.DB.W [R4, R5, R14], (R13)	// push {r4, r5, lr}
    15  	MOVW	R0, R4			// put libcall * in r4
    16  	MOVW	R13, R5			// save stack pointer in r5
    17  
    18  	// SetLastError(0)
    19  	MOVW	$0, R0
    20  	MRC	15, 0, R1, C13, C0, 2
    21  	MOVW	R0, 0x34(R1)
    22  
    23  	MOVW	8(R4), R12	// libcall->args
    24  
    25  	// Do we have more than 4 arguments?
    26  	MOVW	4(R4), R0	// libcall->n
    27  	SUB.S	$4, R0, R2
    28  	BLE	loadregs
    29  
    30  	// Reserve stack space for remaining args
    31  	SUB	R2<<2, R13
    32  	BIC	$0x7, R13	// alignment for ABI
    33  
    34  	// R0: count of arguments
    35  	// R1:
    36  	// R2: loop counter, from 0 to (n-4)
    37  	// R3: scratch
    38  	// R4: pointer to libcall struct
    39  	// R12: libcall->args
    40  	MOVW	$0, R2
    41  stackargs:
    42  	ADD	$4, R2, R3		// r3 = args[4 + i]
    43  	MOVW	R3<<2(R12), R3
    44  	MOVW	R3, R2<<2(R13)		// stack[i] = r3
    45  
    46  	ADD	$1, R2			// i++
    47  	SUB	$4, R0, R3		// while (i < (n - 4))
    48  	CMP	R3, R2
    49  	BLT	stackargs
    50  
    51  loadregs:
    52  	CMP	$3, R0
    53  	MOVW.GT 12(R12), R3
    54  
    55  	CMP	$2, R0
    56  	MOVW.GT 8(R12), R2
    57  
    58  	CMP	$1, R0
    59  	MOVW.GT 4(R12), R1
    60  
    61  	CMP	$0, R0
    62  	MOVW.GT 0(R12), R0
    63  
    64  	BIC	$0x7, R13		// alignment for ABI
    65  	MOVW	0(R4), R12		// branch to libcall->fn
    66  	BL	(R12)
    67  
    68  	MOVW	R5, R13			// free stack space
    69  	MOVW	R0, 12(R4)		// save return value to libcall->r1
    70  	MOVW	R1, 16(R4)
    71  
    72  	// GetLastError
    73  	MRC	15, 0, R1, C13, C0, 2
    74  	MOVW	0x34(R1), R0
    75  	MOVW	R0, 20(R4)		// store in libcall->err
    76  
    77  	MOVM.IA.W (R13), [R4, R5, R15]
    78  
    79  TEXT runtime·getlasterror(SB),NOSPLIT,$0
    80  	MRC	15, 0, R0, C13, C0, 2
    81  	MOVW	0x34(R0), R0
    82  	MOVW	R0, ret+0(FP)
    83  	RET
    84  
    85  // Called by Windows as a Vectored Exception Handler (VEH).
    86  // R0 is pointer to struct containing
    87  // exception record and context pointers.
    88  // R1 is the kind of sigtramp function.
    89  // Return value of sigtrampgo is stored in R0.
    90  TEXT sigtramp<>(SB),NOSPLIT|NOFRAME,$0
    91  	MOVM.DB.W [R4-R11, R14], (R13)	// push {r4-r11, lr} (SP-=40)
    92  	SUB	$(16), R13		// reserve space for parameters/retval to go call
    93  
    94  	MOVW	R0, R6			// Save param0
    95  	MOVW	R1, R7			// Save param1
    96  	BL	runtime·load_g(SB)	// Clobbers R0
    97  
    98  	MOVW	$0, R4
    99  	MOVW	R4, 0(R13)	// No saved link register.
   100  	MOVW	R6, 4(R13)	// Move arg0 into position
   101  	MOVW	R7, 8(R13)	// Move arg1 into position
   102  	BL	runtime·sigtrampgo(SB)
   103  	MOVW	12(R13), R0	// Fetch return value from stack
   104  
   105  	ADD	$(16), R13			// free locals
   106  	MOVM.IA.W (R13), [R4-R11, R14]	// pop {r4-r11, lr}
   107  
   108  	B	(R14)				// return
   109  
   110  // Trampoline to resume execution from exception handler.
   111  // This is part of the control flow guard workaround.
   112  // It switches stacks and jumps to the continuation address.
   113  // R0 and R1 are set above at the end of sigtrampgo
   114  // in the context that starts executing at sigresume.
   115  TEXT runtime·sigresume(SB),NOSPLIT|NOFRAME,$0
   116  	// Important: do not smash LR,
   117  	// which is set to a live value when handling
   118  	// a signal by pushing a call to sigpanic onto the stack.
   119  	MOVW	R0, R13
   120  	B	(R1)
   121  
   122  TEXT runtime·exceptiontramp(SB),NOSPLIT|NOFRAME,$0
   123  	MOVW	$const_callbackVEH, R1
   124  	B	sigtramp<>(SB)
   125  
   126  TEXT runtime·firstcontinuetramp(SB),NOSPLIT|NOFRAME,$0
   127  	MOVW	$const_callbackFirstVCH, R1
   128  	B	sigtramp<>(SB)
   129  
   130  TEXT runtime·lastcontinuetramp(SB),NOSPLIT|NOFRAME,$0
   131  	MOVW	$const_callbackLastVCH, R1
   132  	B	sigtramp<>(SB)
   133  
   134  TEXT runtime·callbackasm1(SB),NOSPLIT|NOFRAME,$0
   135  	// On entry, the trampoline in zcallback_windows_arm.s left
   136  	// the callback index in R12 (which is volatile in the C ABI).
   137  
   138  	// Push callback register arguments r0-r3. We do this first so
   139  	// they're contiguous with stack arguments.
   140  	MOVM.DB.W [R0-R3], (R13)
   141  	// Push C callee-save registers r4-r11 and lr.
   142  	MOVM.DB.W [R4-R11, R14], (R13)
   143  	SUB	$(16 + callbackArgs__size), R13	// space for locals
   144  
   145  	// Create a struct callbackArgs on our stack.
   146  	MOVW	R12, (16+callbackArgs_index)(R13)	// callback index
   147  	MOVW	$(16+callbackArgs__size+4*9)(R13), R0
   148  	MOVW	R0, (16+callbackArgs_args)(R13)		// address of args vector
   149  	MOVW	$0, R0
   150  	MOVW	R0, (16+callbackArgs_result)(R13)	// result
   151  
   152  	// Prepare for entry to Go.
   153  	BL	runtime·load_g(SB)
   154  
   155  	// Call cgocallback, which will call callbackWrap(frame).
   156  	MOVW	$0, R0
   157  	MOVW	R0, 12(R13)	// context
   158  	MOVW	$16(R13), R1	// R1 = &callbackArgs{...}
   159  	MOVW	R1, 8(R13)	// frame (address of callbackArgs)
   160  	MOVW	$·callbackWrap(SB), R1
   161  	MOVW	R1, 4(R13)	// PC of function to call
   162  	BL	runtime·cgocallback(SB)
   163  
   164  	// Get callback result.
   165  	MOVW	(16+callbackArgs_result)(R13), R0
   166  
   167  	ADD	$(16 + callbackArgs__size), R13	// free locals
   168  	MOVM.IA.W (R13), [R4-R11, R12]	// pop {r4-r11, lr=>r12}
   169  	ADD	$(4*4), R13	// skip r0-r3
   170  	B	(R12)	// return
   171  
   172  // uint32 tstart_stdcall(M *newm);
   173  TEXT runtime·tstart_stdcall(SB),NOSPLIT|NOFRAME,$0
   174  	MOVM.DB.W [R4-R11, R14], (R13)		// push {r4-r11, lr}
   175  
   176  	MOVW	m_g0(R0), g
   177  	MOVW	R0, g_m(g)
   178  	BL	runtime·save_g(SB)
   179  
   180  	// Layout new m scheduler stack on os stack.
   181  	MOVW	R13, R0
   182  	MOVW	R0, g_stack+stack_hi(g)
   183  	SUB	$(64*1024), R0
   184  	MOVW	R0, (g_stack+stack_lo)(g)
   185  	MOVW	R0, g_stackguard0(g)
   186  	MOVW	R0, g_stackguard1(g)
   187  
   188  	BL	runtime·emptyfunc(SB)	// fault if stack check is wrong
   189  	BL	runtime·mstart(SB)
   190  
   191  	// Exit the thread.
   192  	MOVW	$0, R0
   193  	MOVM.IA.W (R13), [R4-R11, R15]		// pop {r4-r11, pc}
   194  
   195  // Runs on OS stack.
   196  // duration (in -100ns units) is in dt+0(FP).
   197  // g may be nil.
   198  TEXT runtime·usleep2(SB),NOSPLIT|NOFRAME,$0-4
   199  	MOVW	dt+0(FP), R3
   200  	MOVM.DB.W [R4, R14], (R13)	// push {r4, lr}
   201  	MOVW	R13, R4			// Save SP
   202  	SUB	$8, R13			// R13 = R13 - 8
   203  	BIC	$0x7, R13		// Align SP for ABI
   204  	MOVW	$0, R1			// R1 = FALSE (alertable)
   205  	MOVW	$-1, R0			// R0 = handle
   206  	MOVW	R13, R2			// R2 = pTime
   207  	MOVW	R3, 0(R2)		// time_lo
   208  	MOVW	R0, 4(R2)		// time_hi
   209  	MOVW	runtime·_NtWaitForSingleObject(SB), R3
   210  	BL	(R3)
   211  	MOVW	R4, R13			// Restore SP
   212  	MOVM.IA.W (R13), [R4, R15]	// pop {R4, pc}
   213  
   214  // Runs on OS stack.
   215  TEXT runtime·switchtothread(SB),NOSPLIT|NOFRAME,$0
   216  	MOVM.DB.W [R4, R14], (R13)  	// push {R4, lr}
   217  	MOVW    R13, R4
   218  	BIC	$0x7, R13		// alignment for ABI
   219  	MOVW	runtime·_SwitchToThread(SB), R0
   220  	BL	(R0)
   221  	MOVW 	R4, R13			// restore stack pointer
   222  	MOVM.IA.W (R13), [R4, R15]	// pop {R4, pc}
   223  
   224  TEXT ·publicationBarrier(SB),NOSPLIT|NOFRAME,$0-0
   225  	B	runtime·armPublicationBarrier(SB)
   226  
   227  // never called (this is a GOARM=7 platform)
   228  TEXT runtime·read_tls_fallback(SB),NOSPLIT,$0
   229  	MOVW	$0xabcd, R0
   230  	MOVW	R0, (R0)
   231  	RET
   232  
   233  TEXT runtime·nanotime1(SB),NOSPLIT,$0-8
   234  	MOVW	$0, R0
   235  	MOVB	runtime·useQPCTime(SB), R0
   236  	CMP	$0, R0
   237  	BNE	useQPC
   238  	MOVW	$_INTERRUPT_TIME, R3
   239  loop:
   240  	MOVW	time_hi1(R3), R1
   241  	DMB	MB_ISH
   242  	MOVW	time_lo(R3), R0
   243  	DMB	MB_ISH
   244  	MOVW	time_hi2(R3), R2
   245  	CMP	R1, R2
   246  	BNE	loop
   247  
   248  	// wintime = R1:R0, multiply by 100
   249  	MOVW	$100, R2
   250  	MULLU	R0, R2, (R4, R3)    // R4:R3 = R1:R0 * R2
   251  	MULA	R1, R2, R4, R4
   252  
   253  	// wintime*100 = R4:R3
   254  	MOVW	R3, ret_lo+0(FP)
   255  	MOVW	R4, ret_hi+4(FP)
   256  	RET
   257  useQPC:
   258  	RET	runtime·nanotimeQPC(SB)		// tail call
   259  
   260  // save_g saves the g register (R10) into thread local memory
   261  // so that we can call externally compiled
   262  // ARM code that will overwrite those registers.
   263  // NOTE: runtime.gogo assumes that R1 is preserved by this function.
   264  //       runtime.mcall assumes this function only clobbers R0 and R11.
   265  // Returns with g in R0.
   266  // Save the value in the _TEB->TlsSlots array.
   267  // Effectively implements TlsSetValue().
   268  // tls_g stores the TLS slot allocated TlsAlloc().
   269  TEXT runtime·save_g(SB),NOSPLIT,$0
   270  	MRC	15, 0, R0, C13, C0, 2
   271  	ADD	$0xe10, R0
   272  	MOVW 	$runtime·tls_g(SB), R11
   273  	MOVW	(R11), R11
   274  	MOVW	g, R11<<2(R0)
   275  	MOVW	g, R0	// preserve R0 across call to setg<>
   276  	RET
   277  
   278  // load_g loads the g register from thread-local memory,
   279  // for use after calling externally compiled
   280  // ARM code that overwrote those registers.
   281  // Get the value from the _TEB->TlsSlots array.
   282  // Effectively implements TlsGetValue().
   283  TEXT runtime·load_g(SB),NOSPLIT,$0
   284  	MRC	15, 0, R0, C13, C0, 2
   285  	ADD	$0xe10, R0
   286  	MOVW 	$runtime·tls_g(SB), g
   287  	MOVW	(g), g
   288  	MOVW	g<<2(R0), g
   289  	RET
   290  
   291  // This is called from rt0_go, which runs on the system stack
   292  // using the initial stack allocated by the OS.
   293  // It calls back into standard C using the BL below.
   294  // To do that, the stack pointer must be 8-byte-aligned.
   295  TEXT runtime·_initcgo(SB),NOSPLIT|NOFRAME,$0
   296  	MOVM.DB.W [R4, R14], (R13)	// push {r4, lr}
   297  
   298  	// Ensure stack is 8-byte aligned before calling C code
   299  	MOVW	R13, R4
   300  	BIC	$0x7, R13
   301  
   302  	// Allocate a TLS slot to hold g across calls to external code
   303  	MOVW 	$runtime·_TlsAlloc(SB), R0
   304  	MOVW	(R0), R0
   305  	BL	(R0)
   306  
   307  	// Assert that slot is less than 64 so we can use _TEB->TlsSlots
   308  	CMP	$64, R0
   309  	MOVW	$runtime·abort(SB), R1
   310  	BL.GE	(R1)
   311  
   312  	// Save Slot into tls_g
   313  	MOVW 	$runtime·tls_g(SB), R1
   314  	MOVW	R0, (R1)
   315  
   316  	MOVW	R4, R13
   317  	MOVM.IA.W (R13), [R4, R15]	// pop {r4, pc}
   318  
   319  // Holds the TLS Slot, which was allocated by TlsAlloc()
   320  GLOBL runtime·tls_g+0(SB), NOPTR, $4