0
|
1 /* Copyright (C) 2000, 2001, 2003, 2004, 2005, 2006, 2009
|
|
2 Free Software Foundation, Inc.
|
|
3 This file was pretty much copied from newlib.
|
|
4
|
|
5 This file is part of GCC.
|
|
6
|
|
7 GCC is free software; you can redistribute it and/or modify it
|
|
8 under the terms of the GNU General Public License as published by the
|
|
9 Free Software Foundation; either version 3, or (at your option) any
|
|
10 later version.
|
|
11
|
|
12 GCC is distributed in the hope that it will be useful,
|
|
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
15 General Public License for more details.
|
|
16
|
|
17 Under Section 7 of GPL version 3, you are granted additional
|
|
18 permissions described in the GCC Runtime Library Exception, version
|
|
19 3.1, as published by the Free Software Foundation.
|
|
20
|
|
21 You should have received a copy of the GNU General Public License and
|
|
22 a copy of the GCC Runtime Library Exception along with this program;
|
|
23 see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
|
|
24 <http://www.gnu.org/licenses/>. */
|
|
25
|
|
26
|
|
27 #ifdef MMU_SUPPORT
|
|
28 /* Section used for exception/timer interrupt stack area */
|
|
29 .section .data.vbr.stack,"aw"
|
|
30 .align 4
|
|
31 .global __ST_VBR
|
|
32 __ST_VBR:
|
|
33 .zero 1024 * 2 /* ; 2k for VBR handlers */
|
|
34 /* Label at the highest stack address where the stack grows from */
|
|
35 __timer_stack:
|
|
36 #endif /* MMU_SUPPORT */
|
|
37
|
|
38 /* ;----------------------------------------
|
|
39 Normal newlib crt1.asm */
|
|
40
|
|
41 #ifdef __SH5__
|
|
42 .section .data,"aw"
|
|
43 .global ___data
|
|
44 ___data:
|
|
45
|
|
46 .section .rodata,"a"
|
|
47 .global ___rodata
|
|
48 ___rodata:
|
|
49
|
|
50 #define ICCR_BASE 0x01600000
|
|
51 #define OCCR_BASE 0x01e00000
|
|
52 #define MMUIR_BASE 0x00000000
|
|
53 #define MMUDR_BASE 0x00800000
|
|
54
|
|
55 #define PTE_ENABLED 1
|
|
56 #define PTE_DISABLED 0
|
|
57
|
|
58 #define PTE_SHARED (1 << 1)
|
|
59 #define PTE_NOT_SHARED 0
|
|
60
|
|
61 #define PTE_CB_UNCACHEABLE 0
|
|
62 #define PTE_CB_DEVICE 1
|
|
63 #define PTE_CB_CACHEABLE_WB 2
|
|
64 #define PTE_CB_CACHEABLE_WT 3
|
|
65
|
|
66 #define PTE_SZ_4KB (0 << 3)
|
|
67 #define PTE_SZ_64KB (1 << 3)
|
|
68 #define PTE_SZ_1MB (2 << 3)
|
|
69 #define PTE_SZ_512MB (3 << 3)
|
|
70
|
|
71 #define PTE_PRR (1 << 6)
|
|
72 #define PTE_PRX (1 << 7)
|
|
73 #define PTE_PRW (1 << 8)
|
|
74 #define PTE_PRU (1 << 9)
|
|
75
|
|
76 #define SR_MMU_BIT 31
|
|
77 #define SR_BL_BIT 28
|
|
78
|
|
79 #define ALIGN_4KB (0xfff)
|
|
80 #define ALIGN_1MB (0xfffff)
|
|
81 #define ALIGN_512MB (0x1fffffff)
|
|
82
|
|
83 #define DYNACON_BASE 0x0f000000
|
|
84 #define DM_CB_DLINK_BASE 0x0c000000
|
|
85 #define DM_DB_DLINK_BASE 0x0b000000
|
|
86
|
|
87 #define FEMI_AREA_0 0x00000000
|
|
88 #define FEMI_AREA_1 0x04000000
|
|
89 #define FEMI_AREA_2 0x05000000
|
|
90 #define FEMI_AREA_3 0x06000000
|
|
91 #define FEMI_AREA_4 0x07000000
|
|
92 #define FEMI_CB 0x08000000
|
|
93
|
|
94 #define EMI_BASE 0X80000000
|
|
95
|
|
96 #define DMA_BASE 0X0e000000
|
|
97
|
|
98 #define CPU_BASE 0X0d000000
|
|
99
|
|
100 #define PERIPH_BASE 0X09000000
|
|
101 #define DMAC_BASE 0x0e000000
|
|
102 #define INTC_BASE 0x0a000000
|
|
103 #define CPRC_BASE 0x0a010000
|
|
104 #define TMU_BASE 0x0a020000
|
|
105 #define SCIF_BASE 0x0a030000
|
|
106 #define RTC_BASE 0x0a040000
|
|
107
|
|
108
|
|
109
|
|
110 #define LOAD_CONST32(val, reg) \
|
|
111 movi ((val) >> 16) & 65535, reg; \
|
|
112 shori (val) & 65535, reg
|
|
113
|
|
114 #define LOAD_PTEH_VAL(sym, align, bits, scratch_reg, reg) \
|
|
115 LOAD_ADDR (sym, reg); \
|
|
116 LOAD_CONST32 ((align), scratch_reg); \
|
|
117 andc reg, scratch_reg, reg; \
|
|
118 LOAD_CONST32 ((bits), scratch_reg); \
|
|
119 or reg, scratch_reg, reg
|
|
120
|
|
121 #define LOAD_PTEL_VAL(sym, align, bits, scratch_reg, reg) \
|
|
122 LOAD_ADDR (sym, reg); \
|
|
123 LOAD_CONST32 ((align), scratch_reg); \
|
|
124 andc reg, scratch_reg, reg; \
|
|
125 LOAD_CONST32 ((bits), scratch_reg); \
|
|
126 or reg, scratch_reg, reg
|
|
127
|
|
128 #define SET_PTE(pte_addr_reg, pteh_val_reg, ptel_val_reg) \
|
|
129 putcfg pte_addr_reg, 0, r63; \
|
|
130 putcfg pte_addr_reg, 1, ptel_val_reg; \
|
|
131 putcfg pte_addr_reg, 0, pteh_val_reg
|
|
132
|
|
133 #if __SH5__ == 64
|
|
134 .section .text,"ax"
|
|
135 #define LOAD_ADDR(sym, reg) \
|
|
136 movi (sym >> 48) & 65535, reg; \
|
|
137 shori (sym >> 32) & 65535, reg; \
|
|
138 shori (sym >> 16) & 65535, reg; \
|
|
139 shori sym & 65535, reg
|
|
140 #else
|
|
141 .mode SHmedia
|
|
142 .section .text..SHmedia32,"ax"
|
|
143 #define LOAD_ADDR(sym, reg) \
|
|
144 movi (sym >> 16) & 65535, reg; \
|
|
145 shori sym & 65535, reg
|
|
146 #endif
|
|
147 .global start
|
|
148 start:
|
|
149 LOAD_ADDR (_stack, r15)
|
|
150
|
|
151 #ifdef MMU_SUPPORT
|
|
152 ! Set up the VM using the MMU and caches
|
|
153
|
|
154 ! .vm_ep is first instruction to execute
|
|
155 ! after VM initialization
|
|
156 pt/l .vm_ep, tr1
|
|
157
|
|
158 ! Configure instruction cache (ICCR)
|
|
159 movi 3, r2
|
|
160 movi 0, r3
|
|
161 LOAD_ADDR (ICCR_BASE, r1)
|
|
162 putcfg r1, 0, r2
|
|
163 putcfg r1, 1, r3
|
|
164
|
|
165 ! movi 7, r2 ! write through
|
|
166 ! Configure operand cache (OCCR)
|
|
167 LOAD_ADDR (OCCR_BASE, r1)
|
|
168 putcfg r1, 0, r2
|
|
169 putcfg r1, 1, r3
|
|
170
|
|
171 ! Disable all PTE translations
|
|
172 LOAD_ADDR (MMUIR_BASE, r1)
|
|
173 LOAD_ADDR (MMUDR_BASE, r2)
|
|
174 movi 64, r3
|
|
175 pt/l .disable_ptes_loop, tr0
|
|
176 .disable_ptes_loop:
|
|
177 putcfg r1, 0, r63
|
|
178 putcfg r2, 0, r63
|
|
179 addi r1, 16, r1
|
|
180 addi r2, 16, r2
|
|
181 addi r3, -1, r3
|
|
182 bgt r3, r63, tr0
|
|
183
|
|
184 LOAD_ADDR (MMUIR_BASE, r1)
|
|
185
|
|
186 ! FEMI instruction mappings
|
|
187 ! Area 0 - 1Mb cacheable at 0x00000000
|
|
188 ! Area 1 - None
|
|
189 ! Area 2 - 1Mb cacheable at 0x05000000
|
|
190 ! - 1Mb cacheable at 0x05100000
|
|
191 ! Area 3 - None
|
|
192 ! Area 4 - None
|
|
193
|
|
194 ! Map a 1Mb page for instructions at 0x00000000
|
|
195 LOAD_PTEH_VAL (FEMI_AREA_0, ALIGN_1MB, PTE_ENABLED | PTE_NOT_SHARED, r25, r2)
|
|
196 LOAD_PTEL_VAL (FEMI_AREA_0, ALIGN_1MB, PTE_CB_CACHEABLE_WB | PTE_SZ_1MB | PTE_PRX | PTE_PRU, r25, r3)
|
|
197 SET_PTE (r1, r2, r3)
|
|
198
|
|
199 ! Map a 1Mb page for instructions at 0x05000000
|
|
200 addi r1, 16, r1
|
|
201 LOAD_PTEH_VAL (FEMI_AREA_2, ALIGN_1MB, PTE_ENABLED | PTE_NOT_SHARED, r25, r2)
|
|
202 LOAD_PTEL_VAL (FEMI_AREA_2, ALIGN_1MB, PTE_CB_CACHEABLE_WB | PTE_SZ_1MB | PTE_PRX | PTE_PRU, r25, r3)
|
|
203 SET_PTE (r1, r2, r3)
|
|
204
|
|
205 ! Map a 1Mb page for instructions at 0x05100000
|
|
206 addi r1, 16, r1
|
|
207 LOAD_PTEH_VAL ((FEMI_AREA_2+0x100000), ALIGN_1MB, PTE_ENABLED | PTE_NOT_SHARED, r25, r2)
|
|
208 LOAD_PTEL_VAL ((FEMI_AREA_2+0x100000), ALIGN_1MB, PTE_CB_CACHEABLE_WB | PTE_SZ_1MB | PTE_PRX | PTE_PRU, r25, r3)
|
|
209 SET_PTE (r1, r2, r3)
|
|
210
|
|
211 ! Map a 512M page for instructions at EMI base
|
|
212 addi r1, 16, r1
|
|
213 LOAD_PTEH_VAL (EMI_BASE, ALIGN_512MB, PTE_ENABLED | PTE_NOT_SHARED, r25, r2)
|
|
214 LOAD_PTEL_VAL (EMI_BASE, ALIGN_512MB, PTE_CB_CACHEABLE_WB | PTE_SZ_512MB | PTE_PRX | PTE_PRU, r25, r3)
|
|
215 SET_PTE (r1, r2, r3)
|
|
216
|
|
217 ! Map a 4K page for instructions at DM_DB_DLINK_BASE
|
|
218 addi r1, 16, r1
|
|
219 LOAD_PTEH_VAL (DM_DB_DLINK_BASE, ALIGN_4KB, PTE_ENABLED | PTE_NOT_SHARED, r25, r2)
|
|
220 LOAD_PTEL_VAL (DM_DB_DLINK_BASE, ALIGN_4KB, PTE_CB_CACHEABLE_WB | PTE_SZ_4KB | PTE_PRX | PTE_PRU, r25, r3)
|
|
221 SET_PTE (r1, r2, r3)
|
|
222
|
|
223 LOAD_ADDR (MMUDR_BASE, r1)
|
|
224
|
|
225 ! FEMI data mappings
|
|
226 ! Area 0 - 1Mb cacheable at 0x00000000
|
|
227 ! Area 1 - 1Mb device at 0x04000000
|
|
228 ! Area 2 - 1Mb cacheable at 0x05000000
|
|
229 ! - 1Mb cacheable at 0x05100000
|
|
230 ! Area 3 - None
|
|
231 ! Area 4 - None
|
|
232 ! CB - 1Mb device at 0x08000000
|
|
233
|
|
234 ! Map a 1Mb page for data at 0x00000000
|
|
235 LOAD_PTEH_VAL (FEMI_AREA_0, ALIGN_1MB, PTE_ENABLED | PTE_NOT_SHARED, r25, r2)
|
|
236 LOAD_PTEL_VAL (FEMI_AREA_0, ALIGN_1MB, PTE_CB_CACHEABLE_WB | PTE_SZ_1MB | PTE_PRR | PTE_PRW | PTE_PRU, r25, r3)
|
|
237 SET_PTE (r1, r2, r3)
|
|
238
|
|
239 ! Map a 1Mb page for data at 0x04000000
|
|
240 addi r1, 16, r1
|
|
241 LOAD_PTEH_VAL (FEMI_AREA_1, ALIGN_1MB, PTE_ENABLED | PTE_NOT_SHARED, r25, r2)
|
|
242 LOAD_PTEL_VAL (FEMI_AREA_1, ALIGN_1MB, PTE_CB_DEVICE | PTE_SZ_1MB | PTE_PRR | PTE_PRW | PTE_PRU, r25, r3)
|
|
243 SET_PTE (r1, r2, r3)
|
|
244
|
|
245 ! Map a 1Mb page for data at 0x05000000
|
|
246 addi r1, 16, r1
|
|
247 LOAD_PTEH_VAL (FEMI_AREA_2, ALIGN_1MB, PTE_ENABLED | PTE_NOT_SHARED, r25, r2)
|
|
248 LOAD_PTEL_VAL (FEMI_AREA_2, ALIGN_1MB, PTE_CB_CACHEABLE_WB | PTE_SZ_1MB | PTE_PRR | PTE_PRW | PTE_PRU, r25, r3)
|
|
249 SET_PTE (r1, r2, r3)
|
|
250
|
|
251 ! Map a 1Mb page for data at 0x05100000
|
|
252 addi r1, 16, r1
|
|
253 LOAD_PTEH_VAL ((FEMI_AREA_2+0x100000), ALIGN_1MB, PTE_ENABLED | PTE_NOT_SHARED, r25, r2)
|
|
254 LOAD_PTEL_VAL ((FEMI_AREA_2+0x100000), ALIGN_1MB, PTE_CB_CACHEABLE_WB | PTE_SZ_1MB | PTE_PRR | PTE_PRW | PTE_PRU, r25, r3)
|
|
255 SET_PTE (r1, r2, r3)
|
|
256
|
|
257 ! Map a 4K page for registers at 0x08000000
|
|
258 addi r1, 16, r1
|
|
259 LOAD_PTEH_VAL (FEMI_CB, ALIGN_4KB, PTE_ENABLED | PTE_NOT_SHARED, r25, r2)
|
|
260 LOAD_PTEL_VAL (FEMI_CB, ALIGN_4KB, PTE_CB_DEVICE | PTE_SZ_4KB | PTE_PRR | PTE_PRW | PTE_PRU, r25, r3)
|
|
261 SET_PTE (r1, r2, r3)
|
|
262
|
|
263 ! Map a 512M page for data at EMI
|
|
264 addi r1, 16, r1
|
|
265 LOAD_PTEH_VAL (EMI_BASE, ALIGN_512MB, PTE_ENABLED | PTE_NOT_SHARED, r25, r2)
|
|
266 LOAD_PTEL_VAL (EMI_BASE, ALIGN_512MB, PTE_CB_CACHEABLE_WB | PTE_SZ_512MB | PTE_PRR | PTE_PRW | PTE_PRU, r25, r3)
|
|
267 SET_PTE (r1, r2, r3)
|
|
268
|
|
269 ! Map a 4K page for DYNACON at DYNACON_BASE
|
|
270 addi r1, 16, r1
|
|
271 LOAD_PTEH_VAL (DYNACON_BASE, ALIGN_4KB, PTE_ENABLED | PTE_NOT_SHARED, r25, r2)
|
|
272 LOAD_PTEL_VAL (DYNACON_BASE, ALIGN_4KB, PTE_CB_DEVICE | PTE_SZ_4KB | PTE_PRR | PTE_PRW | PTE_PRU, r25, r3)
|
|
273 SET_PTE (r1, r2, r3)
|
|
274
|
|
275 ! Map a 4K page for instructions at DM_DB_DLINK_BASE
|
|
276 addi r1, 16, r1
|
|
277 LOAD_PTEH_VAL (DM_DB_DLINK_BASE, ALIGN_4KB, PTE_ENABLED | PTE_NOT_SHARED, r25, r2)
|
|
278 LOAD_PTEL_VAL (DM_DB_DLINK_BASE, ALIGN_4KB, PTE_CB_CACHEABLE_WB | PTE_SZ_4KB | PTE_PRR | PTE_PRW | PTE_PRU, r25, r3)
|
|
279 SET_PTE (r1, r2, r3)
|
|
280
|
|
281 ! Map a 4K page for data at DM_DB_DLINK_BASE+0x1000
|
|
282 addi r1, 16, r1
|
|
283 LOAD_PTEH_VAL ((DM_DB_DLINK_BASE+0x1000), ALIGN_4KB, PTE_ENABLED | PTE_NOT_SHARED, r25, r2)
|
|
284 LOAD_PTEL_VAL ((DM_DB_DLINK_BASE+0x1000), ALIGN_4KB, PTE_CB_UNCACHEABLE | PTE_SZ_4KB | PTE_PRR | PTE_PRW | PTE_PRU, r25, r3)
|
|
285 SET_PTE (r1, r2, r3)
|
|
286
|
|
287 ! Map a 4K page for stack DM_DB_DLINK_BASE+0x2000
|
|
288 addi r1, 16, r1
|
|
289 LOAD_PTEH_VAL ((DM_DB_DLINK_BASE+0x2000), ALIGN_4KB, PTE_ENABLED | PTE_NOT_SHARED, r25, r2)
|
|
290 LOAD_PTEL_VAL ((DM_DB_DLINK_BASE+0x2000), ALIGN_4KB, PTE_CB_CACHEABLE_WB | PTE_SZ_4KB | PTE_PRR | PTE_PRW | PTE_PRU, r25, r3)
|
|
291 SET_PTE (r1, r2, r3)
|
|
292
|
|
293 ! Map a 1M page for DM_CB_BASE2 at DM_CB_DLINK
|
|
294 ! 0x0c000000 - 0x0c0fffff
|
|
295 addi r1, 16, r1
|
|
296 LOAD_PTEH_VAL (DM_CB_DLINK_BASE, ALIGN_1MB, PTE_ENABLED | PTE_NOT_SHARED, r25, r2)
|
|
297 LOAD_PTEL_VAL (DM_CB_DLINK_BASE, ALIGN_1MB, PTE_CB_DEVICE | PTE_SZ_1MB | PTE_PRR | PTE_PRW | PTE_PRU, r25, r3)
|
|
298 SET_PTE (r1, r2, r3)
|
|
299
|
|
300 ! Map a 1M page for DM_CB_BASE2 at DM_CB_DLINK
|
|
301 ! 0x0c100000 - 0x0c1fffff
|
|
302 addi r1, 16, r1
|
|
303 LOAD_PTEH_VAL ((DM_CB_DLINK_BASE+0x100000), ALIGN_1MB, PTE_ENABLED | PTE_NOT_SHARED, r25, r2)
|
|
304 LOAD_PTEL_VAL ((DM_CB_DLINK_BASE+0x100000), ALIGN_1MB, PTE_CB_DEVICE | PTE_SZ_1MB | PTE_PRR | PTE_PRW | PTE_PRU, r25, r3)
|
|
305 SET_PTE (r1, r2, r3)
|
|
306
|
|
307 ! Map a 1M page for DM_CB_BASE2 at DM_CB_DLINK
|
|
308 ! 0x0c200000 - 0x0c2fffff
|
|
309 addi r1, 16, r1
|
|
310 LOAD_PTEH_VAL ((DM_CB_DLINK_BASE+0x200000), ALIGN_1MB, PTE_ENABLED | PTE_NOT_SHARED, r25, r2)
|
|
311 LOAD_PTEL_VAL ((DM_CB_DLINK_BASE+0x200000), ALIGN_1MB, PTE_CB_DEVICE | PTE_SZ_1MB | PTE_PRR | PTE_PRW | PTE_PRU, r25, r3)
|
|
312 SET_PTE (r1, r2, r3)
|
|
313
|
|
314 ! Map a 1M page for DM_CB_BASE2 at DM_CB_DLINK
|
|
315 ! 0x0c400000 - 0x0c4fffff
|
|
316 addi r1, 16, r1
|
|
317 LOAD_PTEH_VAL ((DM_CB_DLINK_BASE+0x400000), ALIGN_1MB, PTE_ENABLED | PTE_NOT_SHARED, r25, r2)
|
|
318 LOAD_PTEL_VAL ((DM_CB_DLINK_BASE+0x400000), ALIGN_1MB, PTE_CB_DEVICE | PTE_SZ_1MB | PTE_PRR | PTE_PRW | PTE_PRU, r25, r3)
|
|
319 SET_PTE (r1, r2, r3)
|
|
320
|
|
321 ! Map a 1M page for DM_CB_BASE2 at DM_CB_DLINK
|
|
322 ! 0x0c800000 - 0x0c8fffff
|
|
323 addi r1, 16, r1
|
|
324 LOAD_PTEH_VAL ((DM_CB_DLINK_BASE+0x800000), ALIGN_1MB, PTE_ENABLED | PTE_NOT_SHARED, r25, r2)
|
|
325 LOAD_PTEL_VAL ((DM_CB_DLINK_BASE+0x800000), ALIGN_1MB, PTE_CB_DEVICE | PTE_SZ_1MB | PTE_PRR | PTE_PRW | PTE_PRU, r25, r3)
|
|
326 SET_PTE (r1, r2, r3)
|
|
327
|
|
328 ! Map a 4K page for DMA control registers
|
|
329 addi r1, 16, r1
|
|
330 LOAD_PTEH_VAL (DMA_BASE, ALIGN_4KB, PTE_ENABLED | PTE_NOT_SHARED, r25, r2)
|
|
331 LOAD_PTEL_VAL (DMA_BASE, ALIGN_4KB, PTE_CB_DEVICE | PTE_SZ_4KB | PTE_PRR | PTE_PRW | PTE_PRU, r25, r3)
|
|
332 SET_PTE (r1, r2, r3)
|
|
333
|
|
334 ! Map lots of 4K pages for peripherals
|
|
335
|
|
336 ! /* peripheral */
|
|
337 addi r1, 16, r1
|
|
338 LOAD_PTEH_VAL (PERIPH_BASE, ALIGN_4KB, PTE_ENABLED | PTE_NOT_SHARED, r25, r2)
|
|
339 LOAD_PTEL_VAL (PERIPH_BASE, ALIGN_4KB, PTE_CB_DEVICE | PTE_SZ_4KB | PTE_PRR | PTE_PRW | PTE_PRU, r25, r3)
|
|
340 SET_PTE (r1, r2, r3)
|
|
341 ! /* dmac */
|
|
342 addi r1, 16, r1
|
|
343 LOAD_PTEH_VAL (DMAC_BASE, ALIGN_4KB, PTE_ENABLED | PTE_NOT_SHARED, r25, r2)
|
|
344 LOAD_PTEL_VAL (DMAC_BASE, ALIGN_4KB, PTE_CB_DEVICE | PTE_SZ_4KB | PTE_PRR | PTE_PRW | PTE_PRU, r25, r3)
|
|
345 SET_PTE (r1, r2, r3)
|
|
346 ! /* intc */
|
|
347 addi r1, 16, r1
|
|
348 LOAD_PTEH_VAL (INTC_BASE, ALIGN_4KB, PTE_ENABLED | PTE_NOT_SHARED, r25, r2)
|
|
349 LOAD_PTEL_VAL (INTC_BASE, ALIGN_4KB, PTE_CB_DEVICE | PTE_SZ_4KB | PTE_PRR | PTE_PRW | PTE_PRU, r25, r3)
|
|
350 SET_PTE (r1, r2, r3)
|
|
351 ! /* rtc */
|
|
352 addi r1, 16, r1
|
|
353 LOAD_PTEH_VAL (RTC_BASE, ALIGN_4KB, PTE_ENABLED | PTE_NOT_SHARED, r25, r2)
|
|
354 LOAD_PTEL_VAL (RTC_BASE, ALIGN_4KB, PTE_CB_DEVICE | PTE_SZ_4KB | PTE_PRR | PTE_PRW | PTE_PRU, r25, r3)
|
|
355 SET_PTE (r1, r2, r3)
|
|
356 ! /* dmac */
|
|
357 addi r1, 16, r1
|
|
358 LOAD_PTEH_VAL (TMU_BASE, ALIGN_4KB, PTE_ENABLED | PTE_NOT_SHARED, r25, r2)
|
|
359 LOAD_PTEL_VAL (TMU_BASE, ALIGN_4KB, PTE_CB_DEVICE | PTE_SZ_4KB | PTE_PRR | PTE_PRW | PTE_PRU, r25, r3)
|
|
360 SET_PTE (r1, r2, r3)
|
|
361 ! /* scif */
|
|
362 addi r1, 16, r1
|
|
363 LOAD_PTEH_VAL (SCIF_BASE, ALIGN_4KB, PTE_ENABLED | PTE_NOT_SHARED, r25, r2)
|
|
364 LOAD_PTEL_VAL (SCIF_BASE, ALIGN_4KB, PTE_CB_DEVICE | PTE_SZ_4KB | PTE_PRR | PTE_PRW | PTE_PRU, r25, r3)
|
|
365 SET_PTE (r1, r2, r3)
|
|
366 ! /* cprc */
|
|
367 addi r1, 16, r1
|
|
368 LOAD_PTEH_VAL (CPRC_BASE, ALIGN_4KB, PTE_ENABLED | PTE_NOT_SHARED, r25, r2)
|
|
369 LOAD_PTEL_VAL (CPRC_BASE, ALIGN_4KB, PTE_CB_DEVICE | PTE_SZ_4KB | PTE_PRR | PTE_PRW | PTE_PRU, r25, r3)
|
|
370 SET_PTE (r1, r2, r3)
|
|
371
|
|
372 ! Map CPU WPC registers
|
|
373 addi r1, 16, r1
|
|
374 LOAD_PTEH_VAL (CPU_BASE, ALIGN_1MB, PTE_ENABLED | PTE_NOT_SHARED, r25, r2)
|
|
375 LOAD_PTEL_VAL (CPU_BASE, ALIGN_1MB, PTE_CB_DEVICE | PTE_SZ_1MB | PTE_PRR | PTE_PRW | PTE_PRU, r25, r3)
|
|
376 SET_PTE (r1, r2, r3)
|
|
377 addi r1, 16, r1
|
|
378
|
|
379 LOAD_PTEH_VAL ((CPU_BASE+0x100000), ALIGN_1MB, PTE_ENABLED | PTE_NOT_SHARED, r25, r2)
|
|
380 LOAD_PTEL_VAL ((CPU_BASE+0x100000), ALIGN_1MB, PTE_CB_DEVICE | PTE_SZ_1MB | PTE_PRR | PTE_PRW | PTE_PRU, r25, r3)
|
|
381 SET_PTE (r1, r2, r3)
|
|
382
|
|
383 addi r1, 16, r1
|
|
384 LOAD_PTEH_VAL ((CPU_BASE+0x200000), ALIGN_1MB, PTE_ENABLED | PTE_NOT_SHARED, r25, r2)
|
|
385 LOAD_PTEL_VAL ((CPU_BASE+0x200000), ALIGN_1MB, PTE_CB_DEVICE | PTE_SZ_1MB | PTE_PRR | PTE_PRW | PTE_PRU, r25, r3)
|
|
386 SET_PTE (r1, r2, r3)
|
|
387
|
|
388 addi r1, 16, r1
|
|
389 LOAD_PTEH_VAL ((CPU_BASE+0x400000), ALIGN_1MB, PTE_ENABLED | PTE_NOT_SHARED, r25, r2)
|
|
390 LOAD_PTEL_VAL ((CPU_BASE+0x400000), ALIGN_1MB, PTE_CB_DEVICE | PTE_SZ_1MB | PTE_PRR | PTE_PRW | PTE_PRU, r25, r3)
|
|
391 SET_PTE (r1, r2, r3)
|
|
392
|
|
393 ! Switch over to virtual addressing and enabled cache
|
|
394 getcon sr, r1
|
|
395 movi 1, r2
|
|
396 shlli r2, SR_BL_BIT, r2
|
|
397 or r1, r2, r1
|
|
398 putcon r1, ssr
|
|
399 getcon sr, r1
|
|
400 movi 1, r2
|
|
401 shlli r2, SR_MMU_BIT, r2
|
|
402 or r1, r2, r1
|
|
403 putcon r1, ssr
|
|
404 gettr tr1, r1
|
|
405 putcon r1, spc
|
|
406 synco
|
|
407 rte
|
|
408
|
|
409 ! VM entry point. From now on, we are in VM mode.
|
|
410 .vm_ep:
|
|
411
|
|
412 ! Install the trap handler, by seeding vbr with the
|
|
413 ! correct value, and by assigning sr.bl = 0.
|
|
414
|
|
415 LOAD_ADDR (vbr_start, r1)
|
|
416 putcon r1, vbr
|
|
417 movi ~(1<<28), r1
|
|
418 getcon sr, r2
|
|
419 and r1, r2, r2
|
|
420 putcon r2, sr
|
|
421 #endif /* MMU_SUPPORT */
|
|
422
|
|
423 pt/l .Lzero_bss_loop, tr0
|
|
424 pt/l _init, tr5
|
|
425 pt/l ___setup_argv_and_call_main, tr6
|
|
426 pt/l _exit, tr7
|
|
427
|
|
428 ! zero out bss
|
|
429 LOAD_ADDR (_edata, r0)
|
|
430 LOAD_ADDR (_end, r1)
|
|
431 .Lzero_bss_loop:
|
|
432 stx.q r0, r63, r63
|
|
433 addi r0, 8, r0
|
|
434 bgt/l r1, r0, tr0
|
|
435
|
|
436 LOAD_ADDR (___data, r26)
|
|
437 LOAD_ADDR (___rodata, r27)
|
|
438
|
|
439 #ifdef __SH_FPU_ANY__
|
|
440 getcon sr, r0
|
|
441 ! enable the FP unit, by resetting SR.FD
|
|
442 ! also zero out SR.FR, SR.SZ and SR.PR, as mandated by the ABI
|
|
443 movi 0, r1
|
|
444 shori 0xf000, r1
|
|
445 andc r0, r1, r0
|
|
446 putcon r0, sr
|
|
447 #if __SH5__ == 32
|
|
448 pt/l ___set_fpscr, tr0
|
|
449 movi 0, r4
|
|
450 blink tr0, r18
|
|
451 #endif
|
|
452 #endif
|
|
453
|
|
454 ! arrange for exit to call fini
|
|
455 pt/l _atexit, tr1
|
|
456 LOAD_ADDR (_fini, r2)
|
|
457 blink tr1, r18
|
|
458
|
|
459 ! call init
|
|
460 blink tr5, r18
|
|
461
|
|
462 ! call the mainline
|
|
463 blink tr6, r18
|
|
464
|
|
465 ! call exit
|
|
466 blink tr7, r18
|
|
467 ! We should never return from _exit but in case we do we would enter the
|
|
468 ! the following tight loop. This avoids executing any data that might follow.
|
|
469 limbo:
|
|
470 pt/l limbo, tr0
|
|
471 blink tr0, r63
|
|
472
|
|
473 #ifdef MMU_SUPPORT
|
|
474 ! All these traps are handled in the same place.
|
|
475 .balign 256
|
|
476 vbr_start:
|
|
477 pt/l handler, tr0 ! tr0 trashed.
|
|
478 blink tr0, r63
|
|
479 .balign 256
|
|
480 vbr_100:
|
|
481 pt/l handler, tr0 ! tr0 trashed.
|
|
482 blink tr0, r63
|
|
483 vbr_100_end:
|
|
484 .balign 256
|
|
485 vbr_200:
|
|
486 pt/l handler, tr0 ! tr0 trashed.
|
|
487 blink tr0, r63
|
|
488 .balign 256
|
|
489 vbr_300:
|
|
490 pt/l handler, tr0 ! tr0 trashed.
|
|
491 blink tr0, r63
|
|
492 .balign 256
|
|
493 vbr_400: ! Should be at vbr+0x400
|
|
494 handler:
|
|
495 /* If the trap handler is there call it */
|
|
496 LOAD_ADDR (__superh_trap_handler, r2)
|
|
497 pta chandler,tr2
|
|
498 beq r2, r63, tr2 /* If zero, ie not present branch around to chandler */
|
|
499 /* Now call the trap handler with as much of the context unchanged as possible.
|
|
500 Move trapping address into R18 to make it look like the trap point */
|
|
501 getcon spc, r18
|
|
502 pt/l __superh_trap_handler, tr0
|
|
503 blink tr0, r7
|
|
504 chandler:
|
|
505 getcon spc, r62
|
|
506 getcon expevt, r2
|
|
507 pt/l _exit, tr0
|
|
508 blink tr0, r63
|
|
509
|
|
510 /* Simulated trap handler */
|
|
511 .section .text..SHmedia32,"ax"
|
|
512 gcc2_compiled.:
|
|
513 .section .debug_abbrev
|
|
514 .Ldebug_abbrev0:
|
|
515 .section .text..SHmedia32
|
|
516 .Ltext0:
|
|
517 .section .debug_info
|
|
518 .Ldebug_info0:
|
|
519 .section .debug_line
|
|
520 .Ldebug_line0:
|
|
521 .section .text..SHmedia32,"ax"
|
|
522 .align 5
|
|
523 .global __superh_trap_handler
|
|
524 .type __superh_trap_handler,@function
|
|
525 __superh_trap_handler:
|
|
526 .LFB1:
|
|
527 ptabs r18, tr0
|
|
528 addi.l r15, -8, r15
|
|
529 st.l r15, 4, r14
|
|
530 addi.l r15, -8, r15
|
|
531 add.l r15, r63, r14
|
|
532 st.l r14, 0, r2
|
|
533 ptabs r7, tr0
|
|
534 addi.l r14, 8, r14
|
|
535 add.l r14, r63, r15
|
|
536 ld.l r15, 4, r14
|
|
537 addi.l r15, 8, r15
|
|
538 blink tr0, r63
|
|
539 .LFE1:
|
|
540 .Lfe1:
|
|
541 .size __superh_trap_handler,.Lfe1-__superh_trap_handler
|
|
542
|
|
543 .section .text..SHmedia32
|
|
544 .Letext0:
|
|
545
|
|
546 .section .debug_info
|
|
547 .ualong 0xa7
|
|
548 .uaword 0x2
|
|
549 .ualong .Ldebug_abbrev0
|
|
550 .byte 0x4
|
|
551 .byte 0x1
|
|
552 .ualong .Ldebug_line0
|
|
553 .ualong .Letext0
|
|
554 .ualong .Ltext0
|
|
555 .string "trap_handler.c"
|
|
556
|
|
557 .string "xxxxxxxxxxxxxxxxxxxxxxxxxxxx"
|
|
558
|
|
559 .string "GNU C 2.97-sh5-010522"
|
|
560
|
|
561 .byte 0x1
|
|
562 .byte 0x2
|
|
563 .ualong 0x9a
|
|
564 .byte 0x1
|
|
565 .string "_superh_trap_handler"
|
|
566
|
|
567 .byte 0x1
|
|
568 .byte 0x2
|
|
569 .byte 0x1
|
|
570 .ualong .LFB1
|
|
571 .ualong .LFE1
|
|
572 .byte 0x1
|
|
573 .byte 0x5e
|
|
574 .byte 0x3
|
|
575 .string "trap_reason"
|
|
576
|
|
577 .byte 0x1
|
|
578 .byte 0x1
|
|
579 .ualong 0x9a
|
|
580 .byte 0x2
|
|
581 .byte 0x91
|
|
582 .byte 0x0
|
|
583 .byte 0x0
|
|
584 .byte 0x4
|
|
585 .string "unsigned int"
|
|
586
|
|
587 .byte 0x4
|
|
588 .byte 0x7
|
|
589 .byte 0x0
|
|
590
|
|
591 .section .debug_abbrev
|
|
592 .byte 0x1
|
|
593 .byte 0x11
|
|
594 .byte 0x1
|
|
595 .byte 0x10
|
|
596 .byte 0x6
|
|
597 .byte 0x12
|
|
598 .byte 0x1
|
|
599 .byte 0x11
|
|
600 .byte 0x1
|
|
601 .byte 0x3
|
|
602 .byte 0x8
|
|
603 .byte 0x1b
|
|
604 .byte 0x8
|
|
605 .byte 0x25
|
|
606 .byte 0x8
|
|
607 .byte 0x13
|
|
608 .byte 0xb
|
|
609 .byte 0,0
|
|
610 .byte 0x2
|
|
611 .byte 0x2e
|
|
612 .byte 0x1
|
|
613 .byte 0x1
|
|
614 .byte 0x13
|
|
615 .byte 0x3f
|
|
616 .byte 0xc
|
|
617 .byte 0x3
|
|
618 .byte 0x8
|
|
619 .byte 0x3a
|
|
620 .byte 0xb
|
|
621 .byte 0x3b
|
|
622 .byte 0xb
|
|
623 .byte 0x27
|
|
624 .byte 0xc
|
|
625 .byte 0x11
|
|
626 .byte 0x1
|
|
627 .byte 0x12
|
|
628 .byte 0x1
|
|
629 .byte 0x40
|
|
630 .byte 0xa
|
|
631 .byte 0,0
|
|
632 .byte 0x3
|
|
633 .byte 0x5
|
|
634 .byte 0x0
|
|
635 .byte 0x3
|
|
636 .byte 0x8
|
|
637 .byte 0x3a
|
|
638 .byte 0xb
|
|
639 .byte 0x3b
|
|
640 .byte 0xb
|
|
641 .byte 0x49
|
|
642 .byte 0x13
|
|
643 .byte 0x2
|
|
644 .byte 0xa
|
|
645 .byte 0,0
|
|
646 .byte 0x4
|
|
647 .byte 0x24
|
|
648 .byte 0x0
|
|
649 .byte 0x3
|
|
650 .byte 0x8
|
|
651 .byte 0xb
|
|
652 .byte 0xb
|
|
653 .byte 0x3e
|
|
654 .byte 0xb
|
|
655 .byte 0,0
|
|
656 .byte 0
|
|
657
|
|
658 .section .debug_pubnames
|
|
659 .ualong 0x27
|
|
660 .uaword 0x2
|
|
661 .ualong .Ldebug_info0
|
|
662 .ualong 0xab
|
|
663 .ualong 0x5b
|
|
664 .string "_superh_trap_handler"
|
|
665
|
|
666 .ualong 0x0
|
|
667
|
|
668 .section .debug_aranges
|
|
669 .ualong 0x1c
|
|
670 .uaword 0x2
|
|
671 .ualong .Ldebug_info0
|
|
672 .byte 0x4
|
|
673 .byte 0x0
|
|
674 .uaword 0x0,0
|
|
675 .ualong .Ltext0
|
|
676 .ualong .Letext0-.Ltext0
|
|
677 .ualong 0x0
|
|
678 .ualong 0x0
|
|
679 .ident "GCC: (GNU) 2.97-sh5-010522"
|
|
680 #endif /* MMU_SUPPORT */
|
|
681 #else /* ! __SH5__ */
|
|
682
|
|
683 ! make a place to keep any previous value of the vbr register
|
|
684 ! this will only have a value if it has been set by redboot (for example)
|
|
685 .section .bss
|
|
686 old_vbr:
|
|
687 .long 0
|
|
688 #ifdef PROFILE
|
|
689 profiling_enabled:
|
|
690 .long 0
|
|
691 #endif
|
|
692
|
|
693
|
|
694 .section .text
|
|
695 .global start
|
|
696 .import ___rtos_profiler_start_timer
|
|
697 .weak ___rtos_profiler_start_timer
|
|
698 start:
|
|
699 mov.l stack_k,r15
|
|
700
|
|
701 #if defined (__SH3__) || (defined (__SH_FPU_ANY__) && ! defined (__SH2A__)) || defined (__SH4_NOFPU__)
|
|
702 #define VBR_SETUP
|
|
703 ! before zeroing the bss ...
|
|
704 ! if the vbr is already set to vbr_start then the program has been restarted
|
|
705 ! (i.e. it is not the first time the program has been run since reset)
|
|
706 ! reset the vbr to its old value before old_vbr (in bss) is wiped
|
|
707 ! this ensures that the later code does not create a circular vbr chain
|
|
708 stc vbr, r1
|
|
709 mov.l vbr_start_k, r2
|
|
710 cmp/eq r1, r2
|
|
711 bf 0f
|
|
712 ! reset the old vbr value
|
|
713 mov.l old_vbr_k, r1
|
|
714 mov.l @r1, r2
|
|
715 ldc r2, vbr
|
|
716 0:
|
|
717 #endif /* VBR_SETUP */
|
|
718
|
|
719 ! zero out bss
|
|
720 mov.l edata_k,r0
|
|
721 mov.l end_k,r1
|
|
722 mov #0,r2
|
|
723 start_l:
|
|
724 mov.l r2,@r0
|
|
725 add #4,r0
|
|
726 cmp/ge r0,r1
|
|
727 bt start_l
|
|
728
|
|
729 #if defined (__SH_FPU_ANY__)
|
|
730 mov.l set_fpscr_k, r1
|
|
731 mov #4,r4
|
|
732 jsr @r1
|
|
733 shll16 r4 ! Set DN bit (flush denormal inputs to zero)
|
|
734 lds r3,fpscr ! Switch to default precision
|
|
735 #endif /* defined (__SH_FPU_ANY__) */
|
|
736
|
|
737 #ifdef VBR_SETUP
|
|
738 ! save the existing contents of the vbr
|
|
739 ! there will only be a prior value when using something like redboot
|
|
740 ! otherwise it will be zero
|
|
741 stc vbr, r1
|
|
742 mov.l old_vbr_k, r2
|
|
743 mov.l r1, @r2
|
|
744 ! setup vbr
|
|
745 mov.l vbr_start_k, r1
|
|
746 ldc r1,vbr
|
|
747 #endif /* VBR_SETUP */
|
|
748
|
|
749 ! if an rtos is exporting a timer start fn,
|
|
750 ! then pick up an SR which does not enable ints
|
|
751 ! (the rtos will take care of this)
|
|
752 mov.l rtos_start_fn, r0
|
|
753 mov.l sr_initial_bare, r1
|
|
754 tst r0, r0
|
|
755 bt set_sr
|
|
756
|
|
757 mov.l sr_initial_rtos, r1
|
|
758
|
|
759 set_sr:
|
|
760 ! Set status register (sr)
|
|
761 ldc r1, sr
|
|
762
|
|
763 ! arrange for exit to call fini
|
|
764 mov.l atexit_k,r0
|
|
765 mov.l fini_k,r4
|
|
766 jsr @r0
|
|
767 nop
|
|
768
|
|
769 #ifdef PROFILE
|
|
770 ! arrange for exit to call _mcleanup (via stop_profiling)
|
|
771 mova stop_profiling,r0
|
|
772 mov.l atexit_k,r1
|
|
773 jsr @r1
|
|
774 mov r0, r4
|
|
775
|
|
776 ! Call profiler startup code
|
|
777 mov.l monstartup_k, r0
|
|
778 mov.l start_k, r4
|
|
779 mov.l etext_k, r5
|
|
780 jsr @r0
|
|
781 nop
|
|
782
|
|
783 ! enable profiling trap
|
|
784 ! until now any trap 33s will have been ignored
|
|
785 ! This means that all library functions called before this point
|
|
786 ! (directly or indirectly) may have the profiling trap at the start.
|
|
787 ! Therefore, only mcount itself may not have the extra header.
|
|
788 mov.l profiling_enabled_k2, r0
|
|
789 mov #1, r1
|
|
790 mov.l r1, @r0
|
|
791 #endif /* PROFILE */
|
|
792
|
|
793 ! call init
|
|
794 mov.l init_k,r0
|
|
795 jsr @r0
|
|
796 nop
|
|
797
|
|
798 ! call the mainline
|
|
799 mov.l main_k,r0
|
|
800 jsr @r0
|
|
801 nop
|
|
802
|
|
803 ! call exit
|
|
804 mov r0,r4
|
|
805 mov.l exit_k,r0
|
|
806 jsr @r0
|
|
807 nop
|
|
808
|
|
809 .balign 4
|
|
810 #ifdef PROFILE
|
|
811 stop_profiling:
|
|
812 # stop mcount counting
|
|
813 mov.l profiling_enabled_k2, r0
|
|
814 mov #0, r1
|
|
815 mov.l r1, @r0
|
|
816
|
|
817 # call mcleanup
|
|
818 mov.l mcleanup_k, r0
|
|
819 jmp @r0
|
|
820 nop
|
|
821
|
|
822 .balign 4
|
|
823 mcleanup_k:
|
|
824 .long __mcleanup
|
|
825 monstartup_k:
|
|
826 .long ___monstartup
|
|
827 profiling_enabled_k2:
|
|
828 .long profiling_enabled
|
|
829 start_k:
|
|
830 .long _start
|
|
831 etext_k:
|
|
832 .long __etext
|
|
833 #endif /* PROFILE */
|
|
834
|
|
835 .align 2
|
|
836 #if defined (__SH_FPU_ANY__)
|
|
837 set_fpscr_k:
|
|
838 .long ___set_fpscr
|
|
839 #endif /* defined (__SH_FPU_ANY__) */
|
|
840
|
|
841 stack_k:
|
|
842 .long _stack
|
|
843 edata_k:
|
|
844 .long _edata
|
|
845 end_k:
|
|
846 .long _end
|
|
847 main_k:
|
|
848 .long ___setup_argv_and_call_main
|
|
849 exit_k:
|
|
850 .long _exit
|
|
851 atexit_k:
|
|
852 .long _atexit
|
|
853 init_k:
|
|
854 .long _init
|
|
855 fini_k:
|
|
856 .long _fini
|
|
857 #ifdef VBR_SETUP
|
|
858 old_vbr_k:
|
|
859 .long old_vbr
|
|
860 vbr_start_k:
|
|
861 .long vbr_start
|
|
862 #endif /* VBR_SETUP */
|
|
863
|
|
864 sr_initial_rtos:
|
|
865 ! Privileged mode RB 1 BL 0. Keep BL 0 to allow default trap handlers to work.
|
|
866 ! Whether profiling or not, keep interrupts masked,
|
|
867 ! the RTOS will enable these if required.
|
|
868 .long 0x600000f1
|
|
869
|
|
870 rtos_start_fn:
|
|
871 .long ___rtos_profiler_start_timer
|
|
872
|
|
873 #ifdef PROFILE
|
|
874 sr_initial_bare:
|
|
875 ! Privileged mode RB 1 BL 0. Keep BL 0 to allow default trap handlers to work.
|
|
876 ! For bare machine, we need to enable interrupts to get profiling working
|
|
877 .long 0x60000001
|
|
878 #else
|
|
879
|
|
880 sr_initial_bare:
|
|
881 ! Privileged mode RB 1 BL 0. Keep BL 0 to allow default trap handlers to work.
|
|
882 ! Keep interrupts disabled - the application will enable as required.
|
|
883 .long 0x600000f1
|
|
884 #endif
|
|
885
|
|
886 ! supplied for backward compatibility only, in case of linking
|
|
887 ! code whose main() was compiled with an older version of GCC.
|
|
888 .global ___main
|
|
889 ___main:
|
|
890 rts
|
|
891 nop
|
|
892 #ifdef VBR_SETUP
|
|
893 ! Exception handlers
|
|
894 .section .text.vbr, "ax"
|
|
895 vbr_start:
|
|
896
|
|
897 .org 0x100
|
|
898 vbr_100:
|
|
899 #ifdef PROFILE
|
|
900 ! Note on register usage.
|
|
901 ! we use r0..r3 as scratch in this code. If we are here due to a trapa for profiling
|
|
902 ! then this is OK as we are just before executing any function code.
|
|
903 ! The other r4..r7 we save explicityl on the stack
|
|
904 ! Remaining registers are saved by normal ABI conventions and we assert we do not
|
|
905 ! use floating point registers.
|
|
906 mov.l expevt_k1, r1
|
|
907 mov.l @r1, r1
|
|
908 mov.l event_mask, r0
|
|
909 and r0,r1
|
|
910 mov.l trapcode_k, r2
|
|
911 cmp/eq r1,r2
|
|
912 bt 1f
|
|
913 bra handler_100 ! if not a trapa, go to default handler
|
|
914 nop
|
|
915 1:
|
|
916 mov.l trapa_k, r0
|
|
917 mov.l @r0, r0
|
|
918 shlr2 r0 ! trapa code is shifted by 2.
|
|
919 cmp/eq #33, r0
|
|
920 bt 2f
|
|
921 bra handler_100
|
|
922 nop
|
|
923 2:
|
|
924
|
|
925 ! If here then it looks like we have trap #33
|
|
926 ! Now we need to call mcount with the following convention
|
|
927 ! Save and restore r4..r7
|
|
928 mov.l r4,@-r15
|
|
929 mov.l r5,@-r15
|
|
930 mov.l r6,@-r15
|
|
931 mov.l r7,@-r15
|
|
932 sts.l pr,@-r15
|
|
933
|
|
934 ! r4 is frompc.
|
|
935 ! r5 is selfpc
|
|
936 ! r0 is the branch back address.
|
|
937 ! The code sequence emitted by gcc for the profiling trap is
|
|
938 ! .align 2
|
|
939 ! trapa #33
|
|
940 ! .align 2
|
|
941 ! .long lab Where lab is planted by the compiler. This is the address
|
|
942 ! of a datum that needs to be incremented.
|
|
943 sts pr, r4 ! frompc
|
|
944 stc spc, r5 ! selfpc
|
|
945 mov #2, r2
|
|
946 not r2, r2 ! pattern to align to 4
|
|
947 and r2, r5 ! r5 now has aligned address
|
|
948 ! add #4, r5 ! r5 now has address of address
|
|
949 mov r5, r2 ! Remember it.
|
|
950 ! mov.l @r5, r5 ! r5 has value of lable (lab in above example)
|
|
951 add #8, r2
|
|
952 ldc r2, spc ! our return address avoiding address word
|
|
953
|
|
954 ! only call mcount if profiling is enabled
|
|
955 mov.l profiling_enabled_k, r0
|
|
956 mov.l @r0, r0
|
|
957 cmp/eq #0, r0
|
|
958 bt 3f
|
|
959 ! call mcount
|
|
960 mov.l mcount_k, r2
|
|
961 jsr @r2
|
|
962 nop
|
|
963 3:
|
|
964 lds.l @r15+,pr
|
|
965 mov.l @r15+,r7
|
|
966 mov.l @r15+,r6
|
|
967 mov.l @r15+,r5
|
|
968 mov.l @r15+,r4
|
|
969 rte
|
|
970 nop
|
|
971 .balign 4
|
|
972 event_mask:
|
|
973 .long 0xfff
|
|
974 trapcode_k:
|
|
975 .long 0x160
|
|
976 expevt_k1:
|
|
977 .long 0xff000024 ! Address of expevt
|
|
978 trapa_k:
|
|
979 .long 0xff000020
|
|
980 mcount_k:
|
|
981 .long __call_mcount
|
|
982 profiling_enabled_k:
|
|
983 .long profiling_enabled
|
|
984 #endif
|
|
985 ! Non profiling case.
|
|
986 handler_100:
|
|
987 mov.l 2f, r0 ! load the old vbr setting (if any)
|
|
988 mov.l @r0, r0
|
|
989 cmp/eq #0, r0
|
|
990 bf 1f
|
|
991 ! no previous vbr - jump to own generic handler
|
|
992 bra handler
|
|
993 nop
|
|
994 1: ! there was a previous handler - chain them
|
|
995 add #0x7f, r0 ! 0x7f
|
|
996 add #0x7f, r0 ! 0xfe
|
|
997 add #0x2, r0 ! add 0x100 without corrupting another register
|
|
998 jmp @r0
|
|
999 nop
|
|
1000 .balign 4
|
|
1001 2:
|
|
1002 .long old_vbr
|
|
1003
|
|
1004 .org 0x400
|
|
1005 vbr_400: ! Should be at vbr+0x400
|
|
1006 mov.l 2f, r0 ! load the old vbr setting (if any)
|
|
1007 mov.l @r0, r0
|
|
1008 cmp/eq #0, r0
|
|
1009 ! no previous vbr - jump to own generic handler
|
|
1010 bt handler
|
|
1011 ! there was a previous handler - chain them
|
|
1012 rotcr r0
|
|
1013 rotcr r0
|
|
1014 add #0x7f, r0 ! 0x1fc
|
|
1015 add #0x7f, r0 ! 0x3f8
|
|
1016 add #0x02, r0 ! 0x400
|
|
1017 rotcl r0
|
|
1018 rotcl r0 ! Add 0x400 without corrupting another register
|
|
1019 jmp @r0
|
|
1020 nop
|
|
1021 .balign 4
|
|
1022 2:
|
|
1023 .long old_vbr
|
|
1024 handler:
|
|
1025 /* If the trap handler is there call it */
|
|
1026 mov.l superh_trap_handler_k, r0
|
|
1027 cmp/eq #0, r0 ! True if zero.
|
|
1028 bf 3f
|
|
1029 bra chandler
|
|
1030 nop
|
|
1031 3:
|
|
1032 ! Here handler available, call it.
|
|
1033 /* Now call the trap handler with as much of the context unchanged as possible.
|
|
1034 Move trapping address into PR to make it look like the trap point */
|
|
1035 stc spc, r1
|
|
1036 lds r1, pr
|
|
1037 mov.l expevt_k, r4
|
|
1038 mov.l @r4, r4 ! r4 is value of expevt, first parameter.
|
|
1039 mov r1, r5 ! Remember trapping pc.
|
|
1040 mov r1, r6 ! Remember trapping pc.
|
|
1041 mov.l chandler_k, r1
|
|
1042 mov.l superh_trap_handler_k, r2
|
|
1043 ! jmp to trap handler to avoid disturbing pr.
|
|
1044 jmp @r2
|
|
1045 nop
|
|
1046
|
|
1047 .org 0x600
|
|
1048 vbr_600:
|
|
1049 #ifdef PROFILE
|
|
1050 ! Should be at vbr+0x600
|
|
1051 ! Now we are in the land of interrupts so need to save more state.
|
|
1052 ! Save register state
|
|
1053 mov.l interrupt_stack_k, r15 ! r15 has been saved to sgr.
|
|
1054 mov.l r0,@-r15
|
|
1055 mov.l r1,@-r15
|
|
1056 mov.l r2,@-r15
|
|
1057 mov.l r3,@-r15
|
|
1058 mov.l r4,@-r15
|
|
1059 mov.l r5,@-r15
|
|
1060 mov.l r6,@-r15
|
|
1061 mov.l r7,@-r15
|
|
1062 sts.l pr,@-r15
|
|
1063 sts.l mach,@-r15
|
|
1064 sts.l macl,@-r15
|
|
1065 #if defined(__SH_FPU_ANY__)
|
|
1066 ! Save fpul and fpscr, save fr0-fr7 in 64 bit mode
|
|
1067 ! and set the pervading precision for the timer_handler
|
|
1068 mov #0,r0
|
|
1069 sts.l fpul,@-r15
|
|
1070 sts.l fpscr,@-r15
|
|
1071 lds r0,fpscr ! Clear fpscr
|
|
1072 fmov fr0,@-r15
|
|
1073 fmov fr1,@-r15
|
|
1074 fmov fr2,@-r15
|
|
1075 fmov fr3,@-r15
|
|
1076 mov.l pervading_precision_k,r0
|
|
1077 fmov fr4,@-r15
|
|
1078 fmov fr5,@-r15
|
|
1079 mov.l @r0,r0
|
|
1080 fmov fr6,@-r15
|
|
1081 fmov fr7,@-r15
|
|
1082 lds r0,fpscr
|
|
1083 #endif /* __SH_FPU_ANY__ */
|
|
1084 ! Pass interrupted pc to timer_handler as first parameter (r4).
|
|
1085 stc spc, r4
|
|
1086 mov.l timer_handler_k, r0
|
|
1087 jsr @r0
|
|
1088 nop
|
|
1089 #if defined(__SH_FPU_ANY__)
|
|
1090 mov #0,r0
|
|
1091 lds r0,fpscr ! Clear the fpscr
|
|
1092 fmov @r15+,fr7
|
|
1093 fmov @r15+,fr6
|
|
1094 fmov @r15+,fr5
|
|
1095 fmov @r15+,fr4
|
|
1096 fmov @r15+,fr3
|
|
1097 fmov @r15+,fr2
|
|
1098 fmov @r15+,fr1
|
|
1099 fmov @r15+,fr0
|
|
1100 lds.l @r15+,fpscr
|
|
1101 lds.l @r15+,fpul
|
|
1102 #endif /* __SH_FPU_ANY__ */
|
|
1103 lds.l @r15+,macl
|
|
1104 lds.l @r15+,mach
|
|
1105 lds.l @r15+,pr
|
|
1106 mov.l @r15+,r7
|
|
1107 mov.l @r15+,r6
|
|
1108 mov.l @r15+,r5
|
|
1109 mov.l @r15+,r4
|
|
1110 mov.l @r15+,r3
|
|
1111 mov.l @r15+,r2
|
|
1112 mov.l @r15+,r1
|
|
1113 mov.l @r15+,r0
|
|
1114 stc sgr, r15 ! Restore r15, destroyed by this sequence.
|
|
1115 rte
|
|
1116 nop
|
|
1117 #if defined(__SH_FPU_ANY__)
|
|
1118 .balign 4
|
|
1119 pervading_precision_k:
|
|
1120 #define CONCAT1(A,B) A##B
|
|
1121 #define CONCAT(A,B) CONCAT1(A,B)
|
|
1122 .long CONCAT(__USER_LABEL_PREFIX__,__fpscr_values)+4
|
|
1123 #endif
|
|
1124 #else
|
|
1125 mov.l 2f, r0 ! Load the old vbr setting (if any).
|
|
1126 mov.l @r0, r0
|
|
1127 cmp/eq #0, r0
|
|
1128 ! no previous vbr - jump to own handler
|
|
1129 bt chandler
|
|
1130 ! there was a previous handler - chain them
|
|
1131 rotcr r0
|
|
1132 rotcr r0
|
|
1133 add #0x7f, r0 ! 0x1fc
|
|
1134 add #0x7f, r0 ! 0x3f8
|
|
1135 add #0x7f, r0 ! 0x5f4
|
|
1136 add #0x03, r0 ! 0x600
|
|
1137 rotcl r0
|
|
1138 rotcl r0 ! Add 0x600 without corrupting another register
|
|
1139 jmp @r0
|
|
1140 nop
|
|
1141 .balign 4
|
|
1142 2:
|
|
1143 .long old_vbr
|
|
1144 #endif /* PROFILE code */
|
|
1145 chandler:
|
|
1146 mov.l expevt_k, r4
|
|
1147 mov.l @r4, r4 ! r4 is value of expevt hence making this the return code
|
|
1148 mov.l handler_exit_k,r0
|
|
1149 jsr @r0
|
|
1150 nop
|
|
1151 ! We should never return from _exit but in case we do we would enter the
|
|
1152 ! the following tight loop
|
|
1153 limbo:
|
|
1154 bra limbo
|
|
1155 nop
|
|
1156 .balign 4
|
|
1157 #ifdef PROFILE
|
|
1158 interrupt_stack_k:
|
|
1159 .long __timer_stack ! The high end of the stack
|
|
1160 timer_handler_k:
|
|
1161 .long __profil_counter
|
|
1162 #endif
|
|
1163 expevt_k:
|
|
1164 .long 0xff000024 ! Address of expevt
|
|
1165 chandler_k:
|
|
1166 .long chandler
|
|
1167 superh_trap_handler_k:
|
|
1168 .long __superh_trap_handler
|
|
1169 handler_exit_k:
|
|
1170 .long _exit
|
|
1171 .align 2
|
|
1172 ! Simulated compile of trap handler.
|
|
1173 .section .debug_abbrev,"",@progbits
|
|
1174 .Ldebug_abbrev0:
|
|
1175 .section .debug_info,"",@progbits
|
|
1176 .Ldebug_info0:
|
|
1177 .section .debug_line,"",@progbits
|
|
1178 .Ldebug_line0:
|
|
1179 .text
|
|
1180 .Ltext0:
|
|
1181 .align 5
|
|
1182 .type __superh_trap_handler,@function
|
|
1183 __superh_trap_handler:
|
|
1184 .LFB1:
|
|
1185 mov.l r14,@-r15
|
|
1186 .LCFI0:
|
|
1187 add #-4,r15
|
|
1188 .LCFI1:
|
|
1189 mov r15,r14
|
|
1190 .LCFI2:
|
|
1191 mov.l r4,@r14
|
|
1192 lds r1, pr
|
|
1193 add #4,r14
|
|
1194 mov r14,r15
|
|
1195 mov.l @r15+,r14
|
|
1196 rts
|
|
1197 nop
|
|
1198 .LFE1:
|
|
1199 .Lfe1:
|
|
1200 .size __superh_trap_handler,.Lfe1-__superh_trap_handler
|
|
1201 .section .debug_frame,"",@progbits
|
|
1202 .Lframe0:
|
|
1203 .ualong .LECIE0-.LSCIE0
|
|
1204 .LSCIE0:
|
|
1205 .ualong 0xffffffff
|
|
1206 .byte 0x1
|
|
1207 .string ""
|
|
1208 .uleb128 0x1
|
|
1209 .sleb128 -4
|
|
1210 .byte 0x11
|
|
1211 .byte 0xc
|
|
1212 .uleb128 0xf
|
|
1213 .uleb128 0x0
|
|
1214 .align 2
|
|
1215 .LECIE0:
|
|
1216 .LSFDE0:
|
|
1217 .ualong .LEFDE0-.LASFDE0
|
|
1218 .LASFDE0:
|
|
1219 .ualong .Lframe0
|
|
1220 .ualong .LFB1
|
|
1221 .ualong .LFE1-.LFB1
|
|
1222 .byte 0x4
|
|
1223 .ualong .LCFI0-.LFB1
|
|
1224 .byte 0xe
|
|
1225 .uleb128 0x4
|
|
1226 .byte 0x4
|
|
1227 .ualong .LCFI1-.LCFI0
|
|
1228 .byte 0xe
|
|
1229 .uleb128 0x8
|
|
1230 .byte 0x8e
|
|
1231 .uleb128 0x1
|
|
1232 .byte 0x4
|
|
1233 .ualong .LCFI2-.LCFI1
|
|
1234 .byte 0xd
|
|
1235 .uleb128 0xe
|
|
1236 .align 2
|
|
1237 .LEFDE0:
|
|
1238 .text
|
|
1239 .Letext0:
|
|
1240 .section .debug_info
|
|
1241 .ualong 0xb3
|
|
1242 .uaword 0x2
|
|
1243 .ualong .Ldebug_abbrev0
|
|
1244 .byte 0x4
|
|
1245 .uleb128 0x1
|
|
1246 .ualong .Ldebug_line0
|
|
1247 .ualong .Letext0
|
|
1248 .ualong .Ltext0
|
|
1249 .string "trap_handler.c"
|
|
1250 .string "xxxxxxxxxxxxxxxxxxxxxxxxxxxx"
|
|
1251 .string "GNU C 3.2 20020529 (experimental)"
|
|
1252 .byte 0x1
|
|
1253 .uleb128 0x2
|
|
1254 .ualong 0xa6
|
|
1255 .byte 0x1
|
|
1256 .string "_superh_trap_handler"
|
|
1257 .byte 0x1
|
|
1258 .byte 0x2
|
|
1259 .byte 0x1
|
|
1260 .ualong .LFB1
|
|
1261 .ualong .LFE1
|
|
1262 .byte 0x1
|
|
1263 .byte 0x5e
|
|
1264 .uleb128 0x3
|
|
1265 .string "trap_reason"
|
|
1266 .byte 0x1
|
|
1267 .byte 0x1
|
|
1268 .ualong 0xa6
|
|
1269 .byte 0x2
|
|
1270 .byte 0x91
|
|
1271 .sleb128 0
|
|
1272 .byte 0x0
|
|
1273 .uleb128 0x4
|
|
1274 .string "unsigned int"
|
|
1275 .byte 0x4
|
|
1276 .byte 0x7
|
|
1277 .byte 0x0
|
|
1278 .section .debug_abbrev
|
|
1279 .uleb128 0x1
|
|
1280 .uleb128 0x11
|
|
1281 .byte 0x1
|
|
1282 .uleb128 0x10
|
|
1283 .uleb128 0x6
|
|
1284 .uleb128 0x12
|
|
1285 .uleb128 0x1
|
|
1286 .uleb128 0x11
|
|
1287 .uleb128 0x1
|
|
1288 .uleb128 0x3
|
|
1289 .uleb128 0x8
|
|
1290 .uleb128 0x1b
|
|
1291 .uleb128 0x8
|
|
1292 .uleb128 0x25
|
|
1293 .uleb128 0x8
|
|
1294 .uleb128 0x13
|
|
1295 .uleb128 0xb
|
|
1296 .byte 0x0
|
|
1297 .byte 0x0
|
|
1298 .uleb128 0x2
|
|
1299 .uleb128 0x2e
|
|
1300 .byte 0x1
|
|
1301 .uleb128 0x1
|
|
1302 .uleb128 0x13
|
|
1303 .uleb128 0x3f
|
|
1304 .uleb128 0xc
|
|
1305 .uleb128 0x3
|
|
1306 .uleb128 0x8
|
|
1307 .uleb128 0x3a
|
|
1308 .uleb128 0xb
|
|
1309 .uleb128 0x3b
|
|
1310 .uleb128 0xb
|
|
1311 .uleb128 0x27
|
|
1312 .uleb128 0xc
|
|
1313 .uleb128 0x11
|
|
1314 .uleb128 0x1
|
|
1315 .uleb128 0x12
|
|
1316 .uleb128 0x1
|
|
1317 .uleb128 0x40
|
|
1318 .uleb128 0xa
|
|
1319 .byte 0x0
|
|
1320 .byte 0x0
|
|
1321 .uleb128 0x3
|
|
1322 .uleb128 0x5
|
|
1323 .byte 0x0
|
|
1324 .uleb128 0x3
|
|
1325 .uleb128 0x8
|
|
1326 .uleb128 0x3a
|
|
1327 .uleb128 0xb
|
|
1328 .uleb128 0x3b
|
|
1329 .uleb128 0xb
|
|
1330 .uleb128 0x49
|
|
1331 .uleb128 0x13
|
|
1332 .uleb128 0x2
|
|
1333 .uleb128 0xa
|
|
1334 .byte 0x0
|
|
1335 .byte 0x0
|
|
1336 .uleb128 0x4
|
|
1337 .uleb128 0x24
|
|
1338 .byte 0x0
|
|
1339 .uleb128 0x3
|
|
1340 .uleb128 0x8
|
|
1341 .uleb128 0xb
|
|
1342 .uleb128 0xb
|
|
1343 .uleb128 0x3e
|
|
1344 .uleb128 0xb
|
|
1345 .byte 0x0
|
|
1346 .byte 0x0
|
|
1347 .byte 0x0
|
|
1348 .section .debug_pubnames,"",@progbits
|
|
1349 .ualong 0x27
|
|
1350 .uaword 0x2
|
|
1351 .ualong .Ldebug_info0
|
|
1352 .ualong 0xb7
|
|
1353 .ualong 0x67
|
|
1354 .string "_superh_trap_handler"
|
|
1355 .ualong 0x0
|
|
1356 .section .debug_aranges,"",@progbits
|
|
1357 .ualong 0x1c
|
|
1358 .uaword 0x2
|
|
1359 .ualong .Ldebug_info0
|
|
1360 .byte 0x4
|
|
1361 .byte 0x0
|
|
1362 .uaword 0x0
|
|
1363 .uaword 0x0
|
|
1364 .ualong .Ltext0
|
|
1365 .ualong .Letext0-.Ltext0
|
|
1366 .ualong 0x0
|
|
1367 .ualong 0x0
|
|
1368 #endif /* VBR_SETUP */
|
|
1369 #endif /* ! __SH5__ */
|