xref: /nrf52832-nimble/rt-thread/libcpu/ppc/ppc405/dcr_gcc.S (revision 104654410c56c573564690304ae786df310c91fc)
1*10465441SEvalZero/*
2*10465441SEvalZero * (C) Copyright 2001
3*10465441SEvalZero * Erik Theisen, Wave 7 Optics, [email protected]
4*10465441SEvalZero *
5*10465441SEvalZero * See file CREDITS for list of people who contributed to this
6*10465441SEvalZero * project.
7*10465441SEvalZero *
8*10465441SEvalZero * This program is free software; you can redistribute it and/or
9*10465441SEvalZero * modify it under the terms of the GNU General Public License as
10*10465441SEvalZero * published by the Free Software Foundation; either version 2 of
11*10465441SEvalZero * the License, or (at your option) any later version.
12*10465441SEvalZero *
13*10465441SEvalZero * This program is distributed in the hope that it will be useful,
14*10465441SEvalZero * but WITHOUT ANY WARRANTY; without even the implied warranty of
15*10465441SEvalZero * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.	 See the
16*10465441SEvalZero * GNU General Public License for more details.
17*10465441SEvalZero *
18*10465441SEvalZero * You should have received a copy of the GNU General Public License
19*10465441SEvalZero * along with this program; if not, write to the Free Software
20*10465441SEvalZero * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
21*10465441SEvalZero * MA 02111-1307 USA
22*10465441SEvalZero */
23*10465441SEvalZero#include <asm/ppc4xx.h>
24*10465441SEvalZero
25*10465441SEvalZero/*****************************************************************************
26*10465441SEvalZero *
27*10465441SEvalZero *  XXX - DANGER
28*10465441SEvalZero *        These routines make use of self modifying code.  DO NOT CALL THEM
29*10465441SEvalZero *	  UNTIL THEY ARE RELOCATED TO RAM.  Additionally, I do not
30*10465441SEvalZero *	  recommend them for use in anything other than an interactive
31*10465441SEvalZero *        debugging environment.  This is mainly due to performance reasons.
32*10465441SEvalZero *
33*10465441SEvalZero ****************************************************************************/
34*10465441SEvalZero
35*10465441SEvalZero/*
36*10465441SEvalZero * static void _create_MFDCR(unsigned short dcrn)
37*10465441SEvalZero *
38*10465441SEvalZero * Builds a 'mfdcr' instruction for get_dcr
39*10465441SEvalZero * function.
40*10465441SEvalZero */
41*10465441SEvalZero		.section ".text"
42*10465441SEvalZero		.align 2
43*10465441SEvalZero		.type	 _create_MFDCR,@function
44*10465441SEvalZero_create_MFDCR:
45*10465441SEvalZero		/*
46*10465441SEvalZero		 * Build up a 'mfdcr' instruction formatted as follows:
47*10465441SEvalZero		 *
48*10465441SEvalZero		 *  OPCD |   RT   |    DCRF      |     XO       | CR |
49*10465441SEvalZero		 * ---------------|--------------|--------------|----|
50*10465441SEvalZero		 * 0   5 | 6   10 | 11        20 | 21        30 | 31 |
51*10465441SEvalZero		 *       |        |    DCRN      |              |    |
52*10465441SEvalZero		 *   31  |  %r3   | (5..9|0..4)  |      323     |  0 |
53*10465441SEvalZero		 *
54*10465441SEvalZero		 * Where:
55*10465441SEvalZero		 *	OPCD = opcode - 31
56*10465441SEvalZero		 *	RT   = destination register - %r3 return register
57*10465441SEvalZero		 *	DCRF = DCRN # with upper and lower halves swapped
58*10465441SEvalZero		 *	XO   = extended opcode - 323
59*10465441SEvalZero		 *	CR   = CR[CR0] NOT undefined - 0
60*10465441SEvalZero		 */
61*10465441SEvalZero		rlwinm	r0, r3, 27, 27, 31	/* OPCD = 31 */
62*10465441SEvalZero		rlwinm	r3, r3, 5, 22, 26
63*10465441SEvalZero		or	r3, r3, r0
64*10465441SEvalZero		slwi	r3, r3, 10
65*10465441SEvalZero		oris	r3, r3, 0x3e30		/* RT = %r3 */
66*10465441SEvalZero		ori	r3, r3, 323		/* XO = 323 */
67*10465441SEvalZero		slwi	r3, r3, 1		/* CR = 0 */
68*10465441SEvalZero
69*10465441SEvalZero		mflr	r4
70*10465441SEvalZero		stw	r3, 0(r4)		/* Store instr in get_dcr() */
71*10465441SEvalZero		dcbst	r0, r4			/* Make sure val is written out */
72*10465441SEvalZero		sync				/* Wait for write to complete */
73*10465441SEvalZero		icbi	r0, r4			/* Make sure old instr is dumped */
74*10465441SEvalZero		isync				/* Wait for icbi to complete */
75*10465441SEvalZero
76*10465441SEvalZero		blr
77*10465441SEvalZero.Lfe1:		.size	 _create_MFDCR,.Lfe1-_create_MFDCR
78*10465441SEvalZero/* end _create_MFDCR() */
79*10465441SEvalZero
80*10465441SEvalZero/*
81*10465441SEvalZero * static void _create_MTDCR(unsigned short dcrn, unsigned long value)
82*10465441SEvalZero *
83*10465441SEvalZero * Builds a 'mtdcr' instruction for set_dcr
84*10465441SEvalZero * function.
85*10465441SEvalZero */
86*10465441SEvalZero		.section ".text"
87*10465441SEvalZero		.align 2
88*10465441SEvalZero		.type	 _create_MTDCR,@function
89*10465441SEvalZero_create_MTDCR:
90*10465441SEvalZero		/*
91*10465441SEvalZero		 * Build up a 'mtdcr' instruction formatted as follows:
92*10465441SEvalZero		 *
93*10465441SEvalZero		 *  OPCD |   RS   |    DCRF      |     XO       | CR |
94*10465441SEvalZero		 * ---------------|--------------|--------------|----|
95*10465441SEvalZero		 * 0   5 | 6   10 | 11        20 | 21        30 | 31 |
96*10465441SEvalZero		 *       |        |    DCRN      |              |    |
97*10465441SEvalZero		 *   31  |  %r3   | (5..9|0..4)  |      451     |  0 |
98*10465441SEvalZero		 *
99*10465441SEvalZero		 * Where:
100*10465441SEvalZero		 *	OPCD = opcode - 31
101*10465441SEvalZero		 *	RS   = source register - %r4
102*10465441SEvalZero		 *	DCRF = dest. DCRN # with upper and lower halves swapped
103*10465441SEvalZero		 *	XO   = extended opcode - 451
104*10465441SEvalZero		 *	CR   = CR[CR0] NOT undefined - 0
105*10465441SEvalZero		 */
106*10465441SEvalZero		rlwinm	r0, r3, 27, 27, 31	/* OPCD = 31 */
107*10465441SEvalZero		rlwinm	r3, r3, 5, 22, 26
108*10465441SEvalZero		or	r3, r3, r0
109*10465441SEvalZero		slwi	r3, r3, 10
110*10465441SEvalZero		oris	r3, r3, 0x3e40		/* RS = %r4 */
111*10465441SEvalZero		ori	r3, r3, 451		/* XO = 451 */
112*10465441SEvalZero		slwi	r3, r3, 1		/* CR = 0 */
113*10465441SEvalZero
114*10465441SEvalZero		mflr	r5
115*10465441SEvalZero		stw	r3, 0(r5)		/* Store instr in set_dcr() */
116*10465441SEvalZero		dcbst	r0, r5			/* Make sure val is written out */
117*10465441SEvalZero		sync				/* Wait for write to complete */
118*10465441SEvalZero		icbi	r0, r5			/* Make sure old instr is dumped */
119*10465441SEvalZero		isync				/* Wait for icbi to complete */
120*10465441SEvalZero
121*10465441SEvalZero		blr
122*10465441SEvalZero.Lfe2:		.size	 _create_MTDCR,.Lfe2-_create_MTDCR
123*10465441SEvalZero/* end _create_MTDCR() */
124*10465441SEvalZero
125*10465441SEvalZero
126*10465441SEvalZero/*
127*10465441SEvalZero * unsigned long get_dcr(unsigned short dcrn)
128*10465441SEvalZero *
129*10465441SEvalZero * Return a given DCR's value.
130*10465441SEvalZero */
131*10465441SEvalZero		/* */
132*10465441SEvalZero		/* XXX - This is self modifying code, hence */
133*10465441SEvalZero		/* it is in the data section. */
134*10465441SEvalZero		/* */
135*10465441SEvalZero		.section ".text"
136*10465441SEvalZero		.align	2
137*10465441SEvalZero		.globl	get_dcr
138*10465441SEvalZero		.type	get_dcr,@function
139*10465441SEvalZeroget_dcr:
140*10465441SEvalZero		mflr	r0			/* Get link register */
141*10465441SEvalZero		stwu	r1, -32(r1)		/* Save back chain and move SP */
142*10465441SEvalZero		stw	r0, +36(r1)		/* Save link register */
143*10465441SEvalZero
144*10465441SEvalZero		bl	_create_MFDCR		/* Build following instruction */
145*10465441SEvalZero		/* XXX - we build this instuction up on the fly. */
146*10465441SEvalZero		.long	0			/* Get DCR's value */
147*10465441SEvalZero
148*10465441SEvalZero		lwz	r0, +36(r1)		/* Get saved link register */
149*10465441SEvalZero		mtlr	r0			/* Restore link register */
150*10465441SEvalZero		addi	r1, r1, +32		/* Remove frame from stack */
151*10465441SEvalZero		blr				/* Return to calling function */
152*10465441SEvalZero.Lfe3:		.size	get_dcr,.Lfe3-get_dcr
153*10465441SEvalZero/* end get_dcr() */
154*10465441SEvalZero
155*10465441SEvalZero
156*10465441SEvalZero/*
157*10465441SEvalZero * unsigned void set_dcr(unsigned short dcrn, unsigned long value)
158*10465441SEvalZero *
159*10465441SEvalZero * Return a given DCR's value.
160*10465441SEvalZero */
161*10465441SEvalZero		/*
162*10465441SEvalZero		 * XXX - This is self modifying code, hence
163*10465441SEvalZero		 * it is in the data section.
164*10465441SEvalZero		 */
165*10465441SEvalZero		.section ".text"
166*10465441SEvalZero		.align	2
167*10465441SEvalZero		.globl	set_dcr
168*10465441SEvalZero		.type	set_dcr,@function
169*10465441SEvalZeroset_dcr:
170*10465441SEvalZero		mflr	r0			/* Get link register */
171*10465441SEvalZero		stwu	r1, -32(r1)		/* Save back chain and move SP */
172*10465441SEvalZero		stw	r0, +36(r1)		/* Save link register */
173*10465441SEvalZero
174*10465441SEvalZero		bl	_create_MTDCR		/* Build following instruction */
175*10465441SEvalZero		/* XXX - we build this instuction up on the fly. */
176*10465441SEvalZero		.long	0			/* Set DCR's value */
177*10465441SEvalZero
178*10465441SEvalZero		lwz	r0, +36(r1)		/* Get saved link register */
179*10465441SEvalZero		mtlr	r0			/* Restore link register */
180*10465441SEvalZero		addi	r1, r1, +32		/* Remove frame from stack */
181*10465441SEvalZero		blr				/* Return to calling function */
182*10465441SEvalZero.Lfe4:		.size	set_dcr,.Lfe4-set_dcr
183*10465441SEvalZero/* end set_dcr() */
184*10465441SEvalZero
185