Skip to content
Snippets Groups Projects
Commit 3d3724ac authored by wlott's avatar wlott
Browse files

Initial revision

parent a1279580
No related branches found
No related tags found
No related merge requests found
#include <machine/asm_linkage.h>
#include <machine/psl.h>
#define LANGUAGE_ASSEMBLY
#include "lispregs.h"
#include "lisp.h"
#include "globals.h"
#define load(sym, reg) \
sethi %hi(NAME(sym)), reg; ld [reg+%lo(NAME(sym))], reg
#define store(reg, sym) \
sethi %hi(NAME(sym)), L0; st reg, [L0+%lo(NAME(sym))]
.seg "text"
.global NAME(call_into_lisp)
NAME(call_into_lisp):
save %sp, -(SA(MINFRAME)+SA(4)), %sp
/* Save the return address. */
st %i7, [%fp-4]
/* Clear the descriptor regs. */
mov ZERO, A0
mov ZERO, A1
mov ZERO, A2
mov ZERO, A3
mov ZERO, A4
mov ZERO, A5
mov ZERO, OCFP
mov ZERO, LRA
mov ZERO, L2
mov ZERO, CODE
/* Establish NIL */
set NIL, NULLREG
/* No longer in foreign function call. */
/* Note: the atomic flag should still be set. */
sethi %hi(NAME(foreign_function_call_active)), NL0
st ZERO, [NL0+%lo(NAME(foreign_function_call_active))]
/* Load the rest of lisp state. */
load(current_dynamic_space_free_pointer, ALLOC)
load(current_binding_stack_pointer, BSP)
load(current_control_stack_pointer, CSP)
load(current_control_frame_pointer, OCFP)
/* No longer atomic. */
sethi %hi(PSEUDO_ATOMIC_ATOMIC+SYMBOL_VALUE_OFFSET), NL0
st ZERO, [NL0+%lo(PSEUDO_ATOMIC_ATOMIC+SYMBOL_VALUE_OFFSET)]
/* Were we interrupted? */
sethi %hi(PSEUDO_ATOMIC_INTERRUPTED+SYMBOL_VALUE_OFFSET), NL0
ld [NL0+%lo(PSEUDO_ATOMIC_INTERRUPTED+SYMBOL_VALUE_OFFSET)], NL0
tst NL0
beq 1f
nop
/* Yep, we were. */
unimp trap_PendingInterrupt
1:
/* Pass in the args. */
/* Note: CNAME and LEXENV already hold the correct values. */
mov %i2, CFP
sll %i3, 2, NARGS
ld [CFP+0], A0
ld [CFP+4], A1
ld [CFP+8], A2
ld [CFP+12], A3
ld [CFP+16], A4
ld [CFP+20], A5
/* Calculate LRA */
set lra + type_OtherPointer, LRA
/* Indirect closure */
ld [LEXENV+CLOSURE_FUNCTION_OFFSET], CODE
jmp CODE+FUNCTION_HEADER_CODE_OFFSET
nop
.align 8
lra:
.word type_ReturnPcHeader
/* Blow off any extra values. */
mov OCFP, CSP
nop
/* Return the one value. */
mov A0, %i0
/* Turn on pseudo_atomic */
set 1, NL1
sethi %hi(PSEUDO_ATOMIC_ATOMIC+SYMBOL_VALUE_OFFSET), L0
st NL1, [L0+%lo(PSEUDO_ATOMIC_ATOMIC+SYMBOL_VALUE_OFFSET)]
/* Store LISP state */
store(ALLOC,current_dynamic_space_free_pointer)
store(BSP,current_binding_stack_pointer)
store(CSP,current_control_stack_pointer)
store(CFP,current_control_frame_pointer)
/* No longer in Lisp. */
store(NL1,foreign_function_call_active)
/* Were we interrupted? */
sethi %hi(PSEUDO_ATOMIC_INTERRUPTED+SYMBOL_VALUE_OFFSET), L0
ld [L0+%lo(PSEUDO_ATOMIC_INTERRUPTED+SYMBOL_VALUE_OFFSET)], L0
tst L0
beq 1f
nop
/* Yep, we were. */
unimp trap_PendingInterrupt
1:
/* Back to C we go. */
ld [%fp-4], %i7
ret
restore
.global _call_into_c
_call_into_c:
/* Build a lisp stack frame */
mov CFP, OCFP
mov CSP, CFP
add CSP, 32, CSP
st OCFP, [CFP]
st LIP, [CFP+4]
st CODE, [CFP+8]
/* Turn on pseudo-atomic. */
set 1, NL1
sethi %hi(PSEUDO_ATOMIC_ATOMIC+SYMBOL_VALUE_OFFSET), L0
st NL1, [L0+%lo(PSEUDO_ATOMIC_ATOMIC+SYMBOL_VALUE_OFFSET)]
/* Store LISP state */
store(ALLOC,current_dynamic_space_free_pointer)
store(BSP,current_binding_stack_pointer)
store(CSP,current_control_stack_pointer)
store(CFP,current_control_frame_pointer)
/* No longer in Lisp. */
store(NL1,foreign_function_call_active)
/* Were we interrupted? */
sethi %hi(PSEUDO_ATOMIC_INTERRUPTED+SYMBOL_VALUE_OFFSET), L0
ld [L0+%lo(PSEUDO_ATOMIC_INTERRUPTED+SYMBOL_VALUE_OFFSET)], L0
tst L0
beq 1f
nop
/* Yep, we were. */
unimp trap_PendingInterrupt
1:
/* Into C we go. */
call CFUNC
nop
/* Re-establish NIL */
set NIL, NULLREG
/* No longer in foreign function call. */
/* Note: the atomic flag should still be set. */
sethi %hi(NAME(foreign_function_call_active)), NL1
st ZERO, [NL1+%lo(NAME(foreign_function_call_active))]
/* Load the rest of lisp state. */
load(current_dynamic_space_free_pointer, ALLOC)
load(current_binding_stack_pointer, BSP)
load(current_control_stack_pointer, CSP)
load(current_control_frame_pointer, CFP)
/* No longer atomic. */
sethi %hi(PSEUDO_ATOMIC_ATOMIC+SYMBOL_VALUE_OFFSET), NL1
st ZERO, [NL1+%lo(PSEUDO_ATOMIC_ATOMIC+SYMBOL_VALUE_OFFSET)]
/* Were we interrupted? */
sethi %hi(PSEUDO_ATOMIC_INTERRUPTED+SYMBOL_VALUE_OFFSET), NL1
ld [NL1+%lo(PSEUDO_ATOMIC_INTERRUPTED+SYMBOL_VALUE_OFFSET)], NL1
tst NL1
beq 1f
nop
/* Yep, we were. */
unimp trap_PendingInterrupt
1:
/* Reset the lisp stack. */
/* Note: OCFP is in one of the locals, it gets preserved across C. */
mov CFP, CSP
mov OCFP, CFP
/* And back into lisp. */
ret
nop
.global _undefined_tramp
.align 8
.byte 0
_undefined_tramp:
.byte 0, 0, type_FunctionHeader
.word _undefined_tramp
.word NIL
.word NIL
.word NIL
unimp trap_Error
/****************************************************************\
We need our own version of sigtramp.
\****************************************************************/
.global __sigtramp, __sigfunc
__sigtramp:
!
! On entry sp points to:
! 0 - 63: window save area
! 64: signal number
! 68: signal code
! 72: pointer to sigcontext
! 76: addr parameter
!
! A sigcontext looks like:
! 00: on signal stack flag
! 04: old signal mask
! 08: old sp
! 12: old pc
! 16: old npc
! 20: old psr
! 24: old g1
! 28: old o0
!
! Out sigcontext has the following added:
! 32: regs[32]
! 160: fpregs[32]
! 288: y
! 292: fsr
!
! After we allocate space for the new sigcontext, the stack looks like:
! < window save area, etc >
! SCOFF: start of generic sigcontext.
! IREGSOFF: start of lisp sigcontext.
! SIGNUM: signal number
! CODE: signal code
! OSCP: pointer to orig sigcontext
! ADDR: addr parameter (which isn't supplied by the kernel)
#define SCOFF SA(MINFRAME)
#define IREGSOFF SCOFF+32
#define FPREGSOFF IREGSOFF+(32*4)
#define YOFF FPREGSOFF+(32*4)
#define FSROFF YOFF+4
#define SCSIZE SA(32+(32*4)+(32*4)+4+4)
#define SIGNUMOFF SCOFF+SCSIZE
#define CODEOFF SCOFF+SCSIZE+4
#define ADDROFF SCOFF+SCSIZE+12
#define OSCOFF ADDROFF
! Allocate space for our sigcontext.
sub %sp, SCSIZE+SA(MINFRAME)-64, %sp
! Save integer registers.
! Note: the globals and outs are good, but the locals and ins have
! been trashed. But luckly, they have been saved on the stack.
! So we need to extract the saved stack pointer from the sigcontext
! to determine where they are.
std %0, [%sp+IREGSOFF]
std %2, [%sp+IREGSOFF+8]
std %4, [%sp+IREGSOFF+16]
std %6, [%sp+IREGSOFF+24]
std %o0, [%sp+IREGSOFF+32]
ld [%sp + OSCOFF+8], %o0
std %o2, [%sp+IREGSOFF+40]
std %o4, [%sp+IREGSOFF+48]
st %o0, [%sp+IREGSOFF+56]
st %o7, [%sp+IREGSOFF+60]
ldd [%o0], %16
ldd [%o0+8], %18
ldd [%o0+16], %20
ldd [%o0+24], %22
ldd [%o0+32], %24
ldd [%o0+40], %26
ldd [%o0+48], %28
ldd [%o0+56], %30
std %16, [%sp+IREGSOFF+64]
std %18, [%sp+IREGSOFF+72]
std %20, [%sp+IREGSOFF+80]
std %22, [%sp+IREGSOFF+88]
std %24, [%sp+IREGSOFF+96]
std %26, [%sp+IREGSOFF+104]
std %28, [%sp+IREGSOFF+112]
std %30, [%sp+IREGSOFF+120]
! Copy the original sigcontext down to our sigcontext.
ld [%sp + OSCOFF], %l0
ld [%sp + OSCOFF+4], %l1
ld [%sp + OSCOFF+8], %l2
ld [%sp + OSCOFF+12], %l3
ld [%sp + OSCOFF+16], %l4
ld [%sp + OSCOFF+20], %l5
ld [%sp + OSCOFF+24], %l6
ld [%sp + OSCOFF+28], %l7
std %l0, [%sp+SCOFF]
std %l2, [%sp+SCOFF+8]
std %l4, [%sp+SCOFF+16]
std %l6, [%sp+SCOFF+24]
! Check to see if we need to save the fp regs.
set PSR_EF, %l0
mov %y, %l2 ! save y
btst %l0, %l5 ! is FPU enabled?
bz 1f ! if not skip FPU save
st %l2, [%sp + YOFF]
std %f0, [%sp + FPREGSOFF+(0*4)] ! save all fpu registers.
std %f2, [%sp + FPREGSOFF+(2*4)]
std %f4, [%sp + FPREGSOFF+(4*4)]
std %f6, [%sp + FPREGSOFF+(6*4)]
std %f8, [%sp + FPREGSOFF+(8*4)]
std %f10, [%sp + FPREGSOFF+(10*4)]
std %f12, [%sp + FPREGSOFF+(12*4)]
std %f14, [%sp + FPREGSOFF+(14*4)]
std %f16, [%sp + FPREGSOFF+(16*4)]
std %f18, [%sp + FPREGSOFF+(18*4)]
std %f20, [%sp + FPREGSOFF+(20*4)]
std %f22, [%sp + FPREGSOFF+(22*4)]
std %f24, [%sp + FPREGSOFF+(24*4)]
std %f26, [%sp + FPREGSOFF+(26*4)]
std %f28, [%sp + FPREGSOFF+(28*4)]
std %f30, [%sp + FPREGSOFF+(30*4)]
st %fsr, [%sp + FSROFF] ! save old fsr
1:
ld [%sp + SIGNUMOFF], %o0 ! get signal number
set __sigfunc, %g1 ! get array of function ptrs
sll %o0, 2, %g2 ! scale signal number for index
ld [%g1 + %g2], %g1 ! get func
ld [%sp + CODEOFF], %o1 ! get code
add %sp, SCOFF, %o2 ! compute scp
call %g1 ! (*_sigfunc[sig])(sig,code,scp,addr)
ld [%sp + ADDROFF], %o3 ! get addr
! Recompute scp, and call into _sigreturn
add %sp, SCOFF, %o0
.global _sigreturn
_sigreturn:
! Move values we can't restore directory into real sigcontext.
ld [%o0+32+(4*1)], %l0 ! g1
ld [%o0+32+(4*8)], %l1 ! o0
ld [%o0+32+(4*14)], %l2 ! sp
st %l0, [%o0+24]
st %l1, [%o0+28]
st %l2, [%o0+8]
ld [%o0 + 20], %l2 ! get psr
set PSR_EF, %l0
ld [%o0 + 288], %l1 ! restore y
btst %l0, %l2 ! is FPU enabled?
bz 2f ! if not skip FPU restore
mov %l1, %y
ldd [%o0 + 160+(0*4)], %f0 ! restore all fpu registers.
ldd [%o0 + 160+(2*4)], %f2
ldd [%o0 + 160+(4*4)], %f4
ldd [%o0 + 160+(6*4)], %f6
ldd [%o0 + 160+(8*4)], %f8
ldd [%o0 + 160+(10*4)], %f10
ldd [%o0 + 160+(12*4)], %f12
ldd [%o0 + 160+(14*4)], %f14
ldd [%o0 + 160+(16*4)], %f16
ldd [%o0 + 160+(18*4)], %f18
ldd [%o0 + 160+(20*4)], %f20
ldd [%o0 + 160+(22*4)], %f22
ldd [%o0 + 160+(24*4)], %f24
ldd [%o0 + 160+(26*4)], %f26
ldd [%o0 + 160+(28*4)], %f28
ldd [%o0 + 160+(30*4)], %f30
ld [%o0 + 160+(32*4)], %fsr ! restore old fsr
2:
! Restore the integer regs.
ldd [%o0 + 32+(2*4)], %2
ldd [%o0 + 32+(4*4)], %4
ldd [%o0 + 32+(6*4)], %6
ld [%o0 + 32+(9*4)], %9
ldd [%o0 + 32+(10*4)], %10
ldd [%o0 + 32+(12*4)], %12
ld [%o0 + 32+(15*4)], %15
ldd [%o0 + 32+(16*4)], %16
ldd [%o0 + 32+(18*4)], %18
ldd [%o0 + 32+(20*4)], %20
ldd [%o0 + 32+(22*4)], %22
ldd [%o0 + 32+(24*4)], %24
ldd [%o0 + 32+(26*4)], %26
ldd [%o0 + 32+(28*4)], %28
ldd [%o0 + 32+(30*4)], %30
set 139, %g1 ! sigcleanup system call
t 0
unimp 0 ! just in case it returns
/*NOTREACHED*/
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment