source: rtems/c/src/lib/libcpu/powerpc/shared/include/powerpc-utility.h @ d3c32136

4.104.114.95
Last change on this file since d3c32136 was d3c32136, checked in by Thomas Doerfler <Thomas.Doerfler@…>, on 07/18/08 at 15:56:48

Changed special purpose register inline functions to macros.
fixed some minors in mpc83xx support
added file for mpc55xx watchdog support

  • Property mode set to 100644
File size: 9.9 KB
Line 
1/**
2 * @file
3 *
4 * @ingroup powerpc_shared
5 *
6 * @brief General purpose assembler macros, linker command file support and
7 * some inline functions for direct register access.
8 */
9
10/*
11 * Copyright (c) 2008
12 * Embedded Brains GmbH
13 * Obere Lagerstr. 30
14 * D-82178 Puchheim
15 * Germany
16 * rtems@embedded-brains.de
17 *
18 * access function for Device Control Registers inspired by "ppc405common.h"
19 * from Michael Hamel ADInstruments May 2008
20 *
21 * The license and distribution terms for this file may be found in the file
22 * LICENSE in this distribution or at http://www.rtems.com/license/LICENSE.
23 */
24
25/**
26 * @defgroup powerpc_shared Shared PowerPC Code
27 */
28
29#ifndef LIBCPU_POWERPC_UTILITY_H
30#define LIBCPU_POWERPC_UTILITY_H
31
32#include <rtems/powerpc/registers.h>
33
34#ifndef ASM
35
36#include <stdint.h>
37
38#include <rtems/bspIo.h>
39#include <rtems/system.h>
40#include <rtems/score/cpu.h>
41
42#include <libcpu/cpuIdent.h>
43
44#define LINKER_SYMBOL( sym) extern char sym []
45
46/**
47 * @brief Read one byte from @a src.
48 */
49static inline uint8_t ppc_read_byte( const volatile void *src)
50{
51        uint8_t value;
52
53        asm volatile (
54                "lbz %0, 0(%1)"
55                : "=r" (value)
56                : "r" (src)
57        );
58
59        return value;
60}
61
62/**
63 * @brief Read one half word from @a src.
64 */
65static inline uint16_t ppc_read_half_word( const volatile void *src)
66{
67        uint16_t value;
68
69        asm volatile (
70                "lhz %0, 0(%1)"
71                : "=r" (value)
72                : "r" (src)
73        );
74
75        return value;
76}
77
78/**
79 * @brief Read one word from @a src.
80 */
81static inline uint32_t ppc_read_word( const volatile void *src)
82{
83        uint32_t value;
84
85        asm volatile (
86                "lwz %0, 0(%1)"
87                : "=r" (value)
88                : "r" (src)
89        );
90
91        return value;
92}
93
94/**
95 * @brief Write one byte @a value to @a dest.
96 */
97static inline void ppc_write_byte( uint8_t value, volatile void *dest)
98{
99        asm volatile (
100                "stb %0, 0(%1)"
101                :
102                : "r" (value), "r" (dest)
103        );
104}
105
106/**
107 * @brief Write one half word @a value to @a dest.
108 */
109static inline void ppc_write_half_word( uint16_t value, volatile void *dest)
110{
111        asm volatile (
112                "sth %0, 0(%1)"
113                :
114                : "r" (value), "r" (dest)
115        );
116}
117
118/**
119 * @brief Write one word @a value to @a dest.
120 */
121static inline void ppc_write_word( uint32_t value, volatile void *dest)
122{
123        asm volatile (
124                "stw %0, 0(%1)" :
125                : "r" (value), "r" (dest)
126        );
127}
128
129
130static inline void *ppc_stack_pointer()
131{
132        void *sp;
133
134        asm volatile (
135                "mr %0, 1"
136                : "=r" (sp)
137        );
138
139        return sp;
140}
141
142static inline void ppc_set_stack_pointer( void *sp)
143{
144        asm volatile (
145                "mr 1, %0"
146                :
147                : "r" (sp)
148        );
149}
150
151static inline void *ppc_link_register()
152{
153        void *lr;
154
155        asm volatile (
156                "mflr %0"
157                : "=r" (lr)
158        );
159
160        return lr;
161}
162
163static inline void ppc_set_link_register( void *lr)
164{
165        asm volatile (
166                "mtlr %0"
167                :
168                : "r" (lr)
169        );
170}
171
172static inline uint32_t ppc_machine_state_register()
173{
174        uint32_t msr;
175
176        asm volatile (
177                "mfmsr %0"
178                : "=r" (msr)
179        );
180
181        return msr;
182}
183
184static inline void ppc_set_machine_state_register( uint32_t msr)
185{
186        asm volatile (
187                "mtmsr %0"
188                :
189                : "r" (msr)
190        );
191}
192
193/**
194 * @brief Enables external exceptions.
195 *
196 * You can use this function to enable the external exceptions and restore the
197 * machine state with ppc_external_exceptions_disable() later.
198 */
199static inline uint32_t ppc_external_exceptions_enable()
200{
201        uint32_t current_msr;
202        uint32_t new_msr;
203
204        RTEMS_COMPILER_MEMORY_BARRIER();
205
206        asm volatile (
207                "mfmsr %0;"
208                "ori %1, %0, 0x8000;"
209                "mtmsr %1"
210                : "=r" (current_msr), "=r" (new_msr)
211        );
212
213        return current_msr;
214}
215
216/**
217 * @brief Restores machine state.
218 *
219 * @see ppc_external_exceptions_enable()
220 */
221static inline void ppc_external_exceptions_disable( uint32_t msr)
222{
223        ppc_set_machine_state_register( msr);
224
225        RTEMS_COMPILER_MEMORY_BARRIER();
226}
227
228static inline uint32_t ppc_decrementer_register()
229{
230        uint32_t dec;
231
232        PPC_Get_decrementer( dec);
233
234        return dec;
235}
236
237static inline void ppc_set_decrementer_register( uint32_t dec)
238{
239        PPC_Set_decrementer( dec);
240}
241
242/**
243 * @brief Preprocessor magic for stringification of @a x.
244 */
245#define PPC_STRINGOF( x) #x
246
247/**
248 * @brief Returns the value of the Special Purpose Register with number @a spr.
249 *
250 * @note This macro uses a GNU C extension.
251 */
252#define PPC_SPECIAL_PURPOSE_REGISTER( spr) \
253        ( { \
254                uint32_t val; \
255                asm volatile ( \
256                        "mfspr %0, " PPC_STRINGOF( spr) \
257                        : "=r" (val) \
258                ); \
259                val;\
260        } )
261
262/**
263 * @brief Sets the Special Purpose Register with number @a spr to the value in
264 * @a val.
265 */
266#define PPC_SET_SPECIAL_PURPOSE_REGISTER( spr, val) \
267        do { \
268                asm volatile ( \
269                        "mtspr " PPC_STRINGOF( spr) ", %0" \
270                        : \
271                        : "r" (val) \
272                ); \
273        } while (0)
274
275/**
276 * @brief Sets in the Special Purpose Register with number @a spr all bits
277 * which are set in @a bits.
278 *
279 * Interrupts are disabled throughout this operation.
280 */
281#define PPC_SET_SPECIAL_PURPOSE_REGISTER_BITS( spr, bits) \
282        do { \
283                rtems_interrupt_level level; \
284                uint32_t val; \
285                rtems_interrupt_disable( level); \
286                val = PPC_SPECIAL_PURPOSE_REGISTER( spr); \
287                val |= bits; \
288                PPC_SET_SPECIAL_PURPOSE_REGISTER( spr, val); \
289                rtems_interrupt_enable( level); \
290        } while (0)
291
292/**
293 * @brief Sets in the Special Purpose Register with number @a spr all bits
294 * which are set in @a bits.  The previous register value will be masked with
295 * @a mask.
296 *
297 * Interrupts are disabled throughout this operation.
298 */
299#define PPC_SET_SPECIAL_PURPOSE_REGISTER_BITS_MASKED( spr, bits, mask) \
300        do { \
301                rtems_interrupt_level level; \
302                uint32_t val; \
303                rtems_interrupt_disable( level); \
304                val = PPC_SPECIAL_PURPOSE_REGISTER( spr); \
305                val &= ~mask; \
306                val |= bits; \
307                PPC_SET_SPECIAL_PURPOSE_REGISTER( spr, val); \
308                rtems_interrupt_enable( level); \
309        } while (0)
310
311/**
312 * @brief Clears in the Special Purpose Register with number @a spr all bits
313 * which are set in @a bits.
314 *
315 * Interrupts are disabled throughout this operation.
316 */
317#define PPC_CLEAR_SPECIAL_PURPOSE_REGISTER_BITS( spr, bits) \
318        do { \
319                rtems_interrupt_level level; \
320                uint32_t val; \
321                rtems_interrupt_disable( level); \
322                val = PPC_SPECIAL_PURPOSE_REGISTER( spr); \
323                val &= ~bits; \
324                PPC_SET_SPECIAL_PURPOSE_REGISTER( spr, val); \
325                rtems_interrupt_enable( level); \
326        } while (0)
327
328/**
329 * @brief Returns the value of the Device Control Register with number @a dcr.
330 *
331 * The PowerPC 4XX family has Device Control Registers.
332 *
333 * @note This macro uses a GNU C extension.
334 */
335#define PPC_DEVICE_CONTROL_REGISTER( dcr) \
336        ( { \
337                uint32_t val; \
338                asm volatile ( \
339                        "mfdcr %0, " PPC_STRINGOF( dcr) \
340                        : "=r" (val) \
341                ); \
342                val;\
343        } )
344
345/**
346 * @brief Sets the Device Control Register with number @a dcr to the value in
347 * @a val.
348 *
349 * The PowerPC 4XX family has Device Control Registers.
350 */
351#define PPC_SET_DEVICE_CONTROL_REGISTER( dcr, val) \
352        do { \
353                asm volatile ( \
354                        "mtdcr " PPC_STRINGOF( dcr) ", %0" \
355                        : \
356                        : "r" (val) \
357                ); \
358        } while (0)
359
360/**
361 * @brief Sets in the Device Control Register with number @a dcr all bits
362 * which are set in @a bits.
363 *
364 * Interrupts are disabled throughout this operation.
365 */
366#define PPC_SET_DEVICE_CONTROL_REGISTER_BITS( dcr, bits) \
367        do { \
368                rtems_interrupt_level level; \
369                uint32_t val; \
370                rtems_interrupt_disable( level); \
371                val = PPC_DEVICE_CONTROL_REGISTER( dcr); \
372                val |= bits; \
373                PPC_SET_DEVICE_CONTROL_REGISTER( dcr, val); \
374                rtems_interrupt_enable( level); \
375        } while (0)
376
377/**
378 * @brief Sets in the Device Control Register with number @a dcr all bits
379 * which are set in @a bits.  The previous register value will be masked with
380 * @a mask.
381 *
382 * Interrupts are disabled throughout this operation.
383 */
384#define PPC_SET_DEVICE_CONTROL_REGISTER_BITS_MASKED( dcr, bits, mask) \
385        do { \
386                rtems_interrupt_level level; \
387                uint32_t val; \
388                rtems_interrupt_disable( level); \
389                val = PPC_DEVICE_CONTROL_REGISTER( dcr); \
390                val &= ~mask; \
391                val |= bits; \
392                PPC_SET_DEVICE_CONTROL_REGISTER( dcr, val); \
393                rtems_interrupt_enable( level); \
394        } while (0)
395
396/**
397 * @brief Clears in the Device Control Register with number @a dcr all bits
398 * which are set in @a bits.
399 *
400 * Interrupts are disabled throughout this operation.
401 */
402#define PPC_CLEAR_DEVICE_CONTROL_REGISTER_BITS( dcr, bits) \
403        do { \
404                rtems_interrupt_level level; \
405                uint32_t val; \
406                rtems_interrupt_disable( level); \
407                val = PPC_DEVICE_CONTROL_REGISTER( dcr); \
408                val &= ~bits; \
409                PPC_SET_DEVICE_CONTROL_REGISTER( dcr, val); \
410                rtems_interrupt_enable( level); \
411        } while (0)
412
413static inline uint32_t ppc_time_base()
414{
415        uint32_t val;
416
417        CPU_Get_timebase_low( val);
418
419        return val;
420}
421
422static inline void ppc_set_time_base( uint32_t val)
423{
424        PPC_SET_SPECIAL_PURPOSE_REGISTER( TBWL, val);
425}
426
427static inline uint32_t ppc_time_base_upper()
428{
429        return PPC_SPECIAL_PURPOSE_REGISTER( TBRU);
430}
431
432static inline void ppc_set_time_base_upper( uint32_t val)
433{
434        PPC_SET_SPECIAL_PURPOSE_REGISTER( TBWU, val);
435}
436
437static inline uint64_t ppc_time_base_64()
438{
439        return PPC_Get_timebase_register();
440}
441
442static inline void ppc_set_time_base_64( uint64_t val)
443{
444        PPC_Set_timebase_register( val);
445}
446
447#else /* ASM */
448
449#include <rtems/asm.h>
450
451.macro LA reg, addr
452        lis     \reg, (\addr)@h
453        ori     \reg, \reg, (\addr)@l
454.endm
455
456.macro LWI reg, value
457        lis \reg, (\value)@h
458        ori     \reg, \reg, (\value)@l
459.endm
460
461.macro LW reg, addr
462        lis     \reg, \addr@ha
463        lwz     \reg, \addr@l(\reg)
464.endm
465
466/*
467 * Tests the bits in reg1 against the bits set in mask.  A match is indicated
468 * by EQ = 0 in CR0.  A mismatch is indicated by EQ = 1 in CR0.  The register
469 * reg2 is used to load the mask.
470 */
471.macro  TSTBITS reg1, reg2, mask
472        LWI     \reg2, \mask
473        and     \reg1, \reg1, \reg2
474        cmplw   \reg1, \reg2
475.endm   
476       
477.macro  SETBITS reg1, reg2, mask
478        LWI     \reg2, \mask
479        or      \reg1, \reg1, \reg2
480.endm
481
482.macro  CLRBITS reg1, reg2, mask
483        LWI     \reg2, \mask
484        andc    \reg1, \reg1, \reg2
485.endm
486
487.macro GLOBAL_FUNCTION name
488        .global \name
489        .type \name, @function
490\name:
491.endm
492
493/*
494 * Obtain interrupt mask
495 */
496.macro GET_INTERRUPT_MASK mask
497        mfspr   \mask, sprg0
498.endm
499
500/*
501 * Disables all asynchronous exeptions (interrupts) which may cause a context
502 * switch.
503 */
504.macro INTERRUPT_DISABLE level, mask
505        mfmsr   \level
506        GET_INTERRUPT_MASK mask=\mask
507        andc    \mask, \level, \mask
508        mtmsr   \mask
509.endm
510
511/*
512 * Restore previous machine state.
513 */
514.macro INTERRUPT_ENABLE level
515        mtmsr   \level
516.endm
517
518#define LINKER_SYMBOL( sym) .extern sym
519
520#endif /* ASM */
521
522#endif /* LIBCPU_POWERPC_UTILITY_H */
Note: See TracBrowser for help on using the repository browser.