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 "textflag.h" 6 7 TEXT _rt0_arm_linux(SB),NOSPLIT,$-4 8 MOVW (R13), R0 // argc 9 MOVW $4(R13), R1 // argv 10 MOVW $_rt0_arm_linux1(SB), R4 11 B (R4) 12 13 // When building with -buildmode=c-shared, this symbol is called when the shared 14 // library is loaded. 15 TEXT _rt0_arm_linux_lib(SB),NOSPLIT,$104 16 // Preserve callee-save registers. Raspberry Pi's dlopen(), for example, 17 // actually cares that R11 is preserved. 18 MOVW R4, 12(R13) 19 MOVW R5, 16(R13) 20 MOVW R6, 20(R13) 21 MOVW R7, 24(R13) 22 MOVW R8, 28(R13) 23 MOVW R11, 32(R13) 24 25 // Skip floating point registers on GOARM < 6. 26 MOVB runtimegoarm(SB), R11 27 CMP $6, R11 28 BLT skipfpsave 29 MOVD F8, (32+8*1)(R13) 30 MOVD F9, (32+8*2)(R13) 31 MOVD F10, (32+8*3)(R13) 32 MOVD F11, (32+8*4)(R13) 33 MOVD F12, (32+8*5)(R13) 34 MOVD F13, (32+8*6)(R13) 35 MOVD F14, (32+8*7)(R13) 36 MOVD F15, (32+8*8)(R13) 37 skipfpsave: 38 // Save argc/argv. 39 MOVW R0, _rt0_arm_linux_lib_argc<>(SB) 40 MOVW R1, _rt0_arm_linux_lib_argv<>(SB) 41 42 // Synchronous initialization. 43 MOVW $runtimelibpreinit(SB), R2 44 CALL (R2) 45 46 // Create a new thread to do the runtime initialization. 47 MOVW _cgo_sys_thread_create(SB), R2 48 CMP $0, R2 49 BEQ nocgo 50 MOVW $_rt0_arm_linux_lib_go<>(SB), R0 51 MOVW $0, R1 52 BL (R2) 53 B rr 54 nocgo: 55 MOVW $0x800000, R0 // stacksize = 8192KB 56 MOVW $_rt0_arm_linux_lib_go<>(SB), R1 // fn 57 MOVW R0, 4(R13) 58 MOVW R1, 8(R13) 59 BL runtimenewosproc0(SB) 60 rr: 61 // Restore callee-save registers and return. 62 MOVB runtimegoarm(SB), R11 63 CMP $6, R11 64 BLT skipfprest 65 MOVD (32+8*1)(R13), F8 66 MOVD (32+8*2)(R13), F9 67 MOVD (32+8*3)(R13), F10 68 MOVD (32+8*4)(R13), F11 69 MOVD (32+8*5)(R13), F12 70 MOVD (32+8*6)(R13), F13 71 MOVD (32+8*7)(R13), F14 72 MOVD (32+8*8)(R13), F15 73 skipfprest: 74 MOVW 12(R13), R4 75 MOVW 16(R13), R5 76 MOVW 20(R13), R6 77 MOVW 24(R13), R7 78 MOVW 28(R13), R8 79 MOVW 32(R13), R11 80 RET 81 82 TEXT _rt0_arm_linux_lib_go<>(SB),NOSPLIT,$8 83 MOVW _rt0_arm_linux_lib_argc<>(SB), R0 84 MOVW _rt0_arm_linux_lib_argv<>(SB), R1 85 MOVW R0, 0(R13) 86 MOVW R1, 4(R13) 87 B runtimert0_go(SB) 88 89 DATA _rt0_arm_linux_lib_argc<>(SB)/4,$0 90 GLOBL _rt0_arm_linux_lib_argc<>(SB),NOPTR,$4 91 DATA _rt0_arm_linux_lib_argv<>(SB)/4,$0 92 GLOBL _rt0_arm_linux_lib_argv<>(SB),NOPTR,$4 93 94 TEXT _rt0_arm_linux1(SB),NOSPLIT,$-4 95 // We first need to detect the kernel ABI, and warn the user 96 // if the system only supports OABI 97 // The strategy here is to call some EABI syscall to see if 98 // SIGILL is received. 99 // To catch SIGILL, we have to first setup sigaction, this is 100 // a chicken-and-egg problem, because we can't do syscall if 101 // we don't know the kernel ABI... Oh, not really, we can do 102 // syscall in Thumb mode. 103 104 // Save argc and argv 105 MOVM.DB.W [R0-R1], (R13) 106 107 // Thumb mode OABI check disabled because there are some 108 // EABI systems that do not support Thumb execution. 109 // We can run on them except for this check! 110 111 // // set up sa_handler 112 // MOVW $bad_abi<>(SB), R0 // sa_handler 113 // MOVW $0, R1 // sa_flags 114 // MOVW $0, R2 // sa_restorer 115 // MOVW $0, R3 // sa_mask 116 // MOVM.DB.W [R0-R3], (R13) 117 // MOVW $4, R0 // SIGILL 118 // MOVW R13, R1 // sa 119 // SUB $16, R13 120 // MOVW R13, R2 // old_sa 121 // MOVW $8, R3 // c 122 // MOVW $174, R7 // sys_sigaction 123 // BL oabi_syscall<>(SB) 124 125 // do an EABI syscall 126 MOVW $20, R7 // sys_getpid 127 SWI $0 // this will trigger SIGILL on OABI systems 128 129 // MOVW $4, R0 // SIGILL 130 // MOVW R13, R1 // sa 131 // MOVW $0, R2 // old_sa 132 // MOVW $8, R3 // c 133 // MOVW $174, R7 // sys_sigaction 134 // SWI $0 // restore signal handler 135 // ADD $32, R13 136 137 B runtimert0_go(SB) 138 139 TEXT bad_abi<>(SB),NOSPLIT,$-4 140 // give diagnosis and exit 141 MOVW $2, R0 // stderr 142 MOVW $bad_abi_msg(SB), R1 // data 143 MOVW $45, R2 // len 144 MOVW $4, R7 // sys_write 145 BL oabi_syscall<>(SB) 146 MOVW $1, R0 147 MOVW $1, R7 // sys_exit 148 BL oabi_syscall<>(SB) 149 B 0(PC) 150 151 DATA bad_abi_msg+0x00(SB)/8, $"This pro" 152 DATA bad_abi_msg+0x08(SB)/8, $"gram can" 153 DATA bad_abi_msg+0x10(SB)/8, $" only be" 154 DATA bad_abi_msg+0x18(SB)/8, $" run on " 155 DATA bad_abi_msg+0x20(SB)/8, $"EABI ker" 156 DATA bad_abi_msg+0x28(SB)/4, $"nels" 157 DATA bad_abi_msg+0x2c(SB)/1, $0xa 158 GLOBL bad_abi_msg(SB), RODATA, $45 159 160 TEXT oabi_syscall<>(SB),NOSPLIT,$-4 161 ADD $1, R15, R4 // R15 is hardware PC 162 WORD $0xe12fff14 //BX (R4) // enter thumb mode 163 // TODO(minux): only supports little-endian CPUs 164 WORD $0x4770df01 // swi $1; bx lr 165 166 TEXT main(SB),NOSPLIT,$-4 167 MOVW $_rt0_arm_linux1(SB), R4 168 B (R4) 169 170