summaryrefslogtreecommitdiffstats
path: root/cpukit/score/cpu/sparc/syscall.S
diff options
context:
space:
mode:
Diffstat (limited to 'cpukit/score/cpu/sparc/syscall.S')
-rw-r--r--cpukit/score/cpu/sparc/syscall.S295
1 files changed, 295 insertions, 0 deletions
diff --git a/cpukit/score/cpu/sparc/syscall.S b/cpukit/score/cpu/sparc/syscall.S
new file mode 100644
index 0000000000..da0ee43889
--- /dev/null
+++ b/cpukit/score/cpu/sparc/syscall.S
@@ -0,0 +1,295 @@
+/*
+ * systrap.S
+ *
+ * This file contains emulated system calls using software trap 0.
+ * The following calls are supported:
+ *
+ * + SYS_exit (halt)
+ * + SYS_irqdis (disable interrupts)
+ * + SYS_irqset (set interrupt level)
+ *
+ * COPYRIGHT:
+ *
+ * COPYRIGHT (c) 1995. European Space Agency.
+ * Copyright (c) 2016, 2017 embedded brains GmbH
+ *
+ * This terms of the RTEMS license apply to this file.
+ *
+ */
+
+#include <rtems/asm.h>
+#include <rtems/score/cpuimpl.h>
+#include <rtems/score/percpu.h>
+#include "syscall.h"
+
+ .section ".text"
+ /*
+ * system call - halt
+ *
+ * On entry:
+ *
+ * l0 = psr (from trap table)
+ * l1 = pc
+ * l2 = npc
+ * g1 = system call id (1)
+ *
+ * System Call 1 (exit):
+ * g2 = additional exit code 1
+ * g3 = additional exit code 2
+ */
+
+ PUBLIC(syscall)
+
+SYM(syscall):
+ ta 0 ! syscall 1, halt with %g1,%g2,%g3 info
+
+ PUBLIC(sparc_syscall_exit)
+
+SYM(sparc_syscall_exit):
+
+ mov SYS_exit, %g1
+ mov %o0, %g2 ! Additional exit code 1
+ mov %o1, %g3 ! Additional exit code 2
+ ta SPARC_SWTRAP_SYSCALL
+
+ /*
+ * system call - Interrupt Disable
+ *
+ * On entry:
+ *
+ * l0 = psr (from trap table)
+ * l1 = pc
+ * l2 = npc
+ * l3 = psr | SPARC_PSR_PIL_MASK
+ *
+ * On exit:
+ * g1 = old psr (to user)
+ */
+
+.align 32 ! Align to 32-byte cache-line
+ PUBLIC(syscall_irqdis)
+
+SYM(syscall_irqdis):
+ mov %l3, %psr ! Set PSR. Write delay 3 instr
+ or %l0, SPARC_PSR_ET_MASK, %g1 ! return old PSR with ET=1
+ nop ! PSR write delay
+ jmp %l2 ! Return to after TA 9.
+ rett %l2 + 4
+
+ /*
+ * system call - Interrupt Enable
+ *
+ * On entry:
+ *
+ * l0 = psr (from trap table)
+ * l1 = pc
+ * l2 = npc
+ * l3 = psr & ~0x0f00
+ * g1 = new PIL to write (from user)
+ */
+
+.align 32 ! Align to 32-byte cache-line
+ PUBLIC(syscall_irqen)
+
+SYM(syscall_irqen):
+ and %g1, SPARC_PSR_PIL_MASK, %l4 ! %l4 = (%g1 & 0xf00)
+ wr %l3, %l4, %psr ! PSR = (PSR & ~0xf00) ^ %l4
+ nop; nop ! PSR write delay;
+ jmp %l2 ! Return to after TA 10.
+ rett %l2 + 4
+
+#if defined(SPARC_USE_SYNCHRONOUS_FP_SWITCH)
+ /*
+ * system call - Interrupt disable and set PSR[EF] according to caller
+ * specified %g1
+ *
+ * On entry:
+ *
+ * g1 = the desired PSR[EF] value (from caller)
+ * l0 = psr (from trap table)
+ * l1 = pc
+ * l2 = npc
+ * l3 = psr | SPARC_PSR_PIL_MASK
+ *
+ * On exit:
+ * g1 = old psr (to user)
+ */
+
+.align 32 ! Align to 32-byte cache-line
+ PUBLIC(syscall_irqdis_fp)
+
+SYM(syscall_irqdis_fp):
+ /*
+ * We cannot use an intermediate value for operations with the PSR[EF]
+ * bit since they use a 13-bit sign extension and PSR[EF] is bit 12.
+ */
+ sethi %hi(SPARC_PSR_EF_MASK), %l4
+
+ andn %l3, %l4, %l3 ! Clear PSR[EF]
+ and %g1, %l4, %g1 ! Select PSR[EF] only from %g1
+ or %l3, %g1, %l3 ! Set PSR[EF] according to %g1
+ mov %l3, %psr ! Set PSR. Write delay 3 instr
+ or %l0, SPARC_PSR_ET_MASK, %g1 ! return old PSR with ET=1
+ nop ! PSR write delay
+ jmp %l2 ! Return to after TA 9.
+ rett %l2 + 4
+#endif
+
+#if defined(SPARC_USE_LAZY_FP_SWITCH)
+
+ /*
+ * system call - Perform a lazy floating point switch
+ *
+ * On entry:
+ *
+ * l0 = psr (from trap table)
+ * l1 = pc
+ * l2 = npc
+ * l3 = SPARC_PSR_EF_MASK
+ */
+
+.align 32 ! Align to 32-byte cache-line
+ PUBLIC(syscall_lazy_fp_switch)
+
+SYM(syscall_lazy_fp_switch):
+ ld [%g6 + PER_CPU_OFFSET_EXECUTING], %l4
+ ld [%g6 + PER_CPU_ISR_NEST_LEVEL], %l5
+ ld [%l4 + %lo(SPARC_THREAD_CONTROL_FP_CONTEXT_OFFSET)], %l6
+ ld [%g6 + SPARC_PER_CPU_FP_OWNER_OFFSET], %l7
+
+ /* Ensure that we are not in interrupt context */
+ cmp %l5, 0
+ bne .Lillegal_use_of_floating_point_unit
+ or %l0, %l3, %l0
+
+ /* Ensure that we are a proper floating point thread */
+ cmp %l6, 0
+ be .Lillegal_use_of_floating_point_unit
+ ld [%l4 + %lo(SPARC_THREAD_CONTROL_REGISTERS_FP_CONTEXT_OFFSET)], %l6
+
+ /* Set PSR[EF] to 1, PSR write delay 3 instructions! */
+ mov %l0, %psr
+
+ /*
+ * Check if there is a floating point owner. We have to check this
+ * here, since the floating point owner may have been deleted in the
+ * meantime. Save the floating point context if necessary.
+ */
+ cmp %l7, 0
+ be .Lfp_save_done
+ nop
+ ld [%l7 + %lo(SPARC_THREAD_CONTROL_FP_CONTEXT_OFFSET)], %l5
+ std %f0, [%l5 + SPARC_FP_CONTEXT_OFFSET_F0_F1]
+ SPARC_LEON3FT_B2BST_NOP
+ std %f2, [%l5 + SPARC_FP_CONTEXT_OFFSET_F2_F3]
+ SPARC_LEON3FT_B2BST_NOP
+ std %f4, [%l5 + SPARC_FP_CONTEXT_OFFSET_F4_F5]
+ SPARC_LEON3FT_B2BST_NOP
+ std %f6, [%l5 + SPARC_FP_CONTEXT_OFFSET_F6_F7]
+ SPARC_LEON3FT_B2BST_NOP
+ std %f8, [%l5 + SPARC_FP_CONTEXT_OFFSET_F8_F9]
+ SPARC_LEON3FT_B2BST_NOP
+ std %f10, [%l5 + SPARC_FP_CONTEXT_OFFSET_F10_F11]
+ SPARC_LEON3FT_B2BST_NOP
+ std %f12, [%l5 + SPARC_FP_CONTEXT_OFFSET_F12_F13]
+ SPARC_LEON3FT_B2BST_NOP
+ std %f14, [%l5 + SPARC_FP_CONTEXT_OFFSET_F14_F15]
+ SPARC_LEON3FT_B2BST_NOP
+ std %f16, [%l5 + SPARC_FP_CONTEXT_OFFSET_F16_F17]
+ SPARC_LEON3FT_B2BST_NOP
+ std %f18, [%l5 + SPARC_FP_CONTEXT_OFFSET_F18_F19]
+ SPARC_LEON3FT_B2BST_NOP
+ std %f20, [%l5 + SPARC_FP_CONTEXT_OFFSET_F20_F21]
+ SPARC_LEON3FT_B2BST_NOP
+ std %f22, [%l5 + SPARC_FP_CONTEXT_OFFSET_F22_F23]
+ SPARC_LEON3FT_B2BST_NOP
+ std %f24, [%l5 + SPARC_FP_CONTEXT_OFFSET_F24_F25]
+ SPARC_LEON3FT_B2BST_NOP
+ std %f26, [%l5 + SPARC_FP_CONTEXT_OFFSET_F26_F27]
+ SPARC_LEON3FT_B2BST_NOP
+ std %f28, [%l5 + SPARC_FP_CONTEXT_OFFSET_F28_F29]
+ SPARC_LEON3FT_B2BST_NOP
+ std %f30, [%l5 + SPARC_FP_CONTEXT_OFFSET_F30_F31]
+ SPARC_LEON3FT_B2BST_NOP
+ st %fsr, [%l5 + SPARC_FP_CONTEXT_OFFSET_FSR]
+ SPARC_LEON3FT_B2BST_NOP
+ st %g0, [%g6 + SPARC_PER_CPU_FP_OWNER_OFFSET]
+ SPARC_LEON3FT_B2BST_NOP
+ st %l5, [%l7 + %lo(SPARC_THREAD_CONTROL_REGISTERS_FP_CONTEXT_OFFSET)]
+
+.Lfp_save_done:
+
+ /* Restore the floating point context if necessary */
+ cmp %l6, 0
+ be .Lfp_restore_done
+ st %g0, [%l4 + %lo(SPARC_THREAD_CONTROL_REGISTERS_FP_CONTEXT_OFFSET)]
+ ldd [%l6 + SPARC_FP_CONTEXT_OFFSET_F0_F1], %f0
+ ldd [%l6 + SPARC_FP_CONTEXT_OFFSET_F2_F3], %f2
+ ldd [%l6 + SPARC_FP_CONTEXT_OFFSET_F4_F5], %f4
+ ldd [%l6 + SPARC_FP_CONTEXT_OFFSET_F6_F7], %f6
+ ldd [%l6 + SPARC_FP_CONTEXT_OFFSET_F8_F9], %f8
+ ldd [%l6 + SPARC_FP_CONTEXT_OFFSET_F10_F11], %f10
+ ldd [%l6 + SPARC_FP_CONTEXT_OFFSET_F12_F13], %f12
+ ldd [%l6 + SPARC_FP_CONTEXT_OFFSET_F14_F15], %f14
+ ldd [%l6 + SPARC_FP_CONTEXT_OFFSET_F16_F17], %f16
+ ldd [%l6 + SPARC_FP_CONTEXT_OFFSET_F18_F19], %f18
+ ldd [%l6 + SPARC_FP_CONTEXT_OFFSET_F20_F21], %f20
+ ldd [%l6 + SPARC_FP_CONTEXT_OFFSET_F22_F23], %f22
+ ldd [%l6 + SPARC_FP_CONTEXT_OFFSET_F24_F25], %f24
+ ldd [%l6 + SPARC_FP_CONTEXT_OFFSET_F26_F27], %f26
+ ldd [%l6 + SPARC_FP_CONTEXT_OFFSET_F28_F29], %f28
+ ldd [%l6 + SPARC_FP_CONTEXT_OFFSET_F30_F31], %f30
+ ld [%l6 + SPARC_FP_CONTEXT_OFFSET_FSR], %fsr
+
+.Lfp_restore_done:
+
+ /* Now, retry the floating point instruction with PSR[EF] == 1 */
+ jmp %l1
+ rett %l1 + 4
+
+.Lillegal_use_of_floating_point_unit:
+
+ sethi %hi(_Internal_error), %l1
+ or %l1, %lo(_Internal_error), %l1
+ mov 38, %i0
+ jmp %l1
+ rett %l1 + 4
+#endif
+
+#if defined(RTEMS_PARAVIRT)
+
+ PUBLIC(_SPARC_Get_PSR)
+
+SYM(_SPARC_Get_PSR):
+
+ retl
+ rd %psr, %o0
+
+ PUBLIC(_SPARC_Set_PSR)
+
+SYM(_SPARC_Set_PSR):
+
+ mov %o0, %psr
+ nop
+ nop
+ nop
+ retl
+ nop
+
+ PUBLIC(_SPARC_Get_TBR)
+
+SYM(_SPARC_Get_TBR):
+
+ retl
+ rd %tbr, %o0
+
+ PUBLIC(_SPARC_Set_TBR)
+
+SYM(_SPARC_Set_TBR):
+
+ retl
+ wr %o0, 0, %tbr
+
+#endif /* defined(RTEMS_PARAVIRT) */
+
+/* end of file */