github.com/peggyl/go@v0.0.0-20151008231540-ae315999c2d5/src/runtime/sys_linux_arm.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  //
     6  // System calls and other sys.stuff for arm, Linux
     7  //
     8  
     9  #include "go_asm.h"
    10  #include "go_tls.h"
    11  #include "textflag.h"
    12  
    13  // for EABI, as we don't support OABI
    14  #define SYS_BASE 0x0
    15  
    16  #define SYS_exit (SYS_BASE + 1)
    17  #define SYS_read (SYS_BASE + 3)
    18  #define SYS_write (SYS_BASE + 4)
    19  #define SYS_open (SYS_BASE + 5)
    20  #define SYS_close (SYS_BASE + 6)
    21  #define SYS_getpid (SYS_BASE + 20)
    22  #define SYS_kill (SYS_BASE + 37)
    23  #define SYS_gettimeofday (SYS_BASE + 78)
    24  #define SYS_clone (SYS_BASE + 120)
    25  #define SYS_rt_sigreturn (SYS_BASE + 173)
    26  #define SYS_rt_sigaction (SYS_BASE + 174)
    27  #define SYS_rt_sigprocmask (SYS_BASE + 175)
    28  #define SYS_sigaltstack (SYS_BASE + 186)
    29  #define SYS_mmap2 (SYS_BASE + 192)
    30  #define SYS_futex (SYS_BASE + 240)
    31  #define SYS_exit_group (SYS_BASE + 248)
    32  #define SYS_munmap (SYS_BASE + 91)
    33  #define SYS_madvise (SYS_BASE + 220)
    34  #define SYS_setitimer (SYS_BASE + 104)
    35  #define SYS_mincore (SYS_BASE + 219)
    36  #define SYS_gettid (SYS_BASE + 224)
    37  #define SYS_tkill (SYS_BASE + 238)
    38  #define SYS_sched_yield (SYS_BASE + 158)
    39  #define SYS_select (SYS_BASE + 142) // newselect
    40  #define SYS_ugetrlimit (SYS_BASE + 191)
    41  #define SYS_sched_getaffinity (SYS_BASE + 242)
    42  #define SYS_clock_gettime (SYS_BASE + 263)
    43  #define SYS_epoll_create (SYS_BASE + 250)
    44  #define SYS_epoll_ctl (SYS_BASE + 251)
    45  #define SYS_epoll_wait (SYS_BASE + 252)
    46  #define SYS_epoll_create1 (SYS_BASE + 357)
    47  #define SYS_fcntl (SYS_BASE + 55)
    48  #define SYS_access (SYS_BASE + 33)
    49  #define SYS_connect (SYS_BASE + 283)
    50  #define SYS_socket (SYS_BASE + 281)
    51  
    52  #define ARM_BASE (SYS_BASE + 0x0f0000)
    53  
    54  TEXT runtime·open(SB),NOSPLIT,$0
    55  	MOVW	name+0(FP), R0
    56  	MOVW	mode+4(FP), R1
    57  	MOVW	perm+8(FP), R2
    58  	MOVW	$SYS_open, R7
    59  	SWI	$0
    60  	MOVW	$0xfffff001, R1
    61  	CMP	R1, R0
    62  	MOVW.HI	$-1, R0
    63  	MOVW	R0, ret+12(FP)
    64  	RET
    65  
    66  TEXT runtime·closefd(SB),NOSPLIT,$0
    67  	MOVW	fd+0(FP), R0
    68  	MOVW	$SYS_close, R7
    69  	SWI	$0
    70  	MOVW	$0xfffff001, R1
    71  	CMP	R1, R0
    72  	MOVW.HI	$-1, R0
    73  	MOVW	R0, ret+4(FP)
    74  	RET
    75  
    76  TEXT runtime·write(SB),NOSPLIT,$0
    77  	MOVW	fd+0(FP), R0
    78  	MOVW	p+4(FP), R1
    79  	MOVW	n+8(FP), R2
    80  	MOVW	$SYS_write, R7
    81  	SWI	$0
    82  	MOVW	$0xfffff001, R1
    83  	CMP	R1, R0
    84  	MOVW.HI	$-1, R0
    85  	MOVW	R0, ret+12(FP)
    86  	RET
    87  
    88  TEXT runtime·read(SB),NOSPLIT,$0
    89  	MOVW	fd+0(FP), R0
    90  	MOVW	p+4(FP), R1
    91  	MOVW	n+8(FP), R2
    92  	MOVW	$SYS_read, R7
    93  	SWI	$0
    94  	MOVW	$0xfffff001, R1
    95  	CMP	R1, R0
    96  	MOVW.HI	$-1, R0
    97  	MOVW	R0, ret+12(FP)
    98  	RET
    99  
   100  TEXT runtime·getrlimit(SB),NOSPLIT,$0
   101  	MOVW	kind+0(FP), R0
   102  	MOVW	limit+4(FP), R1
   103  	MOVW	$SYS_ugetrlimit, R7
   104  	SWI	$0
   105  	MOVW	R0, ret+8(FP)
   106  	RET
   107  
   108  TEXT runtime·exit(SB),NOSPLIT,$-4
   109  	MOVW	code+0(FP), R0
   110  	MOVW	$SYS_exit_group, R7
   111  	SWI	$0
   112  	MOVW	$1234, R0
   113  	MOVW	$1002, R1
   114  	MOVW	R0, (R1)	// fail hard
   115  
   116  TEXT runtime·exit1(SB),NOSPLIT,$-4
   117  	MOVW	code+0(FP), R0
   118  	MOVW	$SYS_exit, R7
   119  	SWI	$0
   120  	MOVW	$1234, R0
   121  	MOVW	$1003, R1
   122  	MOVW	R0, (R1)	// fail hard
   123  
   124  TEXT runtime·gettid(SB),NOSPLIT,$0-4
   125  	MOVW	$SYS_gettid, R7
   126  	SWI	$0
   127  	MOVW	R0, ret+0(FP)
   128  	RET
   129  
   130  TEXT	runtime·raise(SB),NOSPLIT,$-4
   131  	MOVW	$SYS_gettid, R7
   132  	SWI	$0
   133  	// arg 1 tid already in R0 from gettid
   134  	MOVW	sig+0(FP), R1	// arg 2 - signal
   135  	MOVW	$SYS_tkill, R7
   136  	SWI	$0
   137  	RET
   138  
   139  TEXT	runtime·raiseproc(SB),NOSPLIT,$-4
   140  	MOVW	$SYS_getpid, R7
   141  	SWI	$0
   142  	// arg 1 tid already in R0 from getpid
   143  	MOVW	sig+0(FP), R1	// arg 2 - signal
   144  	MOVW	$SYS_kill, R7
   145  	SWI	$0
   146  	RET
   147  
   148  TEXT runtime·mmap(SB),NOSPLIT,$0
   149  	MOVW	addr+0(FP), R0
   150  	MOVW	n+4(FP), R1
   151  	MOVW	prot+8(FP), R2
   152  	MOVW	flags+12(FP), R3
   153  	MOVW	fd+16(FP), R4
   154  	MOVW	off+20(FP), R5
   155  	MOVW	$SYS_mmap2, R7
   156  	SWI	$0
   157  	MOVW	$0xfffff001, R6
   158  	CMP		R6, R0
   159  	RSB.HI	$0, R0
   160  	MOVW	R0, ret+24(FP)
   161  	RET
   162  
   163  TEXT runtime·munmap(SB),NOSPLIT,$0
   164  	MOVW	addr+0(FP), R0
   165  	MOVW	n+4(FP), R1
   166  	MOVW	$SYS_munmap, R7
   167  	SWI	$0
   168  	MOVW	$0xfffff001, R6
   169  	CMP 	R6, R0
   170  	MOVW.HI	$0, R8  // crash on syscall failure
   171  	MOVW.HI	R8, (R8)
   172  	RET
   173  
   174  TEXT runtime·madvise(SB),NOSPLIT,$0
   175  	MOVW	addr+0(FP), R0
   176  	MOVW	n+4(FP), R1
   177  	MOVW	flags+8(FP), R2
   178  	MOVW	$SYS_madvise, R7
   179  	SWI	$0
   180  	// ignore failure - maybe pages are locked
   181  	RET
   182  
   183  TEXT runtime·setitimer(SB),NOSPLIT,$0
   184  	MOVW	mode+0(FP), R0
   185  	MOVW	new+4(FP), R1
   186  	MOVW	old+8(FP), R2
   187  	MOVW	$SYS_setitimer, R7
   188  	SWI	$0
   189  	RET
   190  
   191  TEXT runtime·mincore(SB),NOSPLIT,$0
   192  	MOVW	addr+0(FP), R0
   193  	MOVW	n+4(FP), R1
   194  	MOVW	dst+8(FP), R2
   195  	MOVW	$SYS_mincore, R7
   196  	SWI	$0
   197  	MOVW	R0, ret+12(FP)
   198  	RET
   199  
   200  TEXT time·now(SB), NOSPLIT, $32
   201  	MOVW	$0, R0  // CLOCK_REALTIME
   202  	MOVW	$8(R13), R1  // timespec
   203  	MOVW	$SYS_clock_gettime, R7
   204  	SWI	$0
   205  	
   206  	MOVW	8(R13), R0  // sec
   207  	MOVW	12(R13), R2  // nsec
   208  	
   209  	MOVW	R0, sec+0(FP)
   210  	MOVW	$0, R1
   211  	MOVW	R1, loc+4(FP)
   212  	MOVW	R2, nsec+8(FP)
   213  	RET	
   214  
   215  // int64 nanotime(void)
   216  TEXT runtime·nanotime(SB),NOSPLIT,$32
   217  	MOVW	$1, R0  // CLOCK_MONOTONIC
   218  	MOVW	$8(R13), R1  // timespec
   219  	MOVW	$SYS_clock_gettime, R7
   220  	SWI	$0
   221  	
   222  	MOVW	8(R13), R0  // sec
   223  	MOVW	12(R13), R2  // nsec
   224  	
   225  	MOVW	$1000000000, R3
   226  	MULLU	R0, R3, (R1, R0)
   227  	MOVW	$0, R4
   228  	ADD.S	R2, R0
   229  	ADC	R4, R1
   230  
   231  	MOVW	R0, ret_lo+0(FP)
   232  	MOVW	R1, ret_hi+4(FP)
   233  	RET
   234  
   235  // int32 futex(int32 *uaddr, int32 op, int32 val,
   236  //	struct timespec *timeout, int32 *uaddr2, int32 val2);
   237  TEXT runtime·futex(SB),NOSPLIT,$0
   238  	// TODO: Rewrite to use FP references. Vet complains.
   239  	MOVW	4(R13), R0
   240  	MOVW	8(R13), R1
   241  	MOVW	12(R13), R2
   242  	MOVW	16(R13), R3
   243  	MOVW	20(R13), R4
   244  	MOVW	24(R13), R5
   245  	MOVW	$SYS_futex, R7
   246  	SWI	$0
   247  	MOVW	R0, ret+24(FP)
   248  	RET
   249  
   250  // int32 clone(int32 flags, void *stack, M *mp, G *gp, void (*fn)(void));
   251  TEXT runtime·clone(SB),NOSPLIT,$0
   252  	MOVW	flags+0(FP), R0
   253  	MOVW	stk+4(FP), R1
   254  	MOVW	$0, R2	// parent tid ptr
   255  	MOVW	$0, R3	// tls_val
   256  	MOVW	$0, R4	// child tid ptr
   257  	MOVW	$0, R5
   258  
   259  	// Copy mp, gp, fn off parent stack for use by child.
   260  	// TODO(kaib): figure out which registers are clobbered by clone and avoid stack copying
   261  	MOVW	$-16(R1), R1
   262  	MOVW	mm+8(FP), R6
   263  	MOVW	R6, 0(R1)
   264  	MOVW	gg+12(FP), R6
   265  	MOVW	R6, 4(R1)
   266  	MOVW	fn+16(FP), R6
   267  	MOVW	R6, 8(R1)
   268  	MOVW	$1234, R6
   269  	MOVW	R6, 12(R1)
   270  
   271  	MOVW	$SYS_clone, R7
   272  	SWI	$0
   273  
   274  	// In parent, return.
   275  	CMP	$0, R0
   276  	BEQ	3(PC)
   277  	MOVW	R0, ret+20(FP)
   278  	RET
   279  
   280  	// Paranoia: check that SP is as we expect. Use R13 to avoid linker 'fixup'
   281  	MOVW	12(R13), R0
   282  	MOVW	$1234, R1
   283  	CMP	R0, R1
   284  	BEQ	2(PC)
   285  	BL	runtime·abort(SB)
   286  
   287  	MOVW	0(R13), R8    // m
   288  	MOVW	4(R13), R0    // g
   289  
   290  	CMP	$0, R8
   291  	BEQ	nog
   292  	CMP	$0, R0
   293  	BEQ	nog
   294  
   295  	MOVW	R0, g
   296  	MOVW	R8, g_m(g)
   297  
   298  	// paranoia; check they are not nil
   299  	MOVW	0(R8), R0
   300  	MOVW	0(g), R0
   301  
   302  	BL	runtime·emptyfunc(SB)	// fault if stack check is wrong
   303  
   304  	// Initialize m->procid to Linux tid
   305  	MOVW	$SYS_gettid, R7
   306  	SWI	$0
   307  	MOVW	g_m(g), R8
   308  	MOVW	R0, m_procid(R8)
   309  
   310  nog:
   311  	// Call fn
   312  	MOVW	8(R13), R0
   313  	MOVW	$16(R13), R13
   314  	BL	(R0)
   315  
   316  	// It shouldn't return.  If it does, exit that thread.
   317  	SUB	$16, R13 // restore the stack pointer to avoid memory corruption
   318  	MOVW	$0, R0
   319  	MOVW	R0, 4(R13)
   320  	BL	runtime·exit1(SB)
   321  
   322  	MOVW	$1234, R0
   323  	MOVW	$1005, R1
   324  	MOVW	R0, (R1)
   325  
   326  TEXT runtime·sigaltstack(SB),NOSPLIT,$0
   327  	MOVW	new+0(FP), R0
   328  	MOVW	old+4(FP), R1
   329  	MOVW	$SYS_sigaltstack, R7
   330  	SWI	$0
   331  	MOVW	$0xfffff001, R6
   332  	CMP 	R6, R0
   333  	MOVW.HI	$0, R8  // crash on syscall failure
   334  	MOVW.HI	R8, (R8)
   335  	RET
   336  
   337  TEXT runtime·sigfwd(SB),NOSPLIT,$0-16
   338  	MOVW	sig+4(FP), R0
   339  	MOVW	info+8(FP), R1
   340  	MOVW	ctx+12(FP), R2
   341  	MOVW	fn+0(FP), R11
   342  	BL	(R11)
   343  	RET
   344  
   345  TEXT runtime·sigtramp(SB),NOSPLIT,$12
   346  	// this might be called in external code context,
   347  	// where g is not set.
   348  	// first save R0, because runtime·load_g will clobber it
   349  	MOVW	R0, 4(R13)
   350  	MOVB	runtime·iscgo(SB), R0
   351  	CMP 	$0, R0
   352  	BL.NE	runtime·load_g(SB)
   353  
   354  	MOVW	R1, 8(R13)
   355  	MOVW	R2, 12(R13)
   356  	MOVW  	$runtime·sigtrampgo(SB), R11
   357  	BL	(R11)
   358  	RET
   359  
   360  TEXT runtime·rtsigprocmask(SB),NOSPLIT,$0
   361  	MOVW	sig+0(FP), R0
   362  	MOVW	new+4(FP), R1
   363  	MOVW	old+8(FP), R2
   364  	MOVW	size+12(FP), R3
   365  	MOVW	$SYS_rt_sigprocmask, R7
   366  	SWI	$0
   367  	RET
   368  
   369  TEXT runtime·rt_sigaction(SB),NOSPLIT,$0
   370  	MOVW	sig+0(FP), R0
   371  	MOVW	new+4(FP), R1
   372  	MOVW	old+8(FP), R2
   373  	MOVW	size+12(FP), R3
   374  	MOVW	$SYS_rt_sigaction, R7
   375  	SWI	$0
   376  	MOVW	R0, ret+16(FP)
   377  	RET
   378  
   379  TEXT runtime·usleep(SB),NOSPLIT,$12
   380  	MOVW	usec+0(FP), R0
   381  	CALL	runtime·usplitR0(SB)
   382  	MOVW	R0, 4(R13)
   383  	MOVW	R1, 8(R13)
   384  	MOVW	$0, R0
   385  	MOVW	$0, R1
   386  	MOVW	$0, R2
   387  	MOVW	$0, R3
   388  	MOVW	$4(R13), R4
   389  	MOVW	$SYS_select, R7
   390  	SWI	$0
   391  	RET
   392  
   393  // Use kernel version instead of native armcas in asm_arm.s.
   394  // See ../sync/atomic/asm_linux_arm.s for details.
   395  TEXT cas<>(SB),NOSPLIT,$0
   396  	MOVW	$0xffff0fc0, R15 // R15 is hardware PC.
   397  
   398  TEXT runtime·cas(SB),NOSPLIT,$0
   399  	MOVW	ptr+0(FP), R2
   400  	MOVW	old+4(FP), R0
   401  loop:
   402  	MOVW	new+8(FP), R1
   403  	BL	cas<>(SB)
   404  	BCC	check
   405  	MOVW	$1, R0
   406  	MOVB	R0, ret+12(FP)
   407  	RET
   408  check:
   409  	// Kernel lies; double-check.
   410  	MOVW	ptr+0(FP), R2
   411  	MOVW	old+4(FP), R0
   412  	MOVW	0(R2), R3
   413  	CMP	R0, R3
   414  	BEQ	loop
   415  	MOVW	$0, R0
   416  	MOVB	R0, ret+12(FP)
   417  	RET
   418  
   419  TEXT runtime·casp1(SB),NOSPLIT,$0
   420  	B	runtime·cas(SB)
   421  
   422  // As for cas, memory barriers are complicated on ARM, but the kernel
   423  // provides a user helper. ARMv5 does not support SMP and has no
   424  // memory barrier instruction at all. ARMv6 added SMP support and has
   425  // a memory barrier, but it requires writing to a coprocessor
   426  // register. ARMv7 introduced the DMB instruction, but it's expensive
   427  // even on single-core devices. The kernel helper takes care of all of
   428  // this for us.
   429  
   430  TEXT publicationBarrier<>(SB),NOSPLIT,$0
   431  	// void __kuser_memory_barrier(void);
   432  	MOVW	$0xffff0fa0, R15 // R15 is hardware PC.
   433  
   434  TEXT ·publicationBarrier(SB),NOSPLIT,$0
   435  	BL	publicationBarrier<>(SB)
   436  	RET
   437  
   438  TEXT runtime·osyield(SB),NOSPLIT,$0
   439  	MOVW	$SYS_sched_yield, R7
   440  	SWI	$0
   441  	RET
   442  
   443  TEXT runtime·sched_getaffinity(SB),NOSPLIT,$0
   444  	MOVW	pid+0(FP), R0
   445  	MOVW	len+4(FP), R1
   446  	MOVW	buf+8(FP), R2
   447  	MOVW	$SYS_sched_getaffinity, R7
   448  	SWI	$0
   449  	MOVW	R0, ret+12(FP)
   450  	RET
   451  
   452  // int32 runtime·epollcreate(int32 size)
   453  TEXT runtime·epollcreate(SB),NOSPLIT,$0
   454  	MOVW	size+0(FP), R0
   455  	MOVW	$SYS_epoll_create, R7
   456  	SWI	$0
   457  	MOVW	R0, ret+4(FP)
   458  	RET
   459  
   460  // int32 runtime·epollcreate1(int32 flags)
   461  TEXT runtime·epollcreate1(SB),NOSPLIT,$0
   462  	MOVW	flags+0(FP), R0
   463  	MOVW	$SYS_epoll_create1, R7
   464  	SWI	$0
   465  	MOVW	R0, ret+4(FP)
   466  	RET
   467  
   468  // func epollctl(epfd, op, fd int32, ev *epollEvent) int
   469  TEXT runtime·epollctl(SB),NOSPLIT,$0
   470  	MOVW	epfd+0(FP), R0
   471  	MOVW	op+4(FP), R1
   472  	MOVW	fd+8(FP), R2
   473  	MOVW	ev+12(FP), R3
   474  	MOVW	$SYS_epoll_ctl, R7
   475  	SWI	$0
   476  	MOVW	R0, ret+16(FP)
   477  	RET
   478  
   479  // int32 runtime·epollwait(int32 epfd, EpollEvent *ev, int32 nev, int32 timeout)
   480  TEXT runtime·epollwait(SB),NOSPLIT,$0
   481  	MOVW	epfd+0(FP), R0
   482  	MOVW	ev+4(FP), R1
   483  	MOVW	nev+8(FP), R2
   484  	MOVW	timeout+12(FP), R3
   485  	MOVW	$SYS_epoll_wait, R7
   486  	SWI	$0
   487  	MOVW	R0, ret+16(FP)
   488  	RET
   489  
   490  // void runtime·closeonexec(int32 fd)
   491  TEXT runtime·closeonexec(SB),NOSPLIT,$0
   492  	MOVW	fd+0(FP), R0	// fd
   493  	MOVW	$2, R1	// F_SETFD
   494  	MOVW	$1, R2	// FD_CLOEXEC
   495  	MOVW	$SYS_fcntl, R7
   496  	SWI	$0
   497  	RET
   498  
   499  // b __kuser_get_tls @ 0xffff0fe0
   500  TEXT runtime·read_tls_fallback(SB),NOSPLIT,$-4
   501  	MOVW	$0xffff0fe0, R0
   502  	B	(R0)
   503  
   504  TEXT runtime·access(SB),NOSPLIT,$0
   505  	MOVW	name+0(FP), R0
   506  	MOVW	mode+4(FP), R1
   507  	MOVW	$SYS_access, R7
   508  	SWI	$0
   509  	MOVW	R0, ret+8(FP)
   510  	RET
   511  
   512  TEXT runtime·connect(SB),NOSPLIT,$0
   513  	MOVW	fd+0(FP), R0
   514  	MOVW	addr+4(FP), R1
   515  	MOVW	addrlen+8(FP), R2
   516  	MOVW	$SYS_connect, R7
   517  	SWI	$0
   518  	MOVW	R0, ret+12(FP)
   519  	RET
   520  
   521  TEXT runtime·socket(SB),NOSPLIT,$0
   522  	MOVW	domain+0(FP), R0
   523  	MOVW	type+4(FP), R1
   524  	MOVW	protocol+8(FP), R2
   525  	MOVW	$SYS_socket, R7
   526  	SWI	$0
   527  	MOVW	R0, ret+12(FP)
   528  	RET