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