need these too
authorDaniel Barlow <dan@telent.net>
Mon, 18 Mar 2002 17:59:37 +0000 (17:59 +0000)
committerDaniel Barlow <dan@telent.net>
Mon, 18 Mar 2002 17:59:37 +0000 (17:59 +0000)
src/runtime/Config.ppc-linux [new file with mode: 0644]
src/runtime/ppc-arch.c [new file with mode: 0644]
src/runtime/ppc-arch.h [new file with mode: 0644]
src/runtime/ppc-assem.S [new file with mode: 0644]
src/runtime/ppc-linux-os.c [new file with mode: 0644]
src/runtime/ppc-linux-os.h [new file with mode: 0644]
src/runtime/ppc-lispregs.h [new file with mode: 0644]

diff --git a/src/runtime/Config.ppc-linux b/src/runtime/Config.ppc-linux
new file mode 100644 (file)
index 0000000..1dcbc80
--- /dev/null
@@ -0,0 +1,22 @@
+# This software is part of the SBCL system. See the README file for
+# more information.
+#
+# This software is derived from the CMU CL system, which was
+# written at Carnegie Mellon University and released into the
+# public domain. The software is in the public domain and is
+# provided with absolutely no warranty. See the COPYING and CREDITS
+# files for more information.
+
+CFLAGS += -g -Dppc
+LD = ld #-taso
+LINKFLAGS = -v -g # -Wl,-T  -Wl,ld-script.alpha-linux
+NM = nm -p
+
+ASSEM_SRC = ppc-assem.S ldso-stubs.S
+ARCH_SRC = ppc-arch.c
+
+OS_SRC = linux-os.c  ppc-linux-os.c os-common.c 
+LINKFLAGS+=-rdynamic # -static
+OS_LIBS= -ldl
+
+GC_SRC= gc.c
diff --git a/src/runtime/ppc-arch.c b/src/runtime/ppc-arch.c
new file mode 100644 (file)
index 0000000..eac4013
--- /dev/null
@@ -0,0 +1,266 @@
+/*
+
+ $Header$
+
+ This code was written as part of the CMU Common Lisp project at
+ Carnegie Mellon University, and has been placed in the public domain.
+
+*/
+
+#include <stdio.h>
+
+#include "arch.h"
+#include "sbcl.h"
+#include "globals.h"
+#include "validate.h"
+#include "os.h"
+#include "lispregs.h"
+#include "signal.h"
+#include "interrupt.h"
+#include "interr.h"
+
+  /* The header files may not define PT_DAR/PT_DSISR.  This definition
+     is correct for all versions of ppc linux >= 2.0.30
+
+     As of DR2.1u4, MkLinux doesn't pass these registers to signal
+     handlers correctly; a patch is necessary in order to (partially)
+     correct this.
+
+     Even with the patch, the DSISR may not have its 'write' bit set
+     correctly (it tends not to be set if the fault was caused by
+     something other than a protection violation.)
+     
+     Caveat callers.  */
+
+#ifndef PT_DAR
+#define PT_DAR         41
+#endif
+
+#ifndef PT_DSISR
+#define PT_DSISR       42
+#endif
+
+void arch_init()
+{
+}
+
+os_vm_address_t 
+arch_get_bad_addr(int sig, siginfo_t *code, os_context_t *context)
+{
+    unsigned long badinstr;
+    unsigned int *pc =  (unsigned int *)(*os_context_pc_addr(context));
+    int instclass;
+    os_vm_address_t addr;
+    
+    
+    /* Make sure it's not the pc thats bogus, and that it was lisp code */
+    /* that caused the fault. */
+    if ((((unsigned long)pc) & 3) != 0 ||
+       ((pc < READ_ONLY_SPACE_START ||
+         pc >= READ_ONLY_SPACE_START+READ_ONLY_SPACE_SIZE) &&
+        ((lispobj *)pc < current_dynamic_space &&
+         (lispobj *)pc >= current_dynamic_space + DYNAMIC_SPACE_SIZE)))
+       return 0;
+    
+    
+    addr = (os_vm_address_t) (*os_context_register_addr(context,PT_DAR));
+    return addr;
+}
+      
+
+void 
+arch_skip_instruction(os_context_t *context)
+{
+    ((char*)*os_context_pc_addr(context)) +=4; 
+}
+
+unsigned char *
+arch_internal_error_arguments(os_context_t *context)
+{
+    return (unsigned char *)(*os_context_pc_addr(context)+4);
+}
+
+
+boolean 
+arch_pseudo_atomic_atomic(os_context_t *context)
+{
+    return ((*os_context_register_addr(context,reg_ALLOC)) & 4);
+}
+
+#define PSEUDO_ATOMIC_INTERRUPTED_BIAS 0x7f000000
+
+void 
+arch_set_pseudo_atomic_interrupted(os_context_t *context)
+{
+    *os_context_register_addr(context,reg_NL3) 
+       += PSEUDO_ATOMIC_INTERRUPTED_BIAS;
+}
+
+unsigned long 
+arch_install_breakpoint(void *pc)
+{
+    unsigned long *ptr = (unsigned long *)pc;
+    unsigned long result = *ptr;
+    *ptr = (3<<26) | (5 << 21) | trap_Breakpoint;
+    os_flush_icache((os_vm_address_t) pc, sizeof(unsigned long));
+    return result;
+}
+
+void 
+arch_remove_breakpoint(void *pc, unsigned long orig_inst)
+{
+    *(unsigned long *)pc = orig_inst;
+    os_flush_icache((os_vm_address_t) pc, sizeof(unsigned long));
+}
+
+static unsigned long *skipped_break_addr, displaced_after_inst;
+static sigset_t orig_sigmask;
+
+void 
+arch_do_displaced_inst(os_context_t *context,unsigned int orig_inst)
+{
+    /* not sure how we ensure that we get the breakpoint reinstalled
+     * after doing this -dan */
+    unsigned long *pc = (unsigned long *)(*os_context_pc_addr(context));
+    
+    orig_sigmask = *os_context_sigmask_addr(context);
+    sigaddset_blockable(os_context_sigmask_addr(context));
+    
+    *pc = orig_inst;
+    os_flush_icache((os_vm_address_t) pc, sizeof(unsigned long));
+    skipped_break_addr = pc;
+}
+
+static void 
+sigtrap_handler(int signal, siginfo_t *siginfo, os_context_t *context)
+{
+    int badinst;
+    u32 code;
+    sigset_t *mask;
+    mask=(os_context_sigmask_addr(context));
+    sigsetmask(mask); 
+    code=*((u32 *)(*os_context_pc_addr(context)));
+    if (code == ((3 << 26) | (16 << 21) | (reg_ALLOC << 16))) {
+       /* twlti reg_ALLOC,0 - check for deferred interrupt */
+       *os_context_register_addr(context,reg_ALLOC) 
+           -= PSEUDO_ATOMIC_INTERRUPTED_BIAS;
+       arch_skip_instruction(context);
+       /* interrupt or GC was requested in PA; now we're done with the
+          PA section we may as well get around to it */
+       interrupt_handle_pending(context);
+       return;
+       
+    }
+    if ((code >> 16) == ((3 << 10) | (6 << 5))) {
+       /* twllei reg_ZERO,N will always trap if reg_ZERO = 0 */
+       int trap = code & 0x1f, extra = (code >> 5) & 0x1f;
+       
+       switch (trap) {
+       case trap_Halt:
+           fake_foreign_function_call(context);
+           lose("%%primitive halt called; the party is over.\n");
+           
+       case trap_Error:
+       case trap_Cerror:
+           interrupt_internal_error(signal, code, context, trap == trap_Cerror);
+           break;
+           
+       case trap_PendingInterrupt:
+         /* when do we run this branch instead of the twlti code above? */
+           arch_skip_instruction(context);
+           interrupt_handle_pending(context);
+           break;
+           
+       case trap_Breakpoint:
+           handle_breakpoint(signal, code, context);
+           break;
+           
+       case trap_FunEndBreakpoint:
+           *os_context_pc_addr(context)
+               =(int)handle_fun_end_breakpoint(signal, code, context);
+           break;
+           
+       case trap_AfterBreakpoint:
+           *skipped_break_addr = trap_Breakpoint;
+           skipped_break_addr = NULL;
+           *(unsigned long *)*os_context_pc_addr(context) 
+               = displaced_after_inst;
+           *os_context_sigmask_addr(context)= orig_sigmask;
+           os_flush_icache((os_vm_address_t) *os_context_pc_addr(context),
+                           sizeof(unsigned long));
+           break;
+           
+       default:
+           interrupt_handle_now(signal, code, context);
+           break;
+       }
+    }
+    if (((code >> 26) == 3) && (((code >> 21) & 31) == 24)) {
+       interrupt_internal_error(signal, code, context, 0);
+    }
+    
+    interrupt_handle_now(signal, code, context);
+}
+
+
+void arch_install_interrupt_handlers()
+{
+    undoably_install_low_level_interrupt_handler(SIGILL,sigtrap_handler);
+    undoably_install_low_level_interrupt_handler(SIGTRAP,sigtrap_handler);
+}
+
+
+extern lispobj call_into_lisp(lispobj fun, lispobj *args, int nargs);
+
+lispobj funcall0(lispobj function)
+{
+    lispobj *args = current_control_stack_pointer;
+
+    return call_into_lisp(function, args, 0);
+}
+
+lispobj funcall1(lispobj function, lispobj arg0)
+{
+    lispobj *args = current_control_stack_pointer;
+
+    current_control_stack_pointer += 1;
+    args[0] = arg0;
+
+    return call_into_lisp(function, args, 1);
+}
+
+lispobj funcall2(lispobj function, lispobj arg0, lispobj arg1)
+{
+    lispobj *args = current_control_stack_pointer;
+
+    current_control_stack_pointer += 2;
+    args[0] = arg0;
+    args[1] = arg1;
+
+    return call_into_lisp(function, args, 2);
+}
+
+lispobj funcall3(lispobj function, lispobj arg0, lispobj arg1, lispobj arg2)
+{
+    lispobj *args = current_control_stack_pointer;
+
+    current_control_stack_pointer += 3;
+    args[0] = arg0;
+    args[1] = arg1;
+    args[2] = arg2;
+
+    return call_into_lisp(function, args, 3);
+}
+
+void
+ppc_flush_icache(os_vm_address_t address, os_vm_size_t length)
+{
+  os_vm_address_t end = (os_vm_address_t) ((int)(address+length+(32-1)) &~(32-1));
+  extern void ppc_flush_cache_line(os_vm_address_t);
+
+  while (address < end) {
+    ppc_flush_cache_line(address);
+    address += 32;
+  }
+}
diff --git a/src/runtime/ppc-arch.h b/src/runtime/ppc-arch.h
new file mode 100644 (file)
index 0000000..b43e78e
--- /dev/null
@@ -0,0 +1,6 @@
+#ifndef _PPC_ARCH_H
+#define _PPC_ARCH_H
+
+#define ARCH_HAS_LINK_REGISTER
+
+#endif /* _PPC_ARCH_H */
diff --git a/src/runtime/ppc-assem.S b/src/runtime/ppc-assem.S
new file mode 100644 (file)
index 0000000..dc400f2
--- /dev/null
@@ -0,0 +1,416 @@
+#define LANGUAGE_ASSEMBLY
+
+#include "sbcl.h" 
+#include "lispregs.h"
+#include "globals.h"
+
+
+#define FUNCDEF(x)     .text ; \
+                       .align 3 ; \
+                       .type x,@function ; \
+x:
+#define GFUNCDEF(x)    .globl x ; \
+       FUNCDEF(x)
+
+#define SET_SIZE(x) .size x,.-x
+
+/* Load a register from a global, using the register as an intermediary */
+/* The register will be a fixnum for one instruction, so this is gc-safe */
+
+#define load(reg,global) \
+       lis reg,global@ha; lwz reg,global@l(reg)
+#define store(reg,temp,global) \
+       lis temp,global@ha; stw reg,global@l(temp)
+       
+#define        FIRST_SAVE_FPR  14      /* lowest-numbered non-volatile FPR */
+#define        FIRST_SAVE_GPR  14      /* lowest-numbered non-volatile GPR */
+#define        NFPR_SAVE_BYTES(n) ((32-(n))*8)
+#define NGPR_SAVE_BYTES(n) ((32-(~1&((n)+1)))*4)
+#define FRAME_ARG_BYTES(n)  (((((n)+2)*4)+15)&~15)
+
+#define FRAME_SIZE(first_g,first_f,out_arg_words,savecr) \
+(NFPR_SAVE_BYTES(first_f)+ NGPR_SAVE_BYTES(first_g)+ FRAME_ARG_BYTES(out_arg_words+savecr))
+#define SAVE_FPR(n) stfd n,-8*(32-(n))(11)
+#define SAVE_GPR(n) stw n,-4*(32-(n))(11)
+#define FULL_FRAME_SIZE FRAME_SIZE(FIRST_SAVE_GPR,FIRST_SAVE_FPR,0,1)
+
+#define RESTORE_FPR(n) lfd n,-8*(32-(n))(11)
+#define RESTORE_GPR(n) lwz n,-4*(32-(n))(11)
+#define C_FULL_PROLOG \
+       mflr 0 ; \
+       stw 0,4(1) ; \
+       mr 11,1 ; \
+       stwu 1,-FULL_FRAME_SIZE(1) ; \
+       SAVE_FPR(14) ; \
+       SAVE_FPR(15) ; \
+       SAVE_FPR(16) ; \
+       SAVE_FPR(17) ; \
+       SAVE_FPR(18) ; \
+       SAVE_FPR(19) ; \
+       SAVE_FPR(20) ; \
+       SAVE_FPR(21) ; \
+       SAVE_FPR(22) ; \
+       SAVE_FPR(23) ; \
+       SAVE_FPR(24) ; \
+       SAVE_FPR(25) ; \
+       SAVE_FPR(26) ; \
+       SAVE_FPR(27) ; \
+       SAVE_FPR(28) ; \
+       SAVE_FPR(29) ; \
+       SAVE_FPR(30) ; \
+       SAVE_FPR(31) ; \
+       la 11,-NFPR_SAVE_BYTES(FIRST_SAVE_FPR)(11) ; \
+       SAVE_GPR(14) ; \
+       SAVE_GPR(15) ; \
+       SAVE_GPR(16) ; \
+       SAVE_GPR(17) ; \
+       SAVE_GPR(18) ; \
+       SAVE_GPR(19) ; \
+       SAVE_GPR(20) ; \
+       SAVE_GPR(21) ; \
+       SAVE_GPR(22) ; \
+       SAVE_GPR(23) ; \
+       SAVE_GPR(24) ; \
+       SAVE_GPR(25) ; \
+       SAVE_GPR(26) ; \
+       SAVE_GPR(27) ; \
+       SAVE_GPR(28) ; \
+       SAVE_GPR(29) ; \
+       SAVE_GPR(30) ; \
+       SAVE_GPR(31)
+
+
+#define C_FULL_EPILOG \
+       la 11,FULL_FRAME_SIZE-NFPR_SAVE_BYTES(FIRST_SAVE_FPR)(1) ; \
+       RESTORE_GPR(14) ; \
+       RESTORE_GPR(15) ; \
+       RESTORE_GPR(16) ; \
+       RESTORE_GPR(17) ; \
+       RESTORE_GPR(18) ; \
+       RESTORE_GPR(19) ; \
+       RESTORE_GPR(20) ; \
+       RESTORE_GPR(21) ; \
+       RESTORE_GPR(22) ; \
+       RESTORE_GPR(23) ; \
+       RESTORE_GPR(24) ; \
+       RESTORE_GPR(25) ; \
+       RESTORE_GPR(26) ; \
+       RESTORE_GPR(27) ; \
+       RESTORE_GPR(28) ; \
+       RESTORE_GPR(29) ; \
+       RESTORE_GPR(30) ; \
+       RESTORE_GPR(31) ; \
+       la 11,NFPR_SAVE_BYTES(FIRST_SAVE_FPR)(11) ; \
+       RESTORE_FPR(14) ; \
+       RESTORE_FPR(15) ; \
+       RESTORE_FPR(16) ; \
+       RESTORE_FPR(17) ; \
+       RESTORE_FPR(18) ; \
+       RESTORE_FPR(19) ; \
+       RESTORE_FPR(20) ; \
+       RESTORE_FPR(21) ; \
+       RESTORE_FPR(22) ; \
+       RESTORE_FPR(23) ; \
+       RESTORE_FPR(24) ; \
+       RESTORE_FPR(25) ; \
+       RESTORE_FPR(26) ; \
+       RESTORE_FPR(27) ; \
+       RESTORE_FPR(28) ; \
+       RESTORE_FPR(29) ; \
+       RESTORE_FPR(30) ; \
+       RESTORE_FPR(31) ; \
+       lwz 1,0(1) ; \
+       lwz 0,4(1) ; \
+       mtlr 0 ; \
+       
+
+
+       
+       .text
+
+/*
+ * Function to transfer control into lisp.  The lisp object to invoke is
+ * passed as the first argument, which puts it in NL0
+ */
+
+       GFUNCDEF(call_into_lisp)
+       C_FULL_PROLOG
+       mfcr 0
+       stw 0,8(1)
+       /* store(reg_POLL,11,saver2) */
+       /* Initialize tagged registers */
+       li reg_ZERO,0
+       li reg_CODE,0
+       li reg_CNAME,0
+       li reg_LEXENV,0
+       li reg_FDEFN,0
+       li reg_OCFP,0
+       li reg_LRA,0
+       li reg_A0,0
+       li reg_A1,0
+       li reg_A2,0
+       li reg_A3,0
+       li reg_L0,0
+       li reg_L1,0
+       li reg_L2,0
+       li reg_LIP,0
+       lis reg_NULL,NIL@h
+       ori reg_NULL,reg_NULL,NIL@l
+
+       /* Turn on pseudo-atomic */
+
+       li reg_NL3,-4
+       li reg_ALLOC,4
+       store(reg_ZERO,reg_NL4,foreign_function_call_active)
+       load(reg_NL4,dynamic_space_free_pointer)
+       add reg_ALLOC,reg_ALLOC,reg_NL4
+       load(reg_BSP,current_binding_stack_pointer)
+       load(reg_CSP,current_control_stack_pointer)
+       load(reg_OCFP,current_control_frame_pointer)
+
+       /* No longer atomic, and check for interrupt */
+       add reg_ALLOC,reg_ALLOC,reg_NL3
+       twlti reg_ALLOC,0
+
+       /* Pass in the arguments */
+
+       mr reg_CFP,reg_NL1
+       mr reg_LEXENV,reg_NL0
+       lwz reg_A0,0(reg_CFP)
+       lwz reg_A1,4(reg_CFP)
+       lwz reg_A2,8(reg_CFP)
+       lwz reg_A3,12(reg_CFP)
+
+       /* Calculate LRA */
+       lis reg_LRA,lra@ha
+       addi reg_LRA,reg_LRA,lra@l
+       addi reg_LRA,reg_LRA,OTHER_POINTER_LOWTAG
+
+       /* Function is an indirect closure */
+       lwz reg_CODE,SIMPLE_FUN_SELF_OFFSET(reg_LEXENV)
+       addi reg_LIP,reg_CODE,6*4-FUN_POINTER_LOWTAG
+       mtctr reg_LIP
+       slwi reg_NARGS,reg_NL2,2
+       bctr                    
+       
+       .align 3
+lra:
+       .long RETURN_PC_HEADER_WIDETAG 
+
+       /* Blow off any extra values. */
+       mr reg_CSP,reg_OCFP
+       nop
+
+       /* Return the one value. */
+
+       mr 3,reg_A0
+
+       /* Turn on  pseudo-atomic */
+       li reg_NL3,-4
+       la reg_ALLOC,4(reg_ALLOC)
+
+       /* Store lisp state */
+       clrrwi reg_NL1,reg_ALLOC,3
+       store(reg_NL1,reg_NL2,dynamic_space_free_pointer)
+       /* store(reg_POLL,reg_NL2,poll_flag) */
+       /* load(reg_NL2,current_thread) */
+       store(reg_BSP,reg_NL2,current_binding_stack_pointer)
+       store(reg_CSP,reg_NL2,current_control_stack_pointer)
+       store(reg_CFP,reg_NL2,current_control_frame_pointer)
+       /* load(reg_POLL,saver2) */
+
+       /* No longer in Lisp. */
+       store(reg_NL1,reg_NL2,foreign_function_call_active)
+
+       /* Check for interrupt */
+       add reg_ALLOC,reg_ALLOC,reg_NL3
+       twlti reg_ALLOC,0
+
+       /* Back to C */
+       lwz 5,8(1)
+       mtcrf 255,5
+       C_FULL_EPILOG
+       blr
+       SET_SIZE(call_into_lisp)
+\f
+
+       GFUNCDEF(call_into_c)
+       /* We're kind of low on unboxed, non-dedicated registers here:
+       most of the unboxed registers may have outgoing C args in them.
+       CFUNC is going to have to go in the CTR in a moment, anyway
+       so we'll free it up soon.  reg_NFP is preserved by lisp if it
+       has a meaningful value in it, so we can use it.  reg_NARGS is
+       free when it's not holding a copy of the "real" reg_NL3, which
+       gets tied up by the pseudo-atomic mechanism */
+       mtctr reg_CFUNC
+       mflr reg_LIP
+       /* Build a lisp stack frame */
+       mr reg_OCFP,reg_CFP
+       mr reg_CFP,reg_CSP
+       la reg_CSP,32(reg_CSP)
+       stw reg_OCFP,0(reg_CFP)
+       stw reg_CODE,8(reg_CFP)
+       /* The pseudo-atomic mechanism wants to use reg_NL3, but that
+       may be an outgoing C argument.  Copy reg_NL3 to something that's
+       unboxed and -not- one of the C argument registers */
+       mr reg_NARGS,reg_NL3
+
+       /* Turn on pseudo-atomic */
+       li reg_NL3,-4
+       la reg_ALLOC,4(reg_ALLOC)
+
+       /* Convert the return address to an offset and save it on the stack. */
+       sub reg_NFP,reg_LIP,reg_CODE
+       la reg_NFP,OTHER_POINTER_LOWTAG(reg_NFP)
+       stw reg_NFP,4(reg_CFP)
+
+       /* Store Lisp state */
+       clrrwi reg_NFP,reg_ALLOC,3
+       store(reg_NFP,reg_CFUNC,dynamic_space_free_pointer)
+       /* load(reg_CFUNC,current_thread) */
+       
+       store(reg_BSP,reg_CFUNC,current_binding_stack_pointer)
+       store(reg_CSP,reg_CFUNC,current_control_stack_pointer)
+       store(reg_CFP,reg_CFUNC,current_control_frame_pointer)
+
+       /* No longer in Lisp */
+       store(reg_CSP,reg_CFUNC,foreign_function_call_active)
+       /* load(reg_POLL,saver2) */
+       /* Disable pseudo-atomic; check pending interrupt */
+       add reg_ALLOC,reg_ALLOC,reg_NL3
+       twlti reg_ALLOC,0
+       mr reg_NL3,reg_NARGS
+
+        /* Into C we go. */
+       bctrl
+
+       /* Re-establish NIL */
+       lis reg_NULL,NIL@h
+       ori reg_NULL,reg_NULL,NIL@l
+       /* And reg_ZERO */
+       li reg_ZERO,0
+
+       /* If we GC'ed during the FF code (as the result of a callback ?)
+       the tagged lisp registers may now contain garbage (since the
+       registers were saved by C and not seen by the GC.)  Put something
+       harmless in all such registers before allowing an interrupt */
+       li reg_CODE,0
+       li reg_CNAME,0
+       li reg_LEXENV,0
+       /* reg_OCFP was pointing to a control stack frame & was preserved by C */
+       li reg_LRA,0
+       li reg_A0,0
+       li reg_A1,0
+       li reg_A2,0
+       li reg_A3,0
+       li reg_L0,0
+       li reg_L1,0
+       li reg_L2,0
+       li reg_LIP,0
+
+       /* Atomic ... */
+       li reg_NL3,-4
+       li reg_ALLOC,4
+
+       /* No long in foreign function call. */
+       store(reg_ZERO,reg_NL2,foreign_function_call_active)
+
+       /* The free pointer may have moved */
+       load(reg_NL4,dynamic_space_free_pointer)
+       add reg_ALLOC,reg_ALLOC,reg_NL4
+
+       /* The BSP wasn't preserved by C, so load it */
+       load(reg_BSP,current_binding_stack_pointer)
+
+       /* Other lisp stack/frame pointers were preserved by C.
+       I can't imagine why they'd have moved */
+
+       /* Get the return address back. */
+       lwz reg_LIP,4(reg_CFP)
+       lwz reg_CODE,8(reg_CFP)
+       add reg_LIP,reg_CODE,reg_LIP
+       la reg_LIP,-OTHER_POINTER_LOWTAG(reg_LIP)
+
+       /* No longer atomic */
+       add reg_ALLOC,reg_ALLOC,reg_NL3
+       twlti reg_ALLOC,0
+       mtlr reg_LIP
+       
+       /* Reset the lisp stack. */
+       mr reg_CSP,reg_CFP
+       mr reg_CFP,reg_OCFP
+       
+       /* And back into Lisp. */
+       blr
+
+       SET_SIZE(call_into_c)
+
+       GFUNCDEF(xundefined_tramp)
+       .globl undefined_tramp
+       .byte 0,0,0,SIMPLE_FUN_HEADER_WIDETAG /* type_FunctionHeader */
+
+       .byte 18<<2
+undefined_tramp:
+       .byte 0,0,24
+       .long undefined_tramp
+       .long NIL
+       .long NIL
+       .long NIL
+       .long NIL
+       twllei reg_ZERO,trap_Cerror
+       .byte 4
+       .byte UNDEFINED_FUN_ERROR
+       .byte 254, 140, 2       /* 140?  sparc says sc_descriptorReg */
+       .align 2
+1:     lwz reg_CODE,FDEFN_RAW_ADDR_OFFSET(reg_FDEFN)
+       la reg_LIP,SIMPLE_FUN_CODE_OFFSET(reg_CODE)
+       mtctr reg_LIP
+       bctr
+       
+       SET_SIZE(xundefined_tramp)
+
+       GFUNCDEF(xclosure_tramp)
+       .globl closure_tramp
+       .byte 0,0,0,SIMPLE_FUN_HEADER_WIDETAG
+       .byte 18<<2
+closure_tramp:
+       .byte 0,0,24
+       .long closure_tramp
+       .long NIL 
+       .long NIL
+       .long NIL
+       .long NIL
+       lwz reg_LEXENV,FDEFN_FUN_OFFSET(reg_FDEFN)
+       lwz reg_CODE,CLOSURE_FUN_OFFSET(reg_LEXENV)
+       la reg_LIP,SIMPLE_FUN_CODE_OFFSET(reg_CODE)
+       mtctr reg_LIP
+       bctr
+
+       SET_SIZE(xclosure_tramp)
+
+       GFUNCDEF(fun_end_breakpoint_trap)
+       .long 0
+       SET_SIZE(fun_end_breakpoint_trap)
+
+       GFUNCDEF(fun_end_breakpoint)
+       .long 0
+       SET_SIZE(fun_end_breakpoint)
+
+       GFUNCDEF(fun_end_breakpoint_guts)
+       .long 0
+       SET_SIZE(fun_end_breakpoint_guts)
+
+       GFUNCDEF(fun_end_breakpoint_end)
+       .long 0
+       SET_SIZE(fun_end_breakpoint_end)
+
+
+       GFUNCDEF(ppc_flush_cache_line)
+       dcbf 0,3
+       sync
+       icbi 0,3
+       sync
+       isync
+       blr
+       SET_SIZE(ppc_flush_cache_line)
+
diff --git a/src/runtime/ppc-linux-os.c b/src/runtime/ppc-linux-os.c
new file mode 100644 (file)
index 0000000..c5dc7a2
--- /dev/null
@@ -0,0 +1,75 @@
+/*
+ * This is the IBM/Motorola/Apple/whoever Linux incarnation of
+ * arch-dependent OS-dependent routines. See also "linux-os.c".  */
+
+/*
+ * This software is part of the SBCL system. See the README file for
+ * more information.
+ *
+ * This software is derived from the CMU CL system, which was
+ * written at Carnegie Mellon University and released into the
+ * public domain. The software is in the public domain and is
+ * provided with absolutely no warranty. See the COPYING and CREDITS
+ * files for more information.
+ */
+
+/* These header files were lifted wholesale from linux-os.c, some may
+ * be redundant. -- Dan Barlow ca. 2001-05-01 */
+#include <stdio.h>
+#include <sys/param.h>
+#include <sys/file.h>
+#include "./signal.h"
+#include "os.h"
+#include "arch.h"
+#include "globals.h"
+#include "interrupt.h"
+#include "interr.h"
+#include "lispregs.h"
+#include "sbcl.h"
+#include <sys/socket.h>
+#include <sys/utsname.h>
+
+#include <sys/types.h>
+#include <signal.h>
+#include <sys/time.h>
+#include <sys/stat.h>
+#include <unistd.h>
+
+#include "validate.h"
+size_t os_vm_page_size;
+
+#if defined GENCGC             /* unlikely ... */
+#error SBCL PPC does not work with the GENCGC
+#include "gencgc.h"
+#endif
+
+os_context_register_t   *
+os_context_register_addr(os_context_t *context, int offset)
+{
+    return &((context->uc_mcontext.regs)->gpr[offset]);
+}
+
+os_context_register_t *
+os_context_pc_addr(os_context_t *context)
+{
+    return &((context->uc_mcontext.regs)->nip);
+}
+
+os_context_register_t *
+os_context_lr_addr(os_context_t *context)
+{
+    return &((context->uc_mcontext.regs)->link);
+}
+
+sigset_t *
+os_context_sigmask_addr(os_context_t *context)
+{
+    return &context->uc_sigmask;
+}
+
+void os_flush_icache(os_vm_address_t address, os_vm_size_t length)
+{
+    /* see ppc-arch.c */
+    ppc_flush_icache(address,length);
+}
+
diff --git a/src/runtime/ppc-linux-os.h b/src/runtime/ppc-linux-os.h
new file mode 100644 (file)
index 0000000..e057ad3
--- /dev/null
@@ -0,0 +1,10 @@
+#ifndef _PPC_LINUX_OS_H
+#define _PPC_LINUX_OS_H
+
+typedef struct ucontext os_context_t;
+
+static inline os_context_t *arch_os_get_context(void **void_context) {
+  return (os_context_t *) *void_context;
+}
+
+#endif /* _PPC_LINUX_OS_H */
diff --git a/src/runtime/ppc-lispregs.h b/src/runtime/ppc-lispregs.h
new file mode 100644 (file)
index 0000000..956c11d
--- /dev/null
@@ -0,0 +1,51 @@
+#define REG(num) num
+#define NREGS 32
+
+#define reg_ZERO      REG(0)   /* Should always contain 0 in lisp */
+#define reg_NSP       REG(1)   /* The number/C stack pointer */
+#define reg_POLL      REG(2)   /* Lisp preemption/Mystery SVR4 ABI reg */
+#define reg_NL0       REG(3)   /* FF param/result 1 */
+#define reg_NL1       REG(4)   /* FF param/result 2 */
+#define reg_NL2       REG(5)   /* FF param 3 */
+#define reg_NL3       REG(6)
+#define reg_NL4       REG(7)
+#define reg_NL5       REG(8)
+#define reg_NL6       REG(9)   /* Last (7th) FF param */
+#define reg_FDEFN     REG(10)   /* was NL7 until recently -dan */
+#define reg_NARGS     REG(11)
+#define reg_NFP       REG(12)  /* Lisp may save around FF-call */
+#define reg_CFUNC     REG(13)  /* Silly to blow a reg on FF-name */
+#define reg_BSP       REG(14)   /* Binding stack pointer */
+#define reg_CFP       REG(15)  /* Control/value stack frame pointer */
+#define reg_CSP       REG(16)  /* Control/value stack top */
+#define reg_ALLOC     REG(17)  /* (Global) dynamic free pointer */
+#define reg_NULL      REG(18)  /* NIL and globals nearby */
+#define reg_CODE      REG(19)  /* Current function object */
+#define reg_CNAME     REG(20)  /* Current function name */
+#define reg_LEXENV    REG(21)  /* And why burn a register for this ? */
+#define reg_OCFP      REG(22)   /* The caller's reg_CFP */
+#define reg_LRA       REG(23)  /* Tagged lisp return address */
+#define reg_A0        REG(24)  /* First function arg/return value */
+#define reg_A1        REG(25)  /* Second. */
+#define reg_A2        REG(26)  /*  */
+#define reg_A3        REG(27)  /* Last of (only) 4 arg regs */
+#define reg_L0       REG(28)   /* Tagged temp regs */
+#define reg_L1        REG(29)
+#define reg_L2        REG(30)  /* Last lisp temp reg */
+#define reg_LIP       REG(31)  /* Lisp Interior Pointer, e.g., locative */
+
+#define REGNAMES \
+        "ZERO",                "NSP",          "???",          "NL0", \
+       "NL1",          "NL2",          "NL3P",         "NL4", \
+        "NL5",         "NL6",          "FDEFN",        "NARGS", \
+        "NFP",         "CFUNC"         "BSP",          "CFP", \
+        "CSP",         "ALLOC",        "NULL",         "CODE", \
+        "CNAME",       "LEXENV",       "OCFP",         "LRA", \
+        "A0",          "A1",           "A2",           "A3", \
+        "L0",          "L1",           "L2",           "LIP"
+
+#define BOXED_REGISTERS { \
+    reg_FDEFN, reg_CODE, reg_CNAME, reg_LEXENV, reg_OCFP, reg_LRA, \
+    reg_A0, reg_A1, reg_A2, reg_A3, \
+    reg_L0, reg_L1, reg_L2 \
+}