| 1 | /* Copyright (c) 2012-2015 Red Hat, Inc. All rights reserved. |
|---|
| 2 | |
|---|
| 3 | This copyrighted material is made available to anyone wishing to use, modify, |
|---|
| 4 | copy, or redistribute it subject to the terms and conditions of the BSD |
|---|
| 5 | License. This program is distributed in the hope that it will be useful, |
|---|
| 6 | but WITHOUT ANY WARRANTY expressed or implied, including the implied warranties |
|---|
| 7 | of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. A copy of this license |
|---|
| 8 | is available at http://www.opensource.org/licenses. Any Red Hat trademarks that |
|---|
| 9 | are incorporated in the source code or documentation are not subject to the BSD |
|---|
| 10 | License and may only be used or replicated with the express permission of |
|---|
| 11 | Red Hat, Inc. |
|---|
| 12 | */ |
|---|
| 13 | |
|---|
| 14 | #include "memmodel.h" |
|---|
| 15 | |
|---|
| 16 | ;; The linker links all .crt_* sections in asciibetical order at the |
|---|
| 17 | ;; same place. So, the four digits in .crt_NNNN_xxx name created by |
|---|
| 18 | ;; the START_CRT_FUNC macro determine the link order, so, keep them |
|---|
| 19 | ;; in sequential order here. The first two digits are set here, the |
|---|
| 20 | ;; second two allow users to insert code between code fragments here. |
|---|
| 21 | |
|---|
| 22 | #if L0 |
|---|
| 23 | .section ".resetvec", "a" |
|---|
| 24 | __msp430_resetvec_hook: |
|---|
| 25 | .word __crt0_start |
|---|
| 26 | |
|---|
| 27 | ;; Here we provide weak definitions of the symbols used in the |
|---|
| 28 | ;; init_highbss and move_highdata blocks, in case they are not |
|---|
| 29 | ;; provided by the linker script. They are defined here because |
|---|
| 30 | ;; this block is always included in every executable, and because |
|---|
| 31 | ;; if there were defined in the blocks that need them their values |
|---|
| 32 | ;; would be used without giving the linker script a chance to |
|---|
| 33 | ;; override them. |
|---|
| 34 | ;; |
|---|
| 35 | ;; The weak definitions are needed if the user targets an MCU |
|---|
| 36 | ;; without high memory - and hence uses a linker script without |
|---|
| 37 | ;; a definition of the .upper.bss or .upper.data sections - and |
|---|
| 38 | ;; they have compiled their code with the -mdata-region=either |
|---|
| 39 | ;; command line option. That option causes the assembler to |
|---|
| 40 | ;; define the __crt0_move_highdata and/or crt0_init_highbss |
|---|
| 41 | ;; symbols, which in turn forces the inclusion of the |
|---|
| 42 | ;; move_highdata and/or init_highbss blocks in the startup code, |
|---|
| 43 | ;; regardless of the fact that the sections are not present in |
|---|
| 44 | ;; the linker script. |
|---|
| 45 | |
|---|
| 46 | WEAK_DEF __upper_data_init |
|---|
| 47 | WEAK_DEF __rom_highdatacopysize |
|---|
| 48 | WEAK_DEF __high_datastart |
|---|
| 49 | WEAK_DEF __rom_highdatastart |
|---|
| 50 | WEAK_DEF __high_bssstart |
|---|
| 51 | WEAK_DEF __high_bsssize |
|---|
| 52 | |
|---|
| 53 | START_CRT_FUNC 0000 start |
|---|
| 54 | .refsym __msp430_resetvec_hook |
|---|
| 55 | #ifdef MINRT |
|---|
| 56 | .refsym __crt0_call_just_main |
|---|
| 57 | #else |
|---|
| 58 | .refsym __crt0_call_init_then_main |
|---|
| 59 | #endif |
|---|
| 60 | mov_ #__stack, R1 |
|---|
| 61 | |
|---|
| 62 | END_CRT_FUNC start |
|---|
| 63 | #endif |
|---|
| 64 | |
|---|
| 65 | |
|---|
| 66 | #if Lbss |
|---|
| 67 | ;; Note - this section is only included in the startup code of the |
|---|
| 68 | ;; application if it is needed. It is responsible for initializing |
|---|
| 69 | ;; the contents of the .bss section. |
|---|
| 70 | |
|---|
| 71 | START_CRT_FUNC 0100 init_bss |
|---|
| 72 | |
|---|
| 73 | mov_ #__bssstart, R12 |
|---|
| 74 | clr.w R13 |
|---|
| 75 | mov_ #__bsssize, R14 |
|---|
| 76 | #ifdef __MSP430X_LARGE__ |
|---|
| 77 | clr.w R15 ; We assume that __bsssize is never > 64K |
|---|
| 78 | #endif |
|---|
| 79 | call_ #memset |
|---|
| 80 | |
|---|
| 81 | END_CRT_FUNC init_bss |
|---|
| 82 | #endif /* Lbss */ |
|---|
| 83 | |
|---|
| 84 | |
|---|
| 85 | #ifdef __MSP430X_LARGE__ |
|---|
| 86 | #if Lhigh_bss |
|---|
| 87 | ;; Note - this section is only included in the startup code of the |
|---|
| 88 | ;; application if it is needed. It is responsible for initializing |
|---|
| 89 | ;; the contents of the .upper.bss section. |
|---|
| 90 | |
|---|
| 91 | START_CRT_FUNC 0200 init_highbss |
|---|
| 92 | |
|---|
| 93 | mov_ #__high_bssstart, R12 |
|---|
| 94 | mov.w #0, R13 |
|---|
| 95 | mov_ #__high_bsssize, R14 |
|---|
| 96 | ;; If __high_bsssize is zero then skip the call to memset. |
|---|
| 97 | ;; This can happen if all of the bss data was placed into .either.bss. |
|---|
| 98 | cmp.w #0, R14 |
|---|
| 99 | jeq 1f |
|---|
| 100 | call_ #memset |
|---|
| 101 | 1: |
|---|
| 102 | END_CRT_FUNC init_highbss |
|---|
| 103 | #endif /* Lhigh_bss */ |
|---|
| 104 | #endif /* __MSP430X_LARGE__ */ |
|---|
| 105 | |
|---|
| 106 | |
|---|
| 107 | #if Lmovedata |
|---|
| 108 | ;; Note - this section is only included in the startup code of the |
|---|
| 109 | ;; application if it is needed. It is responsible for copying the |
|---|
| 110 | ;; contents of the .data section from its load address (in ROM) to |
|---|
| 111 | ;; its run-time address (in RAM). |
|---|
| 112 | |
|---|
| 113 | START_CRT_FUNC 0300 movedata |
|---|
| 114 | |
|---|
| 115 | mov_ #__datastart, R12 |
|---|
| 116 | mov_ #__romdatastart, R13 |
|---|
| 117 | |
|---|
| 118 | ;; memmove and memcpy do not currently work when src == dst |
|---|
| 119 | cmp_ R12, R13 |
|---|
| 120 | jeq 1f |
|---|
| 121 | |
|---|
| 122 | mov_ #__romdatacopysize, R14 |
|---|
| 123 | |
|---|
| 124 | call_ #memmove |
|---|
| 125 | 1: |
|---|
| 126 | END_CRT_FUNC movedata |
|---|
| 127 | #endif /* Lmovedata */ |
|---|
| 128 | |
|---|
| 129 | |
|---|
| 130 | #ifdef __MSP430X_LARGE__ |
|---|
| 131 | #if Lmove_highdata |
|---|
| 132 | ;; Note - this section is only included in the startup code of the application |
|---|
| 133 | ;; if it is needed. It is responsible either for making sure that the |
|---|
| 134 | ;; contents of the .upper.data section have their correct startup values. |
|---|
| 135 | ;; If a copy of the .upper.data section is stored in ROM then this means |
|---|
| 136 | ;; copying the contents into HIFRAM. If a copy of .upper.data is stored in a |
|---|
| 137 | ;; shadow section in HIFRAM then this means copying from the shadow section |
|---|
| 138 | ;; into the real section. |
|---|
| 139 | |
|---|
| 140 | START_CRT_FUNC 0400 move_highdata |
|---|
| 141 | ;; __rom_highdatacopysize may be zero. Test this first because |
|---|
| 142 | ;; its value may come from the weak definitions above and we do |
|---|
| 143 | ;; not want to access the memory at address 0 pointed to by the |
|---|
| 144 | ;; weak definition of __upper_data_init. |
|---|
| 145 | mov.w #__rom_highdatacopysize, R14 |
|---|
| 146 | cmp.w #0, R14 |
|---|
| 147 | jeq 3f |
|---|
| 148 | |
|---|
| 149 | /* Test our status word. */ |
|---|
| 150 | cmpx.w #0, &__upper_data_init |
|---|
| 151 | jeq 1f |
|---|
| 152 | /* Status word is non-zero - copy from shadow into upper. */ |
|---|
| 153 | mov_ #__high_datastart, R12 |
|---|
| 154 | mov_ #__rom_highdatastart, R13 |
|---|
| 155 | jmp 2f |
|---|
| 156 | |
|---|
| 157 | 1: /* Status word is zero. Copy from upper to shadow and change status word. */ |
|---|
| 158 | movx.w #1, &__upper_data_init |
|---|
| 159 | mov_ #__rom_highdatastart, R12 |
|---|
| 160 | mov_ #__high_datastart, R13 |
|---|
| 161 | |
|---|
| 162 | 2: ;; __rom_highdatacopysize may be zero. memmove should cope. |
|---|
| 163 | mov.w #__rom_highdatacopysize, R14 |
|---|
| 164 | |
|---|
| 165 | call_ #memmove |
|---|
| 166 | 3: |
|---|
| 167 | END_CRT_FUNC move_highdata |
|---|
| 168 | #endif /* Lmove_highdata */ |
|---|
| 169 | #endif /* __MSP430X_LARGE__ */ |
|---|
| 170 | |
|---|
| 171 | |
|---|
| 172 | #if Lmain_minrt |
|---|
| 173 | ;; Note - this section is only included in the startup code of the |
|---|
| 174 | ;; application if it is needed. It is responsible for just calling |
|---|
| 175 | ;; main. No initialization code is called first, and main is not |
|---|
| 176 | ;; expected to return. |
|---|
| 177 | |
|---|
| 178 | START_CRT_FUNC 0600 call_just_main |
|---|
| 179 | |
|---|
| 180 | clr.w R12 ; Set argc == 0 |
|---|
| 181 | call_ #main |
|---|
| 182 | END_CRT_FUNC call_just_main |
|---|
| 183 | #endif /* Lmain_minrt */ |
|---|
| 184 | |
|---|
| 185 | |
|---|
| 186 | #if Lmain |
|---|
| 187 | ;; Note - this section is only included in the startup code of the |
|---|
| 188 | ;; application if it is needed. It is responsible for calling the |
|---|
| 189 | ;; initialization code - constructors, etc - and then main. If main |
|---|
| 190 | ;; returns then the following section should be present to catch it. |
|---|
| 191 | |
|---|
| 192 | START_CRT_FUNC 0700 call_init_then_main |
|---|
| 193 | |
|---|
| 194 | call_ #__msp430_init |
|---|
| 195 | |
|---|
| 196 | clr.w R12 ; Set argc == 0 |
|---|
| 197 | call_ #main |
|---|
| 198 | |
|---|
| 199 | END_CRT_FUNC call_init_then_main |
|---|
| 200 | #endif /* Lmain */ |
|---|
| 201 | |
|---|
| 202 | |
|---|
| 203 | #if Lcallexit |
|---|
| 204 | ;; Note - this section is only included in the startup code of the |
|---|
| 205 | ;; application if it is needed. It is responsible for calling exit |
|---|
| 206 | ;; once main has finished. |
|---|
| 207 | |
|---|
| 208 | START_CRT_FUNC 0800 call_exit |
|---|
| 209 | |
|---|
| 210 | call_ #_exit |
|---|
| 211 | |
|---|
| 212 | END_CRT_FUNC call_exit |
|---|
| 213 | #endif /* Lcallexit */ |
|---|
| 214 | |
|---|
| 215 | ;---------------------------------------- |
|---|
| 216 | |
|---|
| 217 | #ifndef MINRT |
|---|
| 218 | #if L0 |
|---|
| 219 | .section ".crt_0900main_init", "ax", @progbits |
|---|
| 220 | .global _msp430_run_init_array |
|---|
| 221 | .type _msp430_run_init_array,@function |
|---|
| 222 | _msp430_run_init_array: |
|---|
| 223 | mov_ #__init_array_start, R4 |
|---|
| 224 | mov_ #__init_array_end, R5 |
|---|
| 225 | mov_ #PTRsz, R6 |
|---|
| 226 | br_ #_msp430_run_array |
|---|
| 227 | |
|---|
| 228 | .global _msp430_run_preinit_array |
|---|
| 229 | .type _msp430_run_preinit_array,@function |
|---|
| 230 | _msp430_run_preinit_array: |
|---|
| 231 | mov_ #__preinit_array_start, R4 |
|---|
| 232 | mov_ #__preinit_array_end, R5 |
|---|
| 233 | mov_ #PTRsz, R6 |
|---|
| 234 | br_ #_msp430_run_array |
|---|
| 235 | |
|---|
| 236 | .global _msp430_run_fini_array |
|---|
| 237 | .type _msp430_run_fini_array,@function |
|---|
| 238 | _msp430_run_fini_array: |
|---|
| 239 | mov_ #__fini_array_start, R4 |
|---|
| 240 | mov_ #__fini_array_end, R5 |
|---|
| 241 | mov_ #-PTRsz, R6 |
|---|
| 242 | br_ #_msp430_run_array |
|---|
| 243 | |
|---|
| 244 | _msp430_run_array: |
|---|
| 245 | cmp_ R4, R5 |
|---|
| 246 | jeq _msp430_run_done |
|---|
| 247 | mov_ @R4, R7 |
|---|
| 248 | add_ R6, R4 |
|---|
| 249 | call_ @R7 |
|---|
| 250 | br_ _msp430_run_array |
|---|
| 251 | |
|---|
| 252 | _msp430_run_done: |
|---|
| 253 | ret_ |
|---|
| 254 | |
|---|
| 255 | ;---------------------------------------- |
|---|
| 256 | |
|---|
| 257 | .section .init,"ax" |
|---|
| 258 | |
|---|
| 259 | .global __msp430_init |
|---|
| 260 | __msp430_init: |
|---|
| 261 | |
|---|
| 262 | .section .fini,"ax" |
|---|
| 263 | |
|---|
| 264 | .global __msp430_fini |
|---|
| 265 | __msp430_fini: |
|---|
| 266 | call_ #_msp430_run_fini_array |
|---|
| 267 | |
|---|
| 268 | #endif |
|---|
| 269 | #endif /* not MINRT */ |
|---|