summaryrefslogtreecommitdiffstats
path: root/c/src/exec/score/cpu/powerpc/cpu.h
diff options
context:
space:
mode:
authorJoel Sherrill <joel.sherrill@OARcorp.com>1998-04-14 19:54:24 +0000
committerJoel Sherrill <joel.sherrill@OARcorp.com>1998-04-14 19:54:24 +0000
commit993e1b5c733572b09c16cb2057a0d18a22a91d2d (patch)
tree4bcc47c847ca5789308c6b773aa3a2e9df12cb34 /c/src/exec/score/cpu/powerpc/cpu.h
parentremoved shmsupp (diff)
downloadrtems-993e1b5c733572b09c16cb2057a0d18a22a91d2d.tar.bz2
Refreshing effort from Avenger.
Diffstat (limited to 'c/src/exec/score/cpu/powerpc/cpu.h')
-rw-r--r--c/src/exec/score/cpu/powerpc/cpu.h265
1 files changed, 168 insertions, 97 deletions
diff --git a/c/src/exec/score/cpu/powerpc/cpu.h b/c/src/exec/score/cpu/powerpc/cpu.h
index 3f6cb0f000..d2353bacf5 100644
--- a/c/src/exec/score/cpu/powerpc/cpu.h
+++ b/c/src/exec/score/cpu/powerpc/cpu.h
@@ -20,12 +20,12 @@
*
* Derived from c/src/exec/cpu/no_cpu/cpu.h:
*
- * COPYRIGHT (c) 1989-1998.
+ * COPYRIGHT (c) 1989-1997.
* On-Line Applications Research Corporation (OAR).
* Copyright assigned to U.S. Government, 1994.
*
- * The license and distribution terms for this file may be
- * found in the file LICENSE in this distribution or at
+ * The license and distribution terms for this file may in
+ * the file LICENSE in this distribution or at
* http://www.OARcorp.com/rtems/license.html.
*
* $Id$
@@ -285,7 +285,7 @@ struct CPU_Interrupt_frame;
*/
#define CPU_STRUCTURE_ALIGNMENT \
- __attribute__ ((aligned (PPC_CACHE_ALIGNMENT)))
+ __attribute__ ((aligned (PPC_CACHE_ALIGNMENT)))
/*
* Define what is required to specify how the network to host conversion
@@ -300,16 +300,27 @@ struct CPU_Interrupt_frame;
* The following defines the number of bits actually used in the
* interrupt field of the task mode. How those bits map to the
* CPU interrupt levels is defined by the routine _CPU_ISR_Set_level().
- */
-/*
- * ACB Note: Levels are:
- * 0: All maskable interrupts enabled
- * 1: Other critical exceptions enabled
- * 2: Machine check enabled
- * 3: All maskable IRQs disabled
+ *
+ * The interrupt level is bit mapped for the PowerPC family. The
+ * bits are set to 0 to indicate that a particular exception source
+ * enabled and 1 if it is disabled. This keeps with RTEMS convention
+ * that interrupt level 0 means all sources are enabled.
+ *
+ * The bits are assigned to correspond to enable bits in the MSR.
*/
-#define CPU_MODES_INTERRUPT_MASK 0x00000003
+#define PPC_INTERRUPT_LEVEL_ME 0x01
+#define PPC_INTERRUPT_LEVEL_EE 0x02
+#define PPC_INTERRUPT_LEVEL_CE 0x04
+
+/* XXX should these be maskable? */
+#if 0
+#define PPC_INTERRUPT_LEVEL_DE 0x08
+#define PPC_INTERRUPT_LEVEL_BE 0x10
+#define PPC_INTERRUPT_LEVEL_SE 0x20
+#endif
+
+#define CPU_MODES_INTERRUPT_MASK 0x00000007
/*
* Processor defined structures
@@ -450,18 +461,38 @@ typedef struct {
void (*stack_free_hook)( void* );
/* end of fields required on all CPUs */
- unsigned32 clicks_per_usec; /* Timer clicks per microsecond */
- unsigned32 serial_per_sec; /* Serial clocks per second */
+ unsigned32 clicks_per_usec; /* Timer clicks per microsecond */
+ void (*spurious_handler)(unsigned32 vector, CPU_Interrupt_frame *);
+ boolean exceptions_in_RAM; /* TRUE if in RAM */
+
+#if defined(ppc403)
+ unsigned32 serial_per_sec; /* Serial clocks per second */
boolean serial_external_clock;
boolean serial_xon_xoff;
boolean serial_cts_rts;
unsigned32 serial_rate;
unsigned32 timer_average_overhead; /* Average overhead of timer in ticks */
- unsigned32 timer_least_valid; /* Least valid number from timer */
- void (*spurious_handler)(unsigned32 vector, CPU_Interrupt_frame *);
+ unsigned32 timer_least_valid; /* Least valid number from timer */
+#endif
} rtems_cpu_table;
/*
+ * The following type defines an entry in the PPC's trap table.
+ *
+ * NOTE: The instructions chosen are RTEMS dependent although one is
+ * obligated to use two of the four instructions to perform a
+ * long jump. The other instructions load one register with the
+ * trap type (a.k.a. vector) and another with the psr.
+ */
+
+typedef struct {
+ unsigned32 stwu_r1; /* stwu %r1, -(??+IP_END)(%1)*/
+ unsigned32 stw_r0; /* stw %r0, IP_0(%r1) */
+ unsigned32 li_r0_IRQ; /* li %r0, _IRQ */
+ unsigned32 b_Handler; /* b PROC (_ISR_Handler) */
+} CPU_Trap_table_entry;
+
+/*
* This variable is optional. It is used on CPUs on which it is difficult
* to generate an "uninitialized" FP context. It is filled in by
* _CPU_Initialize and copied into the task's FP context area during
@@ -502,6 +533,7 @@ SCORE_EXTERN void *_CPU_Interrupt_stack_high;
* Nothing prevents the porter from declaring more CPU specific variables.
*/
+
SCORE_EXTERN struct {
unsigned32 *Nest_level;
unsigned32 *Disable_level;
@@ -517,6 +549,8 @@ SCORE_EXTERN struct {
#endif
volatile boolean *Switch_necessary;
boolean *Signal;
+
+ unsigned32 msr_initial;
} _CPU_IRQ_info CPU_STRUCTURE_ALIGNMENT;
/*
@@ -549,8 +583,8 @@ SCORE_EXTERN struct {
* by RTEMS.
*/
-#define CPU_INTERRUPT_NUMBER_OF_VECTORS (PPC_INTERRUPT_MAX)
-#define CPU_INTERRUPT_MAXIMUM_VECTOR_NUMBER (CPU_INTERRUPT_NUMBER_OF_VECTORS - 1)
+#define CPU_INTERRUPT_NUMBER_OF_VECTORS (PPC_INTERRUPT_MAX)
+#define CPU_INTERRUPT_MAXIMUM_VECTOR_NUMBER (PPC_INTERRUPT_MAX - 1)
/*
* Should be large enough to run all RTEMS tests. This insures
@@ -609,45 +643,94 @@ SCORE_EXTERN struct {
/*
* Disable all interrupts for an RTEMS critical section. The previous
- * level is returned in _level.
+ * level is returned in _isr_cookie.
*/
#define loc_string(a,b) a " (" #b ")\n"
+#define _CPU_MSR_Value( _msr_value ) \
+ do { \
+ _msr_value = 0; \
+ asm volatile ("mfmsr %0" : "=&r" ((_msr_value)) : "0" ((_msr_value))); \
+ } while (0)
+
+#define _CPU_MSR_SET( _msr_value ) \
+{ asm volatile ("mtmsr %0" : "=&r" ((_msr_value)) : "0" ((_msr_value))); }
+
+#if 0
#define _CPU_ISR_Disable( _isr_cookie ) \
- { \
+ { register unsigned int _disable_mask = PPC_MSR_DISABLE_MASK; \
+ _isr_cookie = 0; \
+ asm volatile (
+ "mfmsr %0" : \
+ "=r" ((_isr_cookie)) : \
+ "0" ((_isr_cookie)) \
+ ); \
+ asm volatile (
+ "andc %1,%0,%1" : \
+ "=r" ((_isr_cookie)), "=&r" ((_disable_mask)) : \
+ "0" ((_isr_cookie)), "1" ((_disable_mask)) \
+ ); \
+ asm volatile (
+ "mtmsr %1" : \
+ "=r" ((_disable_mask)) : \
+ "0" ((_disable_mask)) \
+ ); \
+ }
+#endif
+
+#define _CPU_ISR_Disable( _isr_cookie ) \
+ { register unsigned int _disable_mask = PPC_MSR_DISABLE_MASK; \
+ _isr_cookie = 0; \
asm volatile ( \
"mfmsr %0; andc %1,%0,%1; mtmsr %1" : \
- "=&r" ((_isr_cookie)) : "r" ((PPC_MSR_DISABLE_MASK)) \
+ "=&r" ((_isr_cookie)), "=&r" ((_disable_mask)) : \
+ "0" ((_isr_cookie)), "1" ((_disable_mask)) \
); \
}
+
+#define _CPU_Data_Cache_Block_Flush( _address ) \
+ do { register void *__address = (_address); \
+ register unsigned32 _zero = 0; \
+ asm volatile ( "dcbf %0,%1" : \
+ "=r" (_zero), "=r" (__address) : \
+ "0" (_zero), "1" (__address) \
+ ); \
+ } while (0)
+
+
/*
* Enable interrupts to the previous level (returned by _CPU_ISR_Disable).
* This indicates the end of an RTEMS critical section. The parameter
- * _level is not modified.
+ * _isr_cookie is not modified.
*/
#define _CPU_ISR_Enable( _isr_cookie ) \
{ \
asm volatile ( "mtmsr %0" : \
- "=&r" ((_isr_cookie)) : "0" ((_isr_cookie))); \
+ "=r" ((_isr_cookie)) : \
+ "0" ((_isr_cookie))); \
}
/*
- * This temporarily restores the interrupt to _level before immediately
+ * This temporarily restores the interrupt to _isr_cookie before immediately
* disabling them again. This is used to divide long RTEMS critical
- * sections into two or more parts. The parameter _level is not
- * modified.
+ * sections into two or more parts. The parameter _isr_cookie is not
+ * modified.
+ *
+ * NOTE: The version being used is not very optimized but it does
+ * not trip a problem in gcc where the disable mask does not
+ * get loaded. Check this for future (post 10/97 gcc versions.
*/
#define _CPU_ISR_Flash( _isr_cookie ) \
- { \
+ { register unsigned int _disable_mask = PPC_MSR_DISABLE_MASK; \
asm volatile ( \
- "mtmsr %0; andc %1,%0,%1; mtmsr %1" : \
- "=r" ((_isr_cookie)) : \
- "r" ((PPC_MSR_DISABLE_MASK)), "0" ((_isr_cookie)) \
- ); \
+ "mtmsr %0; andc %1,%0,%1; mtmsr %1" : \
+ "=r" ((_isr_cookie)), "=r" ((_disable_mask)) : \
+ "0" ((_isr_cookie)), "1" ((_disable_mask)) \
+ ); \
}
/*
@@ -661,20 +744,53 @@ SCORE_EXTERN struct {
* via the rtems_task_mode directive.
*/
-#define _CPU_ISR_Set_level( new_level ) \
- { \
- register unsigned32 tmp = 0; \
- asm volatile ( \
- "mfmsr %0; andc %0,%0,%1; and %2, %2, %1; or %0, %0, %2; mtmsr %0" : \
- "=r" ((tmp)) : \
- "r" ((PPC_MSR_DISABLE_MASK)), "r" ((_CPU_msrs[new_level])), "0" ((tmp)) \
- ); \
- }
+unsigned32 _CPU_ISR_Calculate_level(
+ unsigned32 new_level
+);
+void _CPU_ISR_Set_level(
+ unsigned32 new_level
+);
+
unsigned32 _CPU_ISR_Get_level( void );
+void _CPU_ISR_install_raw_handler(
+ unsigned32 vector,
+ proc_ptr new_handler,
+ proc_ptr *old_handler
+);
+
/* end of ISR handler macros */
+/*
+ * Simple spin delay in microsecond units for device drivers.
+ * This is very dependent on the clock speed of the target.
+ */
+
+#define CPU_Get_timebase_low( _value ) \
+ asm volatile( "mftb %0" : "=r" (_value) )
+
+#define delay( _microseconds ) \
+ do { \
+ unsigned32 start, ticks, now; \
+ CPU_Get_timebase_low( start ) ; \
+ ticks = (_microseconds) * Cpu_table.clicks_per_usec; \
+ do \
+ CPU_Get_timebase_low( now ) ; \
+ while (now - start < ticks); \
+ } while (0)
+
+#define delay_in_bus_cycles( _cycles ) \
+ do { \
+ unsigned32 start, now; \
+ CPU_Get_timebase_low( start ); \
+ do \
+ CPU_Get_timebase_low( now ); \
+ while (now - start < (_cycles)); \
+ } while (0)
+
+
+
/* Context handler macros */
/*
@@ -691,63 +807,18 @@ unsigned32 _CPU_ISR_Get_level( void );
* This routine generally does not set any unnecessary register
* in the context. The state of the "general data" registers is
* undefined at task start time.
+ *
+ * NOTE: Implemented as a subroutine for the SPARC port.
*/
-#if PPC_ABI == PPC_ABI_POWEROPEN
-#define _CPU_Context_Initialize( _the_context, _stack_base, _size, \
- _isr, _entry_point, _is_fp ) \
- { \
- unsigned32 sp, *desc; \
- \
- sp = ((unsigned32)_stack_base) + (_size) - 56; \
- *((unsigned32 *)sp) = 0; \
- \
- desc = (unsigned32 *)_entry_point; \
- \
- (_the_context)->msr = PPC_MSR_INITIAL | \
- _CPU_msrs[ _isr ]; \
- (_the_context)->pc = desc[0]; \
- (_the_context)->gpr1 = sp; \
- (_the_context)->gpr2 = desc[1]; \
- }
-#endif
-#if PPC_ABI == PPC_ABI_SVR4
-#define _CPU_Context_Initialize( _the_context, _stack_base, _size, \
- _isr, _entry_point ) \
- { \
- unsigned32 sp, r13; \
- \
- sp = ((unsigned32)_stack_base) + (_size) - 8; \
- *((unsigned32 *)sp) = 0; \
- \
- asm volatile ("mr %0, 13" : "=r" ((r13))); \
- \
- (_the_context->msr) = PPC_MSR_INITIAL | \
- _CPU_msrs[ _isr ]; \
- (_the_context->pc) = _entry_point; \
- (_the_context->gpr1) = sp; \
- (_the_context->gpr13) = r13; \
- }
-#endif
-#if PPC_ABI == PPC_ABI_EABI
-#define _CPU_Context_Initialize( _the_context, _stack_base, _size, \
- _isr, _entry_point ) \
- { \
- unsigned32 sp, r2, r13; \
- \
- sp = ((unsigned32)_stack_base) + (_size) - 8; \
- *((unsigned32 *)sp) = 0; \
- \
- asm volatile ("mr %0,2; mr %1,13" : "=r" ((r2)), "=r" ((r13))); \
- \
- (_the_context)->msr = PPC_MSR_INITIAL | \
- _CPU_msrs[ _isr ]; \
- (_the_context->pc) = _entry_point; \
- (_the_context->gpr1) = sp; \
- (_the_context->gpr2) = r2; \
- (_the_context->gpr13) = r13; \
- }
-#endif
+void _CPU_Context_Initialize(
+ Context_Control *the_context,
+ unsigned32 *stack_base,
+ unsigned32 size,
+ unsigned32 new_level,
+ void *entry_point,
+ boolean is_fp
+);
/*
* This routine is responsible for somehow restarting the currently
@@ -911,7 +982,7 @@ extern const unsigned32 _CPU_msrs[4];
void _CPU_Initialize(
rtems_cpu_table *cpu_table,
- void (*thread_dispatch)
+ void (*thread_dispatch)
);
/*
@@ -951,7 +1022,7 @@ void _CPU_Context_switch(
/*
* _CPU_Context_restore
*
- * This routine is generally used only to restart self in an
+ * This routine is generallu used only to restart self in an
* efficient manner. It may simply be a label in _CPU_Context_switch.
*
* NOTE: May be unnecessary to reload some registers.