summaryrefslogtreecommitdiffstats
path: root/c/src/exec/score/cpu/sparc/cpu_asm.s
diff options
context:
space:
mode:
Diffstat (limited to 'c/src/exec/score/cpu/sparc/cpu_asm.s')
-rw-r--r--c/src/exec/score/cpu/sparc/cpu_asm.s328
1 files changed, 328 insertions, 0 deletions
diff --git a/c/src/exec/score/cpu/sparc/cpu_asm.s b/c/src/exec/score/cpu/sparc/cpu_asm.s
new file mode 100644
index 0000000000..d1e275ca3f
--- /dev/null
+++ b/c/src/exec/score/cpu/sparc/cpu_asm.s
@@ -0,0 +1,328 @@
+/* cpu_asm.s
+ *
+ * This file contains the basic algorithms for all assembly code used
+ * in an specific CPU port of RTEMS. These algorithms must be implemented
+ * in assembly language
+ *
+ * $Id$
+ */
+
+#include <asm.h>
+#include <rtems/score/cpu.h>
+
+/*
+ * _CPU_Context_save_fp
+ *
+ * This routine is responsible for saving the FP context
+ * at *fp_context_ptr. If the point to load the FP context
+ * from is changed then the pointer is modified by this routine.
+ *
+ * Sometimes a macro implementation of this is in cpu.h which dereferences
+ * the ** and a similarly named routine in this file is passed something
+ * like a (Context_Control_fp *). The general rule on making this decision
+ * is to avoid writing assembly language.
+ *
+ * void _CPU_Context_save_fp(
+ * void **fp_context_ptr
+ * )
+ * {
+ * }
+ */
+
+ .align 4
+ PUBLIC(_CPU_Context_save_fp)
+SYM(_CPU_Context_save_fp):
+ save %sp,-104,%sp
+ ld [%i0],%l0
+ std %f0,[%l0+FO_F1_OFFSET]
+ std %f2,[%l0+F2_F3_OFFSET]
+ std %f4,[%l0+F4_F5_OFFSET]
+ std %f6,[%l0+F6_F7_OFFSET]
+ std %f8,[%l0+F8_F9_OFFSET]
+ std %f10,[%l0+F1O_F11_OFFSET]
+ std %f12,[%l0+F12_F13_OFFSET]
+ std %f14,[%l0+F14_F15_OFFSET]
+ std %f16,[%l0+F16_F17_OFFSET]
+ std %f18,[%l0+F18_F19_OFFSET]
+ std %f20,[%l0+F2O_F21_OFFSET]
+ std %f22,[%l0+F22_F23_OFFSET]
+ std %f24,[%l0+F24_F25_OFFSET]
+ std %f26,[%l0+F26_F27_OFFSET]
+ std %f28,[%l0+F28_F29_OFFSET]
+ std %f30,[%l0+F3O_F31_OFFSET]
+ st %fsr,[%l0+FSR_OFFSET]
+ ret
+ restore
+
+/*
+ * _CPU_Context_restore_fp
+ *
+ * This routine is responsible for restoring the FP context
+ * at *fp_context_ptr. If the point to load the FP context
+ * from is changed then the pointer is modified by this routine.
+ *
+ * Sometimes a macro implementation of this is in cpu.h which dereferences
+ * the ** and a similarly named routine in this file is passed something
+ * like a (Context_Control_fp *). The general rule on making this decision
+ * is to avoid writing assembly language.
+ *
+ * void _CPU_Context_restore_fp(
+ * void **fp_context_ptr
+ * )
+ * {
+ * }
+ */
+
+ .align 4
+ PUBLIC(_CPU_Context_restore_fp)
+SYM(_CPU_Context_restore_fp):
+ save %sp,-104,%sp
+ ld [%o0],%l0
+ ldd [%l0+FO_F1_OFFSET],%f0
+ ldd [%l0+F2_F3_OFFSET],%f2
+ ldd [%l0+F4_F5_OFFSET],%f4
+ ldd [%l0+F6_F7_OFFSET],%f6
+ ldd [%l0+F8_F9_OFFSET],%f8
+ ldd [%l0+F1O_F11_OFFSET],%f10
+ ldd [%l0+F12_F13_OFFSET],%f12
+ ldd [%l0+F14_F15_OFFSET],%f14
+ ldd [%l0+F16_F17_OFFSET],%f16
+ ldd [%l0+F18_F19_OFFSET],%f18
+ ldd [%l0+F2O_F21_OFFSET],%f20
+ ldd [%l0+F22_F23_OFFSET],%f22
+ ldd [%l0+F24_F25_OFFSET],%f24
+ ldd [%l0+F26_F27_OFFSET],%f26
+ ldd [%l0+F28_F29_OFFSET],%f28
+ ldd [%l0+F3O_F31_OFFSET],%f30
+ ld [%l0+FSR_OFFSET],%fsr
+ ret
+ restore
+
+/* _CPU_Context_switch
+ *
+ * This routine performs a normal non-FP context switch.
+ *
+ * void _CPU_Context_switch(
+ * Context_Control *run,
+ * Context_Control *heir
+ * )
+ * {
+ * }
+ */
+
+/* from gcc-2.7.0/config/sparc/sparc.h on register usage */
+
+/* 1 for registers that have pervasive standard uses
+ and are not available for the register allocator.
+ g0 is used for the condition code and not to represent %g0, which is
+ hardwired to 0, so reg 0 is *not* fixed.
+ On non-v9 systems:
+ g1 is free to use as temporary.
+ g2-g4 are reserved for applications. Gcc normally uses them as
+ temporaries, but this can be disabled via the -mno-app-regs option.
+ g5 through g7 are reserved for the operating system.
+ On v9 systems:
+ g1 and g5 are free to use as temporaries.
+ g2-g4 are reserved for applications (the compiler will not normally use
+ them, but they can be used as temporaries with -mapp-regs).
+ g6-g7 are reserved for the operating system.
+ ??? Register 1 is used as a temporary by the 64 bit sethi pattern, so must
+ currently be a fixed register until this pattern is rewritten.
+ Register 1 is also used when restoring call-preserved registers in large
+ stack frames. */
+
+
+ .align 4
+ PUBLIC(_CPU_Context_switch)
+SYM(_CPU_Context_switch):
+ ta 0x03 /* flush registers */
+
+ /* skip g0 */
+ st %g1,[%o0+G1_OFFSET] /* globals */
+ st %g2,[%o0+G2_OFFSET]
+ st %g3,[%o0+G3_OFFSET]
+ st %g4,[%o0+G4_OFFSET]
+ st %g5,[%o0+G5_OFFSET]
+ st %g6,[%o0+G6_OFFSET]
+ st %g7,[%o0+G7_OFFSET]
+
+ st %l0,[%o0+L0_OFFSET]
+ st %l1,[%o0+L1_OFFSET]
+ st %l2,[%o0+L2_OFFSET]
+ st %l3,[%o0+L3_OFFSET]
+ st %l4,[%o0+L4_OFFSET]
+ st %l5,[%o0+L5_OFFSET]
+ st %l6,[%o0+L6_OFFSET]
+ st %l7,[%o0+L7_OFFSET]
+
+ st %i0,[%o0+I0_OFFSET]
+ st %i1,[%o0+I1_OFFSET]
+ st %i2,[%o0+I2_OFFSET]
+ st %i3,[%o0+I3_OFFSET]
+ st %i4,[%o0+I4_OFFSET]
+ st %i5,[%o0+I5_OFFSET]
+ st %i6,[%o0+I6_OFFSET]
+ st %i7,[%o0+I7_OFFSET]
+
+ st %o0,[%o0+O0_OFFSET]
+ st %o1,[%o0+O1_OFFSET]
+ st %o2,[%o0+O2_OFFSET]
+ st %o3,[%o0+O3_OFFSET]
+ st %o4,[%o0+O4_OFFSET]
+ st %o5,[%o0+O5_OFFSET]
+ st %o6,[%o0+O6_OFFSET]
+ st %o7,[%o0+O7_OFFSET]
+
+ rd %psr,%o2
+ st %o2,[%o0+PSR_OFFSET] /* save status register */
+
+ /* enter here with o1 = context to restore */
+ /* o2 = psr */
+restore:
+
+ ld [%o1+PSR_OFFSET],%o0
+ and %o2,31,%o2 /* g1 = cwp */
+ and %o0,-32,%o0 /* o0 = psr w/o cwp */
+ or %o0,%o2,%o2 /* o2 = new psr */
+ wr %o2,0,%psr /* restore status register */
+
+ /* skip g0 */
+ ld [%o1+G1_OFFSET],%g1
+ ld [%o1+G2_OFFSET],%g2
+ ld [%o1+G3_OFFSET],%g3
+ ld [%o1+G4_OFFSET],%g4
+ ld [%o1+G5_OFFSET],%g5
+ ld [%o1+G6_OFFSET],%g6
+ ld [%o1+G7_OFFSET],%g7
+
+ ld [%o1+L0_OFFSET],%l0
+ ld [%o1+L1_OFFSET],%l1
+ ld [%o1+L2_OFFSET],%l2
+ ld [%o1+L3_OFFSET],%l3
+ ld [%o1+L4_OFFSET],%l4
+ ld [%o1+L5_OFFSET],%l5
+ ld [%o1+L6_OFFSET],%l6
+ ld [%o1+L7_OFFSET],%l7
+
+ ld [%o1+I0_OFFSET],%i0
+ ld [%o1+I1_OFFSET],%i1
+ ld [%o1+I2_OFFSET],%i2
+ ld [%o1+I3_OFFSET],%i3
+ ld [%o1+I4_OFFSET],%i4
+ ld [%o1+I5_OFFSET],%i5
+ ld [%o1+I6_OFFSET],%i6
+ ld [%o1+I7_OFFSET],%i7
+
+ ld [%o1+O0_OFFSET],%o0
+ /* do o1 last to avoid destroying heir context pointer */
+ ld [%o1+O2_OFFSET],%o2
+ ld [%o1+O3_OFFSET],%o3
+ ld [%o1+O4_OFFSET],%o4
+ ld [%o1+O5_OFFSET],%o5
+ ld [%o1+O6_OFFSET],%o6
+ ld [%o1+O7_OFFSET],%o7
+
+ ld [%o1+O1_OFFSET],%o1 /* overwrite heir pointer */
+
+ jmp %o7 + 8 /* return */
+ nop /* delay slot */
+
+
+/*
+ * _CPU_Context_restore
+ *
+ * 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.
+ *
+ * void _CPU_Context_restore(
+ * Context_Control *new_context
+ * )
+ * {
+ * }
+ */
+
+ .align 4
+ PUBLIC(_CPU_Context_restore)
+SYM(_CPU_Context_restore):
+ save %sp, -104, %sp /* save a stack frame */
+ ta 0x03 /* flush registers */
+ rd %psr,%o2
+ ba restore
+ mov %i0,%o1 /* in the delay slot */
+
+/* void _ISR_Handler()
+ *
+ * This routine provides the RTEMS interrupt management.
+ *
+ * void _ISR_Handler()
+ * {
+ * }
+ */
+
+ .align 4
+ PUBLIC(_ISR_Handler)
+SYM(_ISR_Handler):
+ ret
+
+ /*
+ * This discussion ignores a lot of the ugly details in a real
+ * implementation such as saving enough registers/state to be
+ * able to do something real. Keep in mind that the goal is
+ * to invoke a user's ISR handler which is written in C and
+ * uses a certain set of registers.
+ *
+ * Also note that the exact order is to a large extent flexible.
+ * Hardware will dictate a sequence for a certain subset of
+ * _ISR_Handler while requirements for setting
+ */
+
+ /*
+ * At entry to "common" _ISR_Handler, the vector number must be
+ * available. On some CPUs the hardware puts either the vector
+ * number or the offset into the vector table for this ISR in a
+ * known place. If the hardware does not give us this information,
+ * then the assembly portion of RTEMS for this port will contain
+ * a set of distinct interrupt entry points which somehow place
+ * the vector number in a known place (which is safe if another
+ * interrupt nests this one) and branches to _ISR_Handler.
+ *
+ * save some or all context on stack
+ * may need to save some special interrupt information for exit
+ *
+ * #if ( CPU_HAS_SOFTWARE_INTERRUPT_STACK == TRUE )
+ * if ( _ISR_Nest_level == 0 )
+ * switch to software interrupt stack
+ * #endif
+ *
+ * _ISR_Nest_level++;
+ *
+ * _Thread_Dispatch_disable_level++;
+ *
+ * (*_ISR_Vector_table[ vector ])( vector );
+ *
+ * --_ISR_Nest_level;
+ *
+ * if ( _ISR_Nest_level )
+ * goto the label "exit interrupt (simple case)"
+ *
+ * #if ( CPU_HAS_SOFTWARE_INTERRUPT_STACK == TRUE )
+ * restore stack
+ * #endif
+ *
+ * if ( !_Context_Switch_necessary )
+ * goto the label "exit interrupt (simple case)"
+ *
+ * if ( !_ISR_Signals_to_thread_executing )
+ * goto the label "exit interrupt (simple case)"
+ *
+ * call _Thread_Dispatch() or prepare to return to _ISR_Dispatch
+ *
+ * prepare to get out of interrupt
+ * return from interrupt (maybe to _ISR_Dispatch)
+ *
+ * LABEL "exit interrupt (simple case):
+ * prepare to get out of interrupt
+ * return from interrupt
+ */