...

Text file src/runtime/sys_darwin_arm.s

     1	// Copyright 2014 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	// System calls and other sys.stuff for ARM, Darwin
     6	// System calls are implemented in libSystem, this file contains
     7	// trampolines that convert from Go to C calling convention.
     8	
     9	#include "go_asm.h"
    10	#include "go_tls.h"
    11	#include "textflag.h"
    12	
    13	TEXT notok<>(SB),NOSPLIT,$0
    14		MOVW	$0, R8
    15		MOVW	R8, (R8)
    16		B		0(PC)
    17	
    18	TEXT runtime·open_trampoline(SB),NOSPLIT,$0
    19		MOVW	4(R0), R1	// arg 2 mode
    20		MOVW	8(R0), R2	// arg 3 perm
    21		MOVW	0(R0), R0	// arg 1 name
    22		BL	libc_open(SB)
    23		RET
    24	
    25	TEXT runtime·close_trampoline(SB),NOSPLIT,$0
    26		MOVW	0(R0), R0	// arg 1 fd
    27		BL	libc_close(SB)
    28		RET
    29	
    30	TEXT runtime·write_trampoline(SB),NOSPLIT,$0
    31		MOVW	4(R0), R1	// arg 2 buf
    32		MOVW	8(R0), R2	// arg 3 count
    33		MOVW	0(R0), R0	// arg 1 fd
    34		BL	libc_write(SB)
    35		RET
    36	
    37	TEXT runtime·read_trampoline(SB),NOSPLIT,$0
    38		MOVW	4(R0), R1	// arg 2 buf
    39		MOVW	8(R0), R2	// arg 3 count
    40		MOVW	0(R0), R0	// arg 1 fd
    41		BL	libc_read(SB)
    42		RET
    43	
    44	TEXT runtime·pipe_trampoline(SB),NOSPLIT,$0
    45		BL	libc_pipe(SB)	// pointer already in R0
    46		CMP	$0, R0
    47		BEQ	3(PC)
    48		BL	libc_error(SB)	// return negative errno value
    49		RSB	$0, R0, R0
    50		RET
    51	
    52	TEXT runtime·exit_trampoline(SB),NOSPLIT|NOFRAME,$0
    53		MOVW	0(R0), R0	// arg 0 code
    54		BL libc_exit(SB)
    55		MOVW	$1234, R0
    56		MOVW	$1002, R1
    57		MOVW	R0, (R1)	// fail hard
    58	
    59	TEXT runtime·raiseproc_trampoline(SB),NOSPLIT,$0
    60		MOVW	0(R0), R8	// signal
    61		BL	libc_getpid(SB)
    62		// arg 1 pid already in R0 from getpid
    63		MOVW	R8, R1	// arg 2 signal
    64		BL	libc_kill(SB)
    65		RET
    66	
    67	TEXT runtime·mmap_trampoline(SB),NOSPLIT,$0
    68		MOVW	R0, R8
    69		MOVW	0(R8), R0	// arg 1 addr
    70		MOVW	4(R8), R1	// arg 2 len
    71		MOVW	8(R8), R2	// arg 3 prot
    72		MOVW	12(R8), R3	// arg 4 flags
    73		MOVW	16(R8), R4	// arg 5 fid
    74		MOVW	20(R8), R5	// arg 6 offset
    75		MOVW	$0, R6	// off_t is uint64_t
    76		// Only R0-R3 are used for arguments, the rest
    77		// go on the stack.
    78		MOVM.DB.W [R4-R6], (R13)
    79		BL	libc_mmap(SB)
    80		ADD $12, R13
    81		MOVW	$0, R1
    82		MOVW	$-1, R2
    83		CMP	R0, R2
    84		BNE ok
    85		BL	libc_error(SB)
    86		MOVW	(R0), R1
    87		MOVW	$0, R0
    88	ok:
    89		MOVW	R0, 24(R8)	// ret 1 addr
    90		MOVW	R1, 28(R8)	// ret 2 err
    91		RET
    92	
    93	TEXT runtime·munmap_trampoline(SB),NOSPLIT,$0
    94		MOVW	4(R0), R1	// arg 2 len
    95		MOVW	0(R0), R0	// arg 1 addr
    96		BL libc_munmap(SB)
    97		MOVW	$-1, R2
    98		CMP	R0, R2
    99		BL.EQ	notok<>(SB)
   100		RET
   101	
   102	TEXT runtime·madvise_trampoline(SB),NOSPLIT,$0
   103		MOVW	4(R0), R1	// arg 2 len
   104		MOVW	8(R0), R2	// arg 3 advice
   105		MOVW	0(R0), R0	// arg 1 addr
   106		BL	libc_madvise(SB)
   107		MOVW	$-1, R2
   108		CMP	R0, R2
   109		BL.EQ	notok<>(SB)
   110		RET
   111	
   112	TEXT runtime·setitimer_trampoline(SB),NOSPLIT,$0
   113		MOVW	4(R0), R1	// arg 2 new
   114		MOVW	8(R0), R2	// arg 3 old
   115		MOVW	0(R0), R0	// arg 1 which
   116		BL	libc_setitimer(SB)
   117		RET
   118	
   119	TEXT runtime·walltime_trampoline(SB),NOSPLIT,$0
   120		// R0 already has *timeval
   121		MOVW	$0, R1 // no timezone needed
   122		BL	libc_gettimeofday(SB)
   123		RET
   124	
   125	GLOBL timebase<>(SB),NOPTR,$(machTimebaseInfo__size)
   126	
   127	TEXT runtime·nanotime_trampoline(SB),NOSPLIT,$0
   128		MOVW	R0, R8
   129		BL	libc_mach_absolute_time(SB)
   130		MOVW	R0, 0(R8)
   131		MOVW	R1, 4(R8)
   132		MOVW	timebase<>+machTimebaseInfo_numer(SB), R6
   133		MOVW	$timebase<>+machTimebaseInfo_denom(SB), R5
   134		MOVW	(R5), R7
   135		DMB	MB_ISH	// memory barrier for atomic read
   136		CMP	$0, R7
   137		BNE	initialized
   138	
   139		SUB	$(machTimebaseInfo__size+7)/8*8, R13
   140		MOVW	R13, R0
   141		BL	libc_mach_timebase_info(SB)
   142		MOVW	machTimebaseInfo_numer(R13), R6
   143		MOVW	machTimebaseInfo_denom(R13), R7
   144		ADD	$(machTimebaseInfo__size+7)/8*8, R13
   145	
   146		MOVW	R6, timebase<>+machTimebaseInfo_numer(SB)
   147		MOVW	$timebase<>+machTimebaseInfo_denom(SB), R5
   148		DMB	MB_ISH	// memory barrier for atomic write
   149		MOVW	R7, (R5)
   150		DMB	MB_ISH
   151	
   152	initialized:
   153		MOVW	R6, 8(R8)
   154		MOVW	R7, 12(R8)
   155		RET
   156	
   157	TEXT runtime·sigfwd(SB),NOSPLIT,$0-16
   158		MOVW	sig+4(FP), R0
   159		MOVW	info+8(FP), R1
   160		MOVW	ctx+12(FP), R2
   161		MOVW	fn+0(FP), R11
   162		MOVW	R13, R4
   163		SUB	$24, R13
   164		BIC	$0x7, R13 // alignment for ELF ABI
   165		BL	(R11)
   166		MOVW	R4, R13
   167		RET
   168	
   169	TEXT runtime·sigtramp(SB),NOSPLIT,$0
   170		// Reserve space for callee-save registers and arguments.
   171		SUB	$40, R13
   172	
   173		MOVW	R4, 16(R13)
   174		MOVW	R5, 20(R13)
   175		MOVW	R6, 24(R13)
   176		MOVW	R7, 28(R13)
   177		MOVW	R8, 32(R13)
   178		MOVW	R11, 36(R13)
   179	
   180		// Save arguments.
   181		MOVW	R0, 4(R13)	// sig
   182		MOVW	R1, 8(R13)	// info
   183		MOVW	R2, 12(R13)	// ctx
   184	
   185		// this might be called in external code context,
   186		// where g is not set.
   187		MOVB	runtime·iscgo(SB), R0
   188		CMP 	$0, R0
   189		BL.NE	runtime·load_g(SB)
   190	
   191		MOVW	R13, R6
   192		CMP	$0, g
   193		BEQ nog
   194	
   195		// iOS always use the main stack to run the signal handler.
   196		// We need to switch to gsignal ourselves.
   197		MOVW	g_m(g), R11
   198		MOVW	m_gsignal(R11), R5
   199		MOVW	(g_stack+stack_hi)(R5), R6
   200	
   201	nog:
   202		// Restore arguments.
   203		MOVW	4(R13), R0
   204		MOVW	8(R13), R1
   205		MOVW	12(R13), R2
   206	
   207		// Reserve space for args and the stack pointer on the
   208		// gsignal stack.
   209		SUB $24, R6
   210		// Save stack pointer.
   211		MOVW	R13, R4
   212		MOVW	R4, 16(R6)
   213		// Switch to gsignal stack.
   214		MOVW	R6, R13
   215	
   216		// Call sigtrampgo
   217		MOVW	R0, 4(R13)
   218		MOVW	R1, 8(R13)
   219		MOVW	R2, 12(R13)
   220		BL	runtime·sigtrampgo(SB)
   221	
   222		// Switch to old stack.
   223		MOVW	16(R13), R5
   224		MOVW	R5, R13
   225	
   226		// Restore callee-save registers.
   227		MOVW	16(R13), R4
   228		MOVW	20(R13), R5
   229		MOVW	24(R13), R6
   230		MOVW	28(R13), R7
   231		MOVW	32(R13), R8
   232		MOVW	36(R13), R11
   233	
   234		ADD	$40, R13
   235	
   236		RET
   237	
   238	TEXT runtime·cgoSigtramp(SB),NOSPLIT,$0
   239		JMP	runtime·sigtramp(SB)
   240	
   241	TEXT runtime·sigprocmask_trampoline(SB),NOSPLIT,$0
   242		MOVW	4(R0), R1	// arg 2 new
   243		MOVW	8(R0), R2	// arg 3 old
   244		MOVW	0(R0), R0	// arg 1 how
   245		BL	libc_pthread_sigmask(SB)
   246		CMP	$0, R0
   247		BL.NE	notok<>(SB)
   248		RET
   249	
   250	TEXT runtime·sigaction_trampoline(SB),NOSPLIT,$0
   251		MOVW	4(R0), R1	// arg 2 new
   252		MOVW	8(R0), R2	// arg 3 old
   253		MOVW	0(R0), R0	// arg 1 how
   254		BL	libc_sigaction(SB)
   255		RET
   256	
   257	TEXT runtime·usleep_trampoline(SB),NOSPLIT,$0
   258		MOVW	0(R0), R0	// arg 1 usec
   259		BL libc_usleep(SB)
   260		RET
   261	
   262	TEXT ·publicationBarrier(SB),NOSPLIT|NOFRAME,$0-0
   263		B	runtime·armPublicationBarrier(SB)
   264	
   265	TEXT runtime·sysctl_trampoline(SB),NOSPLIT,$0
   266		MOVW	4(R0), R1	// arg 2 miblen
   267		MOVW	8(R0), R2	// arg 3 out
   268		MOVW	12(R0), R3	// arg 4 size
   269		MOVW	16(R0), R4	// arg 5 dst
   270		MOVW	20(R0), R5	// arg 6 ndst
   271		MOVW	0(R0), R0	// arg 1 mib
   272		// Only R0-R3 are used for arguments, the rest
   273		// go on the stack.
   274		MOVM.DB.W [R4-R5], (R13)
   275		BL	libc_sysctl(SB)
   276		ADD $(2*4), R13
   277		RET
   278	
   279	TEXT runtime·kqueue_trampoline(SB),NOSPLIT,$0
   280		BL	libc_kqueue(SB)
   281		RET
   282	
   283	// int32 runtime·kevent(int kq, Kevent *changelist, int nchanges, Kevent *eventlist, int events, Timespec *timeout)
   284	TEXT runtime·kevent_trampoline(SB),NOSPLIT,$0
   285		MOVW	4(R0), R1	// arg 2 keventss
   286		MOVW	8(R0), R2	// arg 3 nch
   287		MOVW	12(R0), R3	// arg 4 ev
   288		MOVW	16(R0), R4	// arg 5 nev
   289		MOVW	20(R0), R5	// arg 6 ts
   290		MOVW	0(R0), R0	// arg 1 kq
   291		// Only R0-R3 are used for arguments, the rest
   292		// go on the stack.
   293		MOVM.DB.W [R4-R5], (R13)
   294		BL	libc_kevent(SB)
   295		ADD	$(2*4), R13
   296		MOVW	$-1, R2
   297		CMP	R0, R2
   298		BNE	ok
   299		BL	libc_error(SB)
   300		MOVW	(R0), R0	// errno
   301		RSB	$0, R0, R0	// caller wants it as a negative error code
   302	ok:
   303		RET
   304	
   305	TEXT runtime·fcntl_trampoline(SB),NOSPLIT,$0
   306		MOVW	4(R0), R1	// arg 2 cmd
   307		MOVW	8(R0), R2	// arg 3 arg
   308		MOVW	0(R0), R0	// arg 1 fd
   309		BL	libc_fcntl(SB)
   310		RET
   311	
   312	// sigaltstack is not supported on iOS, so our sigtramp has
   313	// to do the stack switch ourselves.
   314	TEXT runtime·sigaltstack_trampoline(SB),NOSPLIT,$0
   315		MOVW	$43, R0
   316		BL	libc_exit(SB)
   317		RET
   318	
   319	// Thread related functions
   320	// Note: On darwin/arm, the runtime always use runtime/cgo to
   321	// create threads, so all thread related functions will just exit with a
   322	// unique status.
   323	
   324	TEXT runtime·mstart_stub(SB),NOSPLIT,$0
   325		MOVW	$44, R0
   326		BL	libc_exit(SB)
   327		RET
   328	
   329	TEXT runtime·pthread_attr_init_trampoline(SB),NOSPLIT,$0
   330		MOVW	$45, R0
   331		BL	libc_exit(SB)
   332		RET
   333	
   334	TEXT runtime·pthread_attr_getstacksize_trampoline(SB),NOSPLIT,$0
   335		MOVW	$46, R0
   336		BL	libc_exit(SB)
   337		RET
   338	
   339	TEXT runtime·pthread_attr_setdetachstate_trampoline(SB),NOSPLIT,$0
   340		MOVW	$47, R0
   341		BL	libc_exit(SB)
   342		RET
   343	
   344	TEXT runtime·pthread_create_trampoline(SB),NOSPLIT,$0
   345		MOVW	$48, R0
   346		BL	libc_exit(SB)
   347		RET
   348	
   349	TEXT runtime·raise_trampoline(SB),NOSPLIT,$0
   350		MOVW	0(R0), R0	// arg 1 sig
   351		BL	libc_raise(SB)
   352		RET
   353	
   354	TEXT runtime·pthread_mutex_init_trampoline(SB),NOSPLIT,$0
   355		MOVW	4(R0), R1	// arg 2 attr
   356		MOVW	0(R0), R0	// arg 1 mutex
   357		BL	libc_pthread_mutex_init(SB)
   358		RET
   359	
   360	TEXT runtime·pthread_mutex_lock_trampoline(SB),NOSPLIT,$0
   361		MOVW	0(R0), R0	// arg 1 mutex
   362		BL	libc_pthread_mutex_lock(SB)
   363		RET
   364	
   365	TEXT runtime·pthread_mutex_unlock_trampoline(SB),NOSPLIT,$0
   366		MOVW	0(R0), R0	// arg 1 mutex
   367		BL	libc_pthread_mutex_unlock(SB)
   368		RET
   369	
   370	TEXT runtime·pthread_cond_init_trampoline(SB),NOSPLIT,$0
   371		MOVW	4(R0), R1	// arg 2 attr
   372		MOVW	0(R0), R0	// arg 1 cond
   373		BL	libc_pthread_cond_init(SB)
   374		RET
   375	
   376	TEXT runtime·pthread_cond_wait_trampoline(SB),NOSPLIT,$0
   377		MOVW	4(R0), R1	// arg 2 mutex
   378		MOVW	0(R0), R0	// arg 1 cond
   379		BL	libc_pthread_cond_wait(SB)
   380		RET
   381	
   382	TEXT runtime·pthread_cond_timedwait_relative_np_trampoline(SB),NOSPLIT,$0
   383		MOVW	4(R0), R1	// arg 2 mutex
   384		MOVW	8(R0), R2	// arg 3 timeout
   385		MOVW	0(R0), R0	// arg 1 cond
   386		BL	libc_pthread_cond_timedwait_relative_np(SB)
   387		RET
   388	
   389	TEXT runtime·pthread_cond_signal_trampoline(SB),NOSPLIT,$0
   390		MOVW	0(R0), R0	// arg 1 cond
   391		BL	libc_pthread_cond_signal(SB)
   392		RET
   393	
   394	// syscall calls a function in libc on behalf of the syscall package.
   395	// syscall takes a pointer to a struct like:
   396	// struct {
   397	//	fn    uintptr
   398	//	a1    uintptr
   399	//	a2    uintptr
   400	//	a3    uintptr
   401	//	r1    uintptr
   402	//	r2    uintptr
   403	//	err   uintptr
   404	// }
   405	// syscall must be called on the g0 stack with the
   406	// C calling convention (use libcCall).
   407	TEXT runtime·syscall(SB),NOSPLIT,$0
   408		MOVW.W	R0, -4(R13)	// push structure pointer
   409		MOVW	0(R0), R12	// fn
   410		MOVW	8(R0), R1	// a2
   411		MOVW	12(R0), R2	// a3
   412		MOVW	4(R0), R0	// a1
   413		BL	(R12)
   414		MOVW.P	4(R13), R2	// pop structure pointer
   415		MOVW	R0, 16(R2)	// save r1
   416		MOVW	R1, 20(R2)	// save r2
   417		MOVW	$-1, R3
   418		CMP	R0, R3
   419		BNE	ok
   420		MOVW.W	R2, -4(R13)	// push structure pointer
   421		BL	libc_error(SB)
   422		MOVW	(R0), R0
   423		MOVW.P	4(R13), R2	// pop structure pointer
   424		MOVW	R0, 24(R2)	// save err
   425	ok:
   426		RET
   427	
   428	// syscallPtr is like syscall except the libc function reports an
   429	// error by returning NULL and setting errno.
   430	TEXT runtime·syscallPtr(SB),NOSPLIT,$0
   431		MOVW.W	R0, -4(R13)	// push structure pointer
   432		MOVW	0(R0), R12	// fn
   433		MOVW	8(R0), R1	// a2
   434		MOVW	12(R0), R2	// a3
   435		MOVW	4(R0), R0	// a1
   436		BL	(R12)
   437		MOVW.P	4(R13), R2	// pop structure pointer
   438		MOVW	R0, 16(R2)	// save r1
   439		MOVW	R1, 20(R2)	// save r2
   440		MOVW	$0, R3
   441		CMP	R0, R3
   442		BNE	ok
   443		MOVW.W	R2, -4(R13)	// push structure pointer
   444		BL	libc_error(SB)
   445		MOVW	(R0), R0
   446		MOVW.P	4(R13), R2	// pop structure pointer
   447		MOVW	R0, 24(R2)	// save err
   448	ok:
   449		RET
   450	
   451	// syscall6 calls a function in libc on behalf of the syscall package.
   452	// syscall6 takes a pointer to a struct like:
   453	// struct {
   454	//	fn    uintptr
   455	//	a1    uintptr
   456	//	a2    uintptr
   457	//	a3    uintptr
   458	//	a4    uintptr
   459	//	a5    uintptr
   460	//	a6    uintptr
   461	//	r1    uintptr
   462	//	r2    uintptr
   463	//	err   uintptr
   464	// }
   465	// syscall6 must be called on the g0 stack with the
   466	// C calling convention (use libcCall).
   467	TEXT runtime·syscall6(SB),NOSPLIT,$0
   468		MOVW.W	R0, -4(R13)	// push structure pointer
   469		MOVW	0(R0), R12	// fn
   470		MOVW	24(R0), R1	// a6
   471		MOVW.W	R1, -4(R13)
   472		MOVW	20(R0), R1	// a5
   473		MOVW.W	R1, -4(R13)
   474		MOVW	8(R0), R1	// a2
   475		MOVW	12(R0), R2	// a3
   476		MOVW	16(R0), R3	// a4
   477		MOVW	4(R0), R0	// a1
   478		BL	(R12)
   479		ADD	$8, R13
   480		MOVW.P	4(R13), R2	// pop structure pointer
   481		MOVW	R0, 28(R2)	// save r1
   482		MOVW	R1, 32(R2)	// save r2
   483		MOVW	$-1, R3
   484		CMP	R0, R3
   485		BNE	ok
   486		MOVW.W	R2, -4(R13)	// push structure pointer
   487		BL	libc_error(SB)
   488		MOVW	(R0), R0
   489		MOVW.P	4(R13), R2	// pop structure pointer
   490		MOVW	R0, 36(R2)	// save err
   491	ok:
   492		RET
   493	
   494	// syscall6X calls a function in libc on behalf of the syscall package.
   495	// syscall6X takes a pointer to a struct like:
   496	// struct {
   497	//	fn    uintptr
   498	//	a1    uintptr
   499	//	a2    uintptr
   500	//	a3    uintptr
   501	//	a4    uintptr
   502	//	a5    uintptr
   503	//	a6    uintptr
   504	//	r1    uintptr
   505	//	r2    uintptr
   506	//	err   uintptr
   507	// }
   508	// syscall6X must be called on the g0 stack with the
   509	// C calling convention (use libcCall).
   510	TEXT runtime·syscall6X(SB),NOSPLIT,$0
   511		MOVW.W	R0, -4(R13)	// push structure pointer
   512		MOVW	0(R0), R12	// fn
   513		MOVW	24(R0), R1	// a6
   514		MOVW.W	R1, -4(R13)
   515		MOVW	20(R0), R1	// a5
   516		MOVW.W	R1, -4(R13)
   517		MOVW	8(R0), R1	// a2
   518		MOVW	12(R0), R2	// a3
   519		MOVW	16(R0), R3	// a4
   520		MOVW	4(R0), R0	// a1
   521		BL	(R12)
   522		ADD	$8, R13
   523		MOVW.P	4(R13), R2	// pop structure pointer
   524		MOVW	R0, 28(R2)	// save r1
   525		MOVW	R1, 32(R2)	// save r2
   526		MOVW	$-1, R3
   527		CMP	R0, R3
   528		BNE	ok
   529		CMP	R1, R3
   530		BNE	ok
   531		MOVW.W	R2, -4(R13)	// push structure pointer
   532		BL	libc_error(SB)
   533		MOVW	(R0), R0
   534		MOVW.P	4(R13), R2	// pop structure pointer
   535		MOVW	R0, 36(R2)	// save err
   536	ok:
   537		RET
   538	
   539	// syscall9 calls a function in libc on behalf of the syscall package.
   540	// syscall9 takes a pointer to a struct like:
   541	// struct {
   542	//	fn    uintptr
   543	//	a1    uintptr
   544	//	a2    uintptr
   545	//	a3    uintptr
   546	//	a4    uintptr
   547	//	a5    uintptr
   548	//	a6    uintptr
   549	//	a7    uintptr
   550	//	a8    uintptr
   551	//	a9    uintptr
   552	//	r1    uintptr
   553	//	r2    uintptr
   554	//	err   uintptr
   555	// }
   556	// syscall9 must be called on the g0 stack with the
   557	// C calling convention (use libcCall).
   558	TEXT runtime·syscall9(SB),NOSPLIT,$0
   559		MOVW.W	R0, -4(R13)	// push structure pointer
   560		MOVW	0(R0), R12	// fn
   561		MOVW	36(R0), R1	// a9
   562		MOVW.W	R1, -4(R13)
   563		MOVW	32(R0), R1	// a8
   564		MOVW.W	R1, -4(R13)
   565		MOVW	28(R0), R1	// a7
   566		MOVW.W	R1, -4(R13)
   567		MOVW	24(R0), R1	// a6
   568		MOVW.W	R1, -4(R13)
   569		MOVW	20(R0), R1	// a5
   570		MOVW.W	R1, -4(R13)
   571		MOVW	8(R0), R1	// a2
   572		MOVW	12(R0), R2	// a3
   573		MOVW	16(R0), R3	// a4
   574		MOVW	4(R0), R0	// a1
   575		BL	(R12)
   576		ADD	$20, R13
   577		MOVW.P	4(R13), R2	// pop structure pointer
   578		MOVW	R0, 40(R2)	// save r1
   579		MOVW	R1, 44(R2)	// save r2
   580		MOVW	$-1, R3
   581		CMP	R0, R3
   582		BNE	ok
   583		MOVW.W	R2, -4(R13)	// push structure pointer
   584		BL	libc_error(SB)
   585		MOVW	(R0), R0
   586		MOVW.P	4(R13), R2	// pop structure pointer
   587		MOVW	R0, 48(R2)	// save err
   588	ok:
   589		RET

View as plain text