1/*	$NetBSD: asm.h,v 1.53 2022/01/07 22:59:32 andvar Exp $	*/
  2
  3/*
  4 * Copyright (C) 1995, 1996 Wolfgang Solfrank.
  5 * Copyright (C) 1995, 1996 TooLs GmbH.
  6 * All rights reserved.
  7 *
  8 * Redistribution and use in source and binary forms, with or without
  9 * modification, are permitted provided that the following conditions
 10 * are met:
 11 * 1. Redistributions of source code must retain the above copyright
 12 *    notice, this list of conditions and the following disclaimer.
 13 * 2. Redistributions in binary form must reproduce the above copyright
 14 *    notice, this list of conditions and the following disclaimer in the
 15 *    documentation and/or other materials provided with the distribution.
 16 * 3. All advertising materials mentioning features or use of this software
 17 *    must display the following acknowledgement:
 18 *	This product includes software developed by TooLs GmbH.
 19 * 4. The name of TooLs GmbH may not be used to endorse or promote products
 20 *    derived from this software without specific prior written permission.
 21 *
 22 * THIS SOFTWARE IS PROVIDED BY TOOLS GMBH ``AS IS'' AND ANY EXPRESS OR
 23 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
 24 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
 25 * IN NO EVENT SHALL TOOLS GMBH BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 26 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 27 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
 28 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
 29 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
 30 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
 31 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 32 */
 33
 34#ifndef _PPC_ASM_H_
 35#define _PPC_ASM_H_
 36
 37#ifdef _LP64
 38
 39/* ppc64 is always PIC, r2 is always the TOC */
 40
 41# define PIC_PLT(x)	.x
 42
 43#else
 44
 45# ifdef __PIC__
 46#  define PIC_PROLOGUE	XXX
 47#  define PIC_EPILOGUE	XXX
 48#  define PIC_PLT(x)	x+32768@plt
 49#  ifdef __STDC__
 50#   define PIC_TOCNAME(name) 	.LCTOC_##name
 51#  else
 52#   define PIC_TOCNAME(name) 	.LCTOC_/**/name
 53#  endif /* __STDC __*/
 54#  define PIC_TOCSETUP(name, reg)						\
 55		.pushsection ".got2","aw"				;\
 56	PIC_TOCNAME(name) = . + 32768					;\
 57		.popsection						;\
 58		bcl	20,31,1001f					;\
 59	1001:	mflr	reg						;\
 60		addis	reg,reg,PIC_TOCNAME(name)-1001b@ha		;\
 61		addi	reg,reg,PIC_TOCNAME(name)-1001b@l
 62#  define PIC_GOTSETUP(reg)						\
 63		bcl	20,31,2002f					;\
 64	2002:	mflr	reg						;\
 65		addis	reg,reg,_GLOBAL_OFFSET_TABLE_-2002b@ha		;\
 66		addi	reg,reg,_GLOBAL_OFFSET_TABLE_-2002b@l
 67#  ifdef __STDC__
 68#   define PIC_GOT(x)	XXX
 69#   define PIC_GOTOFF(x)	XXX
 70#  else	/* not __STDC__ */
 71#   define PIC_GOT(x)	XXX
 72#   define PIC_GOTOFF(x)	XXX
 73#  endif /* __STDC__ */
 74# else /* !__PIC__ */
 75#  define PIC_PROLOGUE
 76#  define PIC_EPILOGUE
 77#  define PIC_PLT(x)	x
 78#  define PIC_GOT(x)	x
 79#  define PIC_GOTOFF(x)	x
 80#  define PIC_GOTSETUP(r)
 81#  define PIC_TOCSETUP(n, r)
 82# endif /* __PIC__ */
 83
 84#endif /* _LP64 */
 85
 86#define	_C_LABEL(x)	x
 87#define	_ASM_LABEL(x)	x
 88
 89#define	_GLOBAL(x) \
 90	.data; .align 2; .globl x; x:
 91
 92#ifdef GPROF
 93# define _PROF_PROLOGUE	mflr 0; stw 0,4(1); bl _mcount
 94#else
 95# define _PROF_PROLOGUE
 96#endif
 97
 98#ifdef _LP64
 99
100# define SF_HEADER_SZ	48
101# define SF_PARAM_SZ	64
102# define SF_SZ		(SF_HEADER_SZ + SF_PARAM_SZ)
103
104# define SF_SP		 0
105# define SF_CR		 8
106# define SF_LR		16
107# define SF_COMP	24
108# define SF_LD		32
109# define SF_TOC		40
110# define SF_PARAM	SF_HEADER_SZ
111# define SF_ALIGN(x)	(((x) + 0xf) & ~0xf)
112
113# define _XENTRY(y)			\
114	.globl	y;			\
115	.pushsection ".opd","aw";	\
116	.align	3;			\
117y:	.quad	.##y,.TOC.@tocbase,0;	\
118	.popsection;			\
119	.size	y,24;			\
120	.type	.##y,@function;		\
121	.globl	.##y;			\
122	.align	3;			\
123.##y:
124
125#define _ENTRY(x)	.text; _XENTRY(x)
126
127# define ENTRY(y) _ENTRY(y)
128
129# define END(y)	.size .##y,. - .##y
130
131# define CALL(y)			\
132	bl	.y;			\
133	nop
134
135# define ENTRY_NOPROFILE(y)	ENTRY(y)
136# define ASENTRY(y)		ENTRY(y)
137#else /* !_LP64 */
138
139# define _XENTRY(x)	.align 2; .globl x; .type x,@function; x:
140# define _ENTRY(x)	.text; _XENTRY(x)
141
142# define ENTRY(y)	_ENTRY(_C_LABEL(y)); _PROF_PROLOGUE
143
144# define END(y)		.size _C_LABEL(y),.-_C_LABEL(y)
145
146# define CALL(y)			\
147	bl	y
148
149# define ENTRY_NOPROFILE(y) _ENTRY(_C_LABEL(y))
150# define ASENTRY(y)	_ENTRY(_ASM_LABEL(y)); _PROF_PROLOGUE
151#endif /* _LP64 */
152
153#define	GLOBAL(y)	_GLOBAL(_C_LABEL(y))
154
155#define	ASMSTR		.asciz
156
157#undef __RCSID
158#define RCSID(x)	__RCSID(x)
159#define __RCSID(x)	.pushsection ".ident","MS",@progbits,1;		\
160			.asciz x;					\
161			.popsection
162
163#ifdef __ELF__
164# define WEAK_ALIAS(alias,sym)						\
165	.weak alias;							\
166	alias = sym
167#endif /* __ELF__ */
168/*
169 * STRONG_ALIAS: create a strong alias.
170 */
171#define STRONG_ALIAS(alias,sym)						\
172	.globl alias;							\
173	alias = sym
174
175#ifdef __STDC__
176# define WARN_REFERENCES(sym,msg)					\
177	.pushsection .gnu.warning. ## sym;				\
178	.ascii msg;							\
179	.popsection
180#else
181# define WARN_REFERENCES(sym,msg)					\
182	.pushsection .gnu.warning./**/sym;				\
183	.ascii msg;							\
184	.popsection
185#endif /* __STDC__ */
186
187#ifdef _KERNEL
188/*
189 * Get cpu_info pointer for current processor.  Always in SPRG0. *ALWAYS*
190 */
191# define GET_CPUINFO(r)		mfsprg r,0
192/*
193 * IN:
194 *	R4[er] = first free byte beyond end/esym.
195 *
196 * OUT:
197 *	R1[sp] = new kernel stack
198 *	R4[er] = kernelend
199 */
200
201# ifdef CI_INTSTK
202#  define INIT_CPUINFO_INTSTK(er,tmp1)					\
203	addis	er,er,INTSTK@ha;					\
204	addi	er,er,INTSTK@l;						\
205	stptr	er,CI_INTSTK(tmp1)
206# else
207#  define INIT_CPUINFO_INTSTK(er,tmp1)	/* nothing */
208# endif /* CI_INTSTK */
209
210/*
211 * We use lis/ori instead of lis/addi in case tmp2 is r0.
212 */
213# define INIT_CPUINFO(er,sp,tmp1,tmp2) 					\
214	li	tmp1,PAGE_MASK;						\
215	add	er,er,tmp1;						\
216	andc	er,er,tmp1;		/* page align */		\
217	lis	tmp1,_C_LABEL(cpu_info)@ha;				\
218	addi	tmp1,tmp1,_C_LABEL(cpu_info)@l;				\
219	mtsprg0	tmp1;			/* save for later use */	\
220	INIT_CPUINFO_INTSTK(er,tmp1);					\
221	lis	tmp2,_C_LABEL(emptyidlespin)@h;				\
222	ori	tmp2,tmp2,_C_LABEL(emptyidlespin)@l;			\
223	stptr	tmp2,CI_IDLESPIN(tmp1);					\
224	li	tmp2,-1;						\
225	stint	tmp2,CI_IDEPTH(tmp1);					\
226	li	tmp2,0;							\
227	lis	%r13,_C_LABEL(lwp0)@h;					\
228	ori	%r13,%r13,_C_LABEL(lwp0)@l;				\
229	stptr	er,L_PCB(%r13);		/* XXXuvm_lwp_getuarea */	\
230	stptr	tmp1,L_CPU(%r13);	 				\
231	addis	er,er,USPACE@ha;	/* stackpointer for lwp0 */	\
232	addi	er,er,USPACE@l;		/* stackpointer for lwp0 */	\
233	addi	sp,er,-FRAMELEN-CALLFRAMELEN;	/* stackpointer for lwp0 */ \
234	stptr	sp,L_MD_UTF(%r13);	/* save in lwp0.l_md.md_utf */	\
235		/* er = end of mem reserved for kernel */		\
236	li	tmp2,0;							\
237	stptr	tmp2,-CALLFRAMELEN(er);	/* end of stack chain */	\
238	stptru	tmp2,-CALLFRAMELEN(sp)	/* end of stack chain */
239
240#endif /* _KERNEL */
241
242
243#if defined(_REGNAMES) && (defined(_KERNEL) || defined(_STANDALONE))
244  /* Condition Register Bit Fields */
245# define cr0	 0
246# define cr1	 1
247# define cr2	 2
248# define cr3	 3
249# define cr4	 4
250# define cr5	 5
251# define cr6	 6
252# define cr7	 7
253  /* General Purpose Registers (GPRs) */
254# define r0	 0
255# define r1	 1
256# define r2	 2
257# define r3	 3
258# define r4	 4
259# define r5	 5
260# define r6	 6
261# define r7	 7
262# define r8	 8
263# define r9	 9
264# define r10	10
265# define r11	11
266# define r12	12
267# define r13	13
268# define r14	14
269# define r15	15
270# define r16	16
271# define r17	17
272# define r18	18
273# define r19	19
274# define r20	20
275# define r21	21
276# define r22	22
277# define r23	23
278# define r24	24
279# define r25	25
280# define r26	26
281# define r27	27
282# define r28	28
283# define r29	29
284# define r30	30
285# define r31	31
286  /* Floating Point Registers (FPRs) */
287# define fr0	 0
288# define fr1	 1
289# define fr2	 2
290# define fr3	 3
291# define fr4	 4
292# define fr5	 5
293# define fr6	 6
294# define fr7	 7
295# define fr8	 8
296# define fr9	 9
297# define fr10	10
298# define fr11	11
299# define fr12	12
300# define fr13	13
301# define fr14	14
302# define fr15	15
303# define fr16	16
304# define fr17	17
305# define fr18	18
306# define fr19	19
307# define fr20	20
308# define fr21	21
309# define fr22	22
310# define fr23	23
311# define fr24	24
312# define fr25	25
313# define fr26	26
314# define fr27	27
315# define fr28	28
316# define fr29	29
317# define fr30	30
318# define fr31	31
319#endif /* _REGNAMES && (_KERNEL || _STANDALONE) */
320
321/*
322 * Add some psuedo instructions to made sharing of assembly versions of
323 * ILP32 and LP64 code possible.
324 */
325#define ldint		lwz	/* not needed but for completeness */
326#define ldintu		lwzu	/* not needed but for completeness */
327#define stint		stw	/* not needed but for completeness */
328#define stintu		stwu	/* not needed but for completeness */
329
330#ifndef _LP64
331
332# define ldlong		lwz	/* load "C" long */
333# define ldlongu	lwzu	/* load "C" long with update */
334# define stlong		stw	/* load "C" long */
335# define stlongu	stwu	/* load "C" long with update */
336# define ldptr		lwz	/* load "C" pointer */
337# define ldptru		lwzu	/* load "C" pointer with update */
338# define stptr		stw	/* load "C" pointer */
339# define stptru		stwu	/* load "C" pointer with update */
340# define ldreg		lwz	/* load PPC general register */
341# define ldregu		lwzu	/* load PPC general register with update */
342# define streg		stw	/* load PPC general register */
343# define stregu		stwu	/* load PPC general register with update */
344# define SZREG		4	/* 4 byte registers */
345# define P2SZREG	2
346
347# define lptrarx	lwarx	/* load "C" pointer with reservation */
348# define llongarx	lwarx	/* load "C" long with reservation */
349# define lregarx	lwarx	/* load PPC general register with reservation */
350
351# define stptrcx	stwcx	/* store "C" pointer conditional */
352# define stlongcx	stwcx	/* store "C" long conditional */
353# define stregcx	stwcx	/* store PPC general register conditional */
354
355# define clrrptri	clrrwi	/* clear right "C" pointer immediate */
356# define clrrlongi	clrrwi	/* clear right "C" long immediate */
357# define clrrregi	clrrwi	/* clear right PPC general register immediate */
358
359# define cmpptr		cmpw
360# define cmplong	cmpw
361# define cmpreg		cmpw
362# define cmpptri	cmpwi
363# define cmplongi	cmpwi
364# define cmpregi	cmpwi
365# define cmpptrl	cmplw
366# define cmplongl	cmplw
367# define cmpregl	cmplw
368# define cmpptrli	cmplwi
369# define cmplongli	cmplwi
370# define cmpregli	cmplwi
371
372#else /* _LP64 */
373
374# define ldlong		ld	/* load "C" long */
375# define ldlongu	ldu	/* load "C" long with update */
376# define stlong		std	/* store "C" long */
377# define stlongu	stdu	/* store "C" long with update */
378# define ldptr		ld	/* load "C" pointer */
379# define ldptru		ldu	/* load "C" pointer with update */
380# define stptr		std	/* store "C" pointer */
381# define stptru		stdu	/* store "C" pointer with update */
382# define ldreg		ld	/* load PPC general register */
383# define ldregu		ldu	/* load PPC general register with update */
384# define streg		std	/* store PPC general register */
385# define stregu		stdu	/* store PPC general register with update */
386/* redefined this to force an error on PPC64 to catch their use.  */
387# define lmw		lmd	/* load multiple PPC general registers */
388# define stmw		stmd	/* store multiple PPC general registers */
389# define SZREG		8	/* 8 byte registers */
390# define P2SZREG	3
391
392# define lptrarx	ldarx	/* load "C" pointer with reservation */
393# define llongarx	ldarx	/* load "C" long with reservation */
394# define lregarx	ldarx	/* load PPC general register with reservation */
395
396# define stptrcx	stdcx	/* store "C" pointer conditional */
397# define stlongcx	stdcx	/* store "C" long conditional */
398# define stregax	stdcx	/* store PPC general register conditional */
399
400# define clrrptri	clrrdi	/* clear right "C" pointer immediate */
401# define clrrlongi	clrrdi	/* clear right "C" long immediate */
402# define clrrregi	clrrdi	/* clear right PPC general register immediate */
403
404# define cmpptr		cmpd
405# define cmplong	cmpd
406# define cmpreg		cmpd
407# define cmpptri	cmpdi
408# define cmplongi	cmpdi
409# define cmpregi	cmpdi
410# define cmpptrl	cmpld
411# define cmplongl	cmpld
412# define cmpregl	cmpld
413# define cmpptrli	cmpldi
414# define cmplongli	cmpldi
415# define cmpregli	cmpldi
416
417#endif /* _LP64 */
418
419#ifdef _LOCORE
420.macro	stmd	r,dst
421	i = 0
422    .rept	32-\r
423	std	i+\r, i*8+\dst
424	i = i + 1
425    .endr
426.endm
427
428.macro	lmd	r,dst
429	i = 0
430    .rept	32-\r
431	ld	i+\r, i*8+\dst
432	i = i + 1
433    .endr
434.endm
435#endif /* _LOCORE */
436
437#if defined(IBM405_ERRATA77) || \
438    ((defined(_MODULE) || !defined(_KERNEL)) && !defined(_LP64))
439/*
440 * Workaround for IBM405 Errata 77 (CPU_210): interrupted stwcx. may
441 * errantly write data to memory
442 *
443 * (1) Insert dcbt before every stwcx. instruction
444 * (2) Insert sync before every rfi/rfci instruction
445 */
446#define	IBM405_ERRATA77_DCBT(ra, rb)	dcbt ra,rb
447#define	IBM405_ERRATA77_SYNC		sync
448#else
449#define	IBM405_ERRATA77_DCBT(ra, rb)	/* nothing */
450#define	IBM405_ERRATA77_SYNC		/* nothing */
451#endif
452
453#endif /* !_PPC_ASM_H_ */