]> git.kernelconcepts.de Git - karo-tx-uboot.git/blob - arch/powerpc/cpu/ppc4xx/dcr.S
Merge branch 'master' of git://git.denx.de/u-boot-arm
[karo-tx-uboot.git] / arch / powerpc / cpu / ppc4xx / dcr.S
1 /*
2  * (C) Copyright 2001
3  * Erik Theisen, Wave 7 Optics, etheisen@mindspring.com
4  *
5  * SPDX-License-Identifier:     GPL-2.0+
6  */
7 #include <config.h>
8
9 #if defined(CONFIG_4xx) && defined(CONFIG_CMD_SETGETDCR)
10
11 #include <asm/ppc4xx.h>
12
13 #include <ppc_asm.tmpl>
14 #include <ppc_defs.h>
15
16 #include <asm/cache.h>
17 #include <asm/mmu.h>
18
19 #define _ASMLANGUAGE
20
21 /*****************************************************************************
22  *
23  *  XXX - DANGER
24  *        These routines make use of self modifying code.  DO NOT CALL THEM
25  *        UNTIL THEY ARE RELOCATED TO RAM.  Additionally, I do not
26  *        recommend them for use in anything other than an interactive
27  *        debugging environment.  This is mainly due to performance reasons.
28  *
29  ****************************************************************************/
30
31 /*
32  * static void _create_MFDCR(unsigned short dcrn)
33  *
34  * Builds a 'mfdcr' instruction for get_dcr
35  * function.
36  */
37                 .section ".text"
38                 .align 2
39                 .type    _create_MFDCR,@function
40 _create_MFDCR:
41                 /*
42                  * Build up a 'mfdcr' instruction formatted as follows:
43                  *
44                  *  OPCD |   RT   |    DCRF      |     XO       | CR |
45                  * ---------------|--------------|--------------|----|
46                  * 0   5 | 6   10 | 11        20 | 21        30 | 31 |
47                  *       |        |    DCRN      |              |    |
48                  *   31  |  %r3   | (5..9|0..4)  |      323     |  0 |
49                  *
50                  * Where:
51                  *      OPCD = opcode - 31
52                  *      RT   = destination register - %r3 return register
53                  *      DCRF = DCRN # with upper and lower halves swapped
54                  *      XO   = extended opcode - 323
55                  *      CR   = CR[CR0] NOT undefined - 0
56                  */
57                 rlwinm  r0, r3, 27, 27, 31      /* OPCD = 31 */
58                 rlwinm  r3, r3, 5, 22, 26
59                 or      r3, r3, r0
60                 slwi    r3, r3, 10
61                 oris    r3, r3, 0x3e30          /* RT = %r3 */
62                 ori     r3, r3, 323             /* XO = 323 */
63                 slwi    r3, r3, 1               /* CR = 0 */
64
65                 mflr    r4
66                 stw     r3, 0(r4)               /* Store instr in get_dcr() */
67                 dcbst   r0, r4                  /* Make sure val is written out */
68                 sync                            /* Wait for write to complete */
69                 icbi    r0, r4                  /* Make sure old instr is dumped */
70                 isync                           /* Wait for icbi to complete */
71
72                 blr
73 .Lfe1:          .size    _create_MFDCR,.Lfe1-_create_MFDCR
74 /* end _create_MFDCR() */
75
76 /*
77  * static void _create_MTDCR(unsigned short dcrn, unsigned long value)
78  *
79  * Builds a 'mtdcr' instruction for set_dcr
80  * function.
81  */
82                 .section ".text"
83                 .align 2
84                 .type    _create_MTDCR,@function
85 _create_MTDCR:
86                 /*
87                  * Build up a 'mtdcr' instruction formatted as follows:
88                  *
89                  *  OPCD |   RS   |    DCRF      |     XO       | CR |
90                  * ---------------|--------------|--------------|----|
91                  * 0   5 | 6   10 | 11        20 | 21        30 | 31 |
92                  *       |        |    DCRN      |              |    |
93                  *   31  |  %r3   | (5..9|0..4)  |      451     |  0 |
94                  *
95                  * Where:
96                  *      OPCD = opcode - 31
97                  *      RS   = source register - %r4
98                  *      DCRF = dest. DCRN # with upper and lower halves swapped
99                  *      XO   = extended opcode - 451
100                  *      CR   = CR[CR0] NOT undefined - 0
101                  */
102                 rlwinm  r0, r3, 27, 27, 31      /* OPCD = 31 */
103                 rlwinm  r3, r3, 5, 22, 26
104                 or      r3, r3, r0
105                 slwi    r3, r3, 10
106                 oris    r3, r3, 0x3e40          /* RS = %r4 */
107                 ori     r3, r3, 451             /* XO = 451 */
108                 slwi    r3, r3, 1               /* CR = 0 */
109
110                 mflr    r5
111                 stw     r3, 0(r5)               /* Store instr in set_dcr() */
112                 dcbst   r0, r5                  /* Make sure val is written out */
113                 sync                            /* Wait for write to complete */
114                 icbi    r0, r5                  /* Make sure old instr is dumped */
115                 isync                           /* Wait for icbi to complete */
116
117                 blr
118 .Lfe2:          .size    _create_MTDCR,.Lfe2-_create_MTDCR
119 /* end _create_MTDCR() */
120
121
122 /*
123  * unsigned long get_dcr(unsigned short dcrn)
124  *
125  * Return a given DCR's value.
126  */
127                 /* */
128                 /* XXX - This is self modifying code, hence */
129                 /* it is in the data section. */
130                 /* */
131                 .section ".data"
132                 .align  2
133                 .globl  get_dcr
134                 .type   get_dcr,@function
135 get_dcr:
136                 mflr    r0                      /* Get link register */
137                 stwu    r1, -32(r1)             /* Save back chain and move SP */
138                 stw     r0, +36(r1)             /* Save link register */
139
140                 bl      _create_MFDCR           /* Build following instruction */
141                 /* XXX - we build this instuction up on the fly. */
142                 .long   0                       /* Get DCR's value */
143
144                 lwz     r0, +36(r1)             /* Get saved link register */
145                 mtlr    r0                      /* Restore link register */
146                 addi    r1, r1, +32             /* Remove frame from stack */
147                 blr                             /* Return to calling function */
148 .Lfe3:          .size   get_dcr,.Lfe3-get_dcr
149 /* end get_dcr() */
150
151
152 /*
153  * unsigned void set_dcr(unsigned short dcrn, unsigned long value)
154  *
155  * Return a given DCR's value.
156  */
157                 /*
158                  * XXX - This is self modifying code, hence
159                  * it is in the data section.
160                  */
161                 .section ".data"
162                 .align  2
163                 .globl  set_dcr
164                 .type   set_dcr,@function
165 set_dcr:
166                 mflr    r0                      /* Get link register */
167                 stwu    r1, -32(r1)             /* Save back chain and move SP */
168                 stw     r0, +36(r1)             /* Save link register */
169
170                 bl      _create_MTDCR           /* Build following instruction */
171                 /* XXX - we build this instuction up on the fly. */
172                 .long   0                       /* Set DCR's value */
173
174                 lwz     r0, +36(r1)             /* Get saved link register */
175                 mtlr    r0                      /* Restore link register */
176                 addi    r1, r1, +32             /* Remove frame from stack */
177                 blr                             /* Return to calling function */
178 .Lfe4:          .size   set_dcr,.Lfe4-set_dcr
179 /* end set_dcr() */
180 #endif