Linux Audio

Check our new training course

Yocto / OpenEmbedded training

Mar 24-27, 2025, special US time zones
Register
Loading...
v4.17
 
  1/*
  2 * Copyright (C) Paul Mackerras 1997.
  3 *
  4 * Adapted for 64 bit LE PowerPC by Andrew Tauferner
  5 *
  6 * This program is free software; you can redistribute it and/or
  7 * modify it under the terms of the GNU General Public License
  8 * as published by the Free Software Foundation; either version
  9 * 2 of the License, or (at your option) any later version.
 10 *
 11 */
 12
 13#include "ppc_asm.h"
 14
 15RELA = 7
 16RELACOUNT = 0x6ffffff9
 17
 18	.text
 19	/* A procedure descriptor used when booting this as a COFF file.
 20	 * When making COFF, this comes first in the link and we're
 21	 * linked at 0x500000.
 22	 */
 23	.globl	_zimage_start_opd
 24_zimage_start_opd:
 25	.long	0x500000, 0, 0, 0
 
 
 26
 27#ifdef __powerpc64__
 28.balign 8
 29p_start:	.8byte	_start
 30p_etext:	.8byte	_etext
 31p_bss_start:	.8byte	__bss_start
 32p_end:		.8byte	_end
 33
 34p_toc:		.8byte	__toc_start + 0x8000 - p_base
 35p_dyn:		.8byte	__dynamic_start - p_base
 36p_rela:		.8byte	__rela_dyn_start - p_base
 37p_prom:		.8byte	0
 38	.weak	_platform_stack_top
 39p_pstack:	.8byte	_platform_stack_top
 40#else
 41p_start:	.long	_start
 42p_etext:	.long	_etext
 43p_bss_start:	.long	__bss_start
 44p_end:		.long	_end
 45
 46	.weak	_platform_stack_top
 47p_pstack:	.long	_platform_stack_top
 48#endif
 49
 50	.weak	_zimage_start
 51	.globl	_zimage_start
 
 
 
 52_zimage_start:
 53	.globl	_zimage_start_lib
 54_zimage_start_lib:
 55	/* Work out the offset between the address we were linked at
 56	   and the address where we're running. */
 57	bl	.+4
 58p_base:	mflr	r10		/* r10 now points to runtime addr of p_base */
 59#ifndef __powerpc64__
 60	/* grab the link address of the dynamic section in r11 */
 61	addis	r11,r10,(_GLOBAL_OFFSET_TABLE_-p_base)@ha
 62	lwz	r11,(_GLOBAL_OFFSET_TABLE_-p_base)@l(r11)
 63	cmpwi	r11,0
 64	beq	3f		/* if not linked -pie */
 65	/* get the runtime address of the dynamic section in r12 */
 66	.weak	__dynamic_start
 67	addis	r12,r10,(__dynamic_start-p_base)@ha
 68	addi	r12,r12,(__dynamic_start-p_base)@l
 69	subf	r11,r11,r12	/* runtime - linktime offset */
 70
 71	/* The dynamic section contains a series of tagged entries.
 72	 * We need the RELA and RELACOUNT entries. */
 73	li	r9,0
 74	li	r0,0
 759:	lwz	r8,0(r12)	/* get tag */
 76	cmpwi	r8,0
 77	beq	10f		/* end of list */
 78	cmpwi	r8,RELA
 79	bne	11f
 80	lwz	r9,4(r12)	/* get RELA pointer in r9 */
 81	b	12f
 8211:	addis	r8,r8,(-RELACOUNT)@ha
 83	cmpwi	r8,RELACOUNT@l
 84	bne	12f
 85	lwz	r0,4(r12)	/* get RELACOUNT value in r0 */
 8612:	addi	r12,r12,8
 87	b	9b
 88
 89	/* The relocation section contains a list of relocations.
 90	 * We now do the R_PPC_RELATIVE ones, which point to words
 91	 * which need to be initialized with addend + offset.
 92	 * The R_PPC_RELATIVE ones come first and there are RELACOUNT
 93	 * of them. */
 9410:	/* skip relocation if we don't have both */
 95	cmpwi	r0,0
 96	beq	3f
 97	cmpwi	r9,0
 98	beq	3f
 99
100	add	r9,r9,r11	/* Relocate RELA pointer */
101	mtctr	r0
1022:	lbz	r0,4+3(r9)	/* ELF32_R_INFO(reloc->r_info) */
103	cmpwi	r0,22		/* R_PPC_RELATIVE */
104	bne	3f
105	lwz	r12,0(r9)	/* reloc->r_offset */
106	lwz	r0,8(r9)	/* reloc->r_addend */
107	add	r0,r0,r11
108	stwx	r0,r11,r12
109	addi	r9,r9,12
110	bdnz	2b
111
112	/* Do a cache flush for our text, in case the loader didn't */
1133:	lwz	r9,p_start-p_base(r10)	/* note: these are relocated now */
114	lwz	r8,p_etext-p_base(r10)
1154:	dcbf	r0,r9
116	icbi	r0,r9
117	addi	r9,r9,0x20
118	cmplw	cr0,r9,r8
119	blt	4b
120	sync
121	isync
122
123	/* Clear the BSS */
124	lwz	r9,p_bss_start-p_base(r10)
125	lwz	r8,p_end-p_base(r10)
126	li	r0,0
1275:	stw	r0,0(r9)
128	addi	r9,r9,4
129	cmplw	cr0,r9,r8
130	blt	5b
131
132	/* Possibly set up a custom stack */
133	lwz	r8,p_pstack-p_base(r10)
134	cmpwi	r8,0
135	beq	6f
136	lwz	r1,0(r8)
137	li	r0,0
138	stwu	r0,-16(r1)	/* establish a stack frame */
1396:
140#else /* __powerpc64__ */
141	/* Save the prom pointer at p_prom. */
142	std	r5,(p_prom-p_base)(r10)
143
144	/* Set r2 to the TOC. */
145	ld	r2,(p_toc-p_base)(r10)
146	add	r2,r2,r10
147
148	/* Grab the link address of the dynamic section in r11. */
149	ld	r11,-32768(r2)
150	cmpwi	r11,0
151	beq	3f              /* if not linked -pie then no dynamic section */
152
153	ld	r11,(p_dyn-p_base)(r10)
154	add	r11,r11,r10
155	ld	r9,(p_rela-p_base)(r10)
156	add	r9,r9,r10
157
158	li	r13,0
159	li	r8,0
1609:	ld	r12,0(r11)       /* get tag */
161	cmpdi	r12,0
162	beq	12f              /* end of list */
163	cmpdi	r12,RELA
164	bne	10f
165	ld	r13,8(r11)       /* get RELA pointer in r13 */
166	b	11f
16710:	addis	r12,r12,(-RELACOUNT)@ha
168	cmpdi	r12,RELACOUNT@l
169	bne	11f
170	ld	r8,8(r11)       /* get RELACOUNT value in r8 */
17111:	addi	r11,r11,16
172	b	9b
17312:
174	cmpdi	r13,0            /* check we have both RELA and RELACOUNT */
175	cmpdi	cr1,r8,0
176	beq	3f
177	beq	cr1,3f
178
179	/* Calcuate the runtime offset. */
180	subf	r13,r13,r9
181
182	/* Run through the list of relocations and process the
183	 * R_PPC64_RELATIVE ones. */
184	mtctr	r8
18513:	ld	r0,8(r9)        /* ELF64_R_TYPE(reloc->r_info) */
186	cmpdi	r0,22           /* R_PPC64_RELATIVE */
187	bne	3f
188	ld	r12,0(r9)        /* reloc->r_offset */
189	ld	r0,16(r9)       /* reloc->r_addend */
190	add	r0,r0,r13
191	stdx	r0,r13,r12
192	addi	r9,r9,24
193	bdnz	13b
194
195	/* Do a cache flush for our text, in case the loader didn't */
1963:	ld	r9,p_start-p_base(r10)	/* note: these are relocated now */
197	ld	r8,p_etext-p_base(r10)
1984:	dcbf	r0,r9
199	icbi	r0,r9
200	addi	r9,r9,0x20
201	cmpld	cr0,r9,r8
202	blt	4b
203	sync
204	isync
205
206	/* Clear the BSS */
207	ld	r9,p_bss_start-p_base(r10)
208	ld	r8,p_end-p_base(r10)
209	li	r0,0
2105:	std	r0,0(r9)
211	addi	r9,r9,8
212	cmpld	cr0,r9,r8
213	blt	5b
214
215	/* Possibly set up a custom stack */
216	ld	r8,p_pstack-p_base(r10)
217	cmpdi	r8,0
218	beq	6f
219	ld	r1,0(r8)
220	li	r0,0
221	stdu	r0,-112(r1)	/* establish a stack frame */
2226:
223#endif  /* __powerpc64__ */
224	/* Call platform_init() */
225	bl	platform_init
226
227	/* Call start */
228	b	start
229
230#ifdef __powerpc64__
231
232#define PROM_FRAME_SIZE 512
233#define SAVE_GPR(n, base)       std     n,8*(n)(base)
234#define REST_GPR(n, base)       ld      n,8*(n)(base)
235#define SAVE_2GPRS(n, base)     SAVE_GPR(n, base); SAVE_GPR(n+1, base)
236#define SAVE_4GPRS(n, base)     SAVE_2GPRS(n, base); SAVE_2GPRS(n+2, base)
237#define SAVE_8GPRS(n, base)     SAVE_4GPRS(n, base); SAVE_4GPRS(n+4, base)
238#define SAVE_10GPRS(n, base)    SAVE_8GPRS(n, base); SAVE_2GPRS(n+8, base)
239#define REST_2GPRS(n, base)     REST_GPR(n, base); REST_GPR(n+1, base)
240#define REST_4GPRS(n, base)     REST_2GPRS(n, base); REST_2GPRS(n+2, base)
241#define REST_8GPRS(n, base)     REST_4GPRS(n, base); REST_4GPRS(n+4, base)
242#define REST_10GPRS(n, base)    REST_8GPRS(n, base); REST_2GPRS(n+8, base)
243
244/* prom handles the jump into and return from firmware.  The prom args pointer
245   is loaded in r3. */
246.globl prom
247prom:
248	mflr	r0
249	std	r0,16(r1)
250	stdu	r1,-PROM_FRAME_SIZE(r1) /* Save SP and create stack space */
251
252	SAVE_GPR(2, r1)
253	SAVE_GPR(13, r1)
254	SAVE_8GPRS(14, r1)
255	SAVE_10GPRS(22, r1)
256	mfcr    r10
257	std     r10,8*32(r1)
258	mfmsr   r10
259	std     r10,8*33(r1)
260
261	/* remove MSR_LE from msr but keep MSR_SF */
262	mfmsr	r10
263	rldicr	r10,r10,0,62
264	mtsrr1	r10
265
266	/* Load FW address, set LR to label 1, and jump to FW */
267	bl	0f
2680:	mflr	r10
269	addi	r11,r10,(1f-0b)
270	mtlr	r11
271
272	ld	r10,(p_prom-0b)(r10)
273	mtsrr0	r10
274
275	rfid
276
2771:	/* Return from OF */
278	FIXUP_ENDIAN
279
280	/* Restore registers and return. */
281	rldicl  r1,r1,0,32
282
283	/* Restore the MSR (back to 64 bits) */
284	ld      r10,8*(33)(r1)
285	mtmsr	r10
286	isync
287
288	/* Restore other registers */
289	REST_GPR(2, r1)
290	REST_GPR(13, r1)
291	REST_8GPRS(14, r1)
292	REST_10GPRS(22, r1)
293	ld      r10,8*32(r1)
294	mtcr	r10
295
296	addi    r1,r1,PROM_FRAME_SIZE
297	ld      r0,16(r1)
298	mtlr    r0
299	blr
300#endif
v5.4
  1/* SPDX-License-Identifier: GPL-2.0-or-later */
  2/*
  3 * Copyright (C) Paul Mackerras 1997.
  4 *
  5 * Adapted for 64 bit LE PowerPC by Andrew Tauferner
 
 
 
 
 
 
  6 */
  7
  8#include "ppc_asm.h"
  9
 10RELA = 7
 11RELACOUNT = 0x6ffffff9
 12
 13	.data
 14	/* A procedure descriptor used when booting this as a COFF file.
 15	 * When making COFF, this comes first in the link and we're
 16	 * linked at 0x500000.
 17	 */
 18	.globl	_zimage_start_opd
 19_zimage_start_opd:
 20	.long	0x500000, 0, 0, 0
 21	.text
 22	b	_zimage_start
 23
 24#ifdef __powerpc64__
 25.balign 8
 26p_start:	.8byte	_start
 27p_etext:	.8byte	_etext
 28p_bss_start:	.8byte	__bss_start
 29p_end:		.8byte	_end
 30
 31p_toc:		.8byte	__toc_start + 0x8000 - p_base
 32p_dyn:		.8byte	__dynamic_start - p_base
 33p_rela:		.8byte	__rela_dyn_start - p_base
 34p_prom:		.8byte	0
 35	.weak	_platform_stack_top
 36p_pstack:	.8byte	_platform_stack_top
 37#else
 38p_start:	.long	_start
 39p_etext:	.long	_etext
 40p_bss_start:	.long	__bss_start
 41p_end:		.long	_end
 42
 43	.weak	_platform_stack_top
 44p_pstack:	.long	_platform_stack_top
 45#endif
 46
 
 47	.globl	_zimage_start
 48	/* Clang appears to require the .weak directive to be after the symbol
 49	 * is defined. See https://bugs.llvm.org/show_bug.cgi?id=38921  */
 50	.weak	_zimage_start
 51_zimage_start:
 52	.globl	_zimage_start_lib
 53_zimage_start_lib:
 54	/* Work out the offset between the address we were linked at
 55	   and the address where we're running. */
 56	bl	.+4
 57p_base:	mflr	r10		/* r10 now points to runtime addr of p_base */
 58#ifndef __powerpc64__
 59	/* grab the link address of the dynamic section in r11 */
 60	addis	r11,r10,(_GLOBAL_OFFSET_TABLE_-p_base)@ha
 61	lwz	r11,(_GLOBAL_OFFSET_TABLE_-p_base)@l(r11)
 62	cmpwi	r11,0
 63	beq	3f		/* if not linked -pie */
 64	/* get the runtime address of the dynamic section in r12 */
 65	.weak	__dynamic_start
 66	addis	r12,r10,(__dynamic_start-p_base)@ha
 67	addi	r12,r12,(__dynamic_start-p_base)@l
 68	subf	r11,r11,r12	/* runtime - linktime offset */
 69
 70	/* The dynamic section contains a series of tagged entries.
 71	 * We need the RELA and RELACOUNT entries. */
 72	li	r9,0
 73	li	r0,0
 749:	lwz	r8,0(r12)	/* get tag */
 75	cmpwi	r8,0
 76	beq	10f		/* end of list */
 77	cmpwi	r8,RELA
 78	bne	11f
 79	lwz	r9,4(r12)	/* get RELA pointer in r9 */
 80	b	12f
 8111:	addis	r8,r8,(-RELACOUNT)@ha
 82	cmpwi	r8,RELACOUNT@l
 83	bne	12f
 84	lwz	r0,4(r12)	/* get RELACOUNT value in r0 */
 8512:	addi	r12,r12,8
 86	b	9b
 87
 88	/* The relocation section contains a list of relocations.
 89	 * We now do the R_PPC_RELATIVE ones, which point to words
 90	 * which need to be initialized with addend + offset.
 91	 * The R_PPC_RELATIVE ones come first and there are RELACOUNT
 92	 * of them. */
 9310:	/* skip relocation if we don't have both */
 94	cmpwi	r0,0
 95	beq	3f
 96	cmpwi	r9,0
 97	beq	3f
 98
 99	add	r9,r9,r11	/* Relocate RELA pointer */
100	mtctr	r0
1012:	lbz	r0,4+3(r9)	/* ELF32_R_INFO(reloc->r_info) */
102	cmpwi	r0,22		/* R_PPC_RELATIVE */
103	bne	3f
104	lwz	r12,0(r9)	/* reloc->r_offset */
105	lwz	r0,8(r9)	/* reloc->r_addend */
106	add	r0,r0,r11
107	stwx	r0,r11,r12
108	addi	r9,r9,12
109	bdnz	2b
110
111	/* Do a cache flush for our text, in case the loader didn't */
1123:	lwz	r9,p_start-p_base(r10)	/* note: these are relocated now */
113	lwz	r8,p_etext-p_base(r10)
1144:	dcbf	r0,r9
115	icbi	r0,r9
116	addi	r9,r9,0x20
117	cmplw	cr0,r9,r8
118	blt	4b
119	sync
120	isync
121
122	/* Clear the BSS */
123	lwz	r9,p_bss_start-p_base(r10)
124	lwz	r8,p_end-p_base(r10)
125	li	r0,0
1265:	stw	r0,0(r9)
127	addi	r9,r9,4
128	cmplw	cr0,r9,r8
129	blt	5b
130
131	/* Possibly set up a custom stack */
132	lwz	r8,p_pstack-p_base(r10)
133	cmpwi	r8,0
134	beq	6f
135	lwz	r1,0(r8)
136	li	r0,0
137	stwu	r0,-16(r1)	/* establish a stack frame */
1386:
139#else /* __powerpc64__ */
140	/* Save the prom pointer at p_prom. */
141	std	r5,(p_prom-p_base)(r10)
142
143	/* Set r2 to the TOC. */
144	ld	r2,(p_toc-p_base)(r10)
145	add	r2,r2,r10
146
147	/* Grab the link address of the dynamic section in r11. */
148	ld	r11,-32768(r2)
149	cmpwi	r11,0
150	beq	3f              /* if not linked -pie then no dynamic section */
151
152	ld	r11,(p_dyn-p_base)(r10)
153	add	r11,r11,r10
154	ld	r9,(p_rela-p_base)(r10)
155	add	r9,r9,r10
156
157	li	r13,0
158	li	r8,0
1599:	ld	r12,0(r11)       /* get tag */
160	cmpdi	r12,0
161	beq	12f              /* end of list */
162	cmpdi	r12,RELA
163	bne	10f
164	ld	r13,8(r11)       /* get RELA pointer in r13 */
165	b	11f
16610:	addis	r12,r12,(-RELACOUNT)@ha
167	cmpdi	r12,RELACOUNT@l
168	bne	11f
169	ld	r8,8(r11)       /* get RELACOUNT value in r8 */
17011:	addi	r11,r11,16
171	b	9b
17212:
173	cmpdi	r13,0            /* check we have both RELA and RELACOUNT */
174	cmpdi	cr1,r8,0
175	beq	3f
176	beq	cr1,3f
177
178	/* Calcuate the runtime offset. */
179	subf	r13,r13,r9
180
181	/* Run through the list of relocations and process the
182	 * R_PPC64_RELATIVE ones. */
183	mtctr	r8
18413:	ld	r0,8(r9)        /* ELF64_R_TYPE(reloc->r_info) */
185	cmpdi	r0,22           /* R_PPC64_RELATIVE */
186	bne	3f
187	ld	r12,0(r9)        /* reloc->r_offset */
188	ld	r0,16(r9)       /* reloc->r_addend */
189	add	r0,r0,r13
190	stdx	r0,r13,r12
191	addi	r9,r9,24
192	bdnz	13b
193
194	/* Do a cache flush for our text, in case the loader didn't */
1953:	ld	r9,p_start-p_base(r10)	/* note: these are relocated now */
196	ld	r8,p_etext-p_base(r10)
1974:	dcbf	r0,r9
198	icbi	r0,r9
199	addi	r9,r9,0x20
200	cmpld	cr0,r9,r8
201	blt	4b
202	sync
203	isync
204
205	/* Clear the BSS */
206	ld	r9,p_bss_start-p_base(r10)
207	ld	r8,p_end-p_base(r10)
208	li	r0,0
2095:	std	r0,0(r9)
210	addi	r9,r9,8
211	cmpld	cr0,r9,r8
212	blt	5b
213
214	/* Possibly set up a custom stack */
215	ld	r8,p_pstack-p_base(r10)
216	cmpdi	r8,0
217	beq	6f
218	ld	r1,0(r8)
219	li	r0,0
220	stdu	r0,-112(r1)	/* establish a stack frame */
2216:
222#endif  /* __powerpc64__ */
223	/* Call platform_init() */
224	bl	platform_init
225
226	/* Call start */
227	b	start
228
229#ifdef __powerpc64__
230
231#define PROM_FRAME_SIZE 512
232#define SAVE_GPR(n, base)       std     n,8*(n)(base)
233#define REST_GPR(n, base)       ld      n,8*(n)(base)
234#define SAVE_2GPRS(n, base)     SAVE_GPR(n, base); SAVE_GPR(n+1, base)
235#define SAVE_4GPRS(n, base)     SAVE_2GPRS(n, base); SAVE_2GPRS(n+2, base)
236#define SAVE_8GPRS(n, base)     SAVE_4GPRS(n, base); SAVE_4GPRS(n+4, base)
237#define SAVE_10GPRS(n, base)    SAVE_8GPRS(n, base); SAVE_2GPRS(n+8, base)
238#define REST_2GPRS(n, base)     REST_GPR(n, base); REST_GPR(n+1, base)
239#define REST_4GPRS(n, base)     REST_2GPRS(n, base); REST_2GPRS(n+2, base)
240#define REST_8GPRS(n, base)     REST_4GPRS(n, base); REST_4GPRS(n+4, base)
241#define REST_10GPRS(n, base)    REST_8GPRS(n, base); REST_2GPRS(n+8, base)
242
243/* prom handles the jump into and return from firmware.  The prom args pointer
244   is loaded in r3. */
245.globl prom
246prom:
247	mflr	r0
248	std	r0,16(r1)
249	stdu	r1,-PROM_FRAME_SIZE(r1) /* Save SP and create stack space */
250
251	SAVE_GPR(2, r1)
252	SAVE_GPR(13, r1)
253	SAVE_8GPRS(14, r1)
254	SAVE_10GPRS(22, r1)
255	mfcr    r10
256	std     r10,8*32(r1)
257	mfmsr   r10
258	std     r10,8*33(r1)
259
260	/* remove MSR_LE from msr but keep MSR_SF */
261	mfmsr	r10
262	rldicr	r10,r10,0,62
263	mtsrr1	r10
264
265	/* Load FW address, set LR to label 1, and jump to FW */
266	bl	0f
2670:	mflr	r10
268	addi	r11,r10,(1f-0b)
269	mtlr	r11
270
271	ld	r10,(p_prom-0b)(r10)
272	mtsrr0	r10
273
274	rfid
275
2761:	/* Return from OF */
277	FIXUP_ENDIAN
278
279	/* Restore registers and return. */
280	rldicl  r1,r1,0,32
281
282	/* Restore the MSR (back to 64 bits) */
283	ld      r10,8*(33)(r1)
284	mtmsr	r10
285	isync
286
287	/* Restore other registers */
288	REST_GPR(2, r1)
289	REST_GPR(13, r1)
290	REST_8GPRS(14, r1)
291	REST_10GPRS(22, r1)
292	ld      r10,8*32(r1)
293	mtcr	r10
294
295	addi    r1,r1,PROM_FRAME_SIZE
296	ld      r0,16(r1)
297	mtlr    r0
298	blr
299#endif