Back to index

lightning-sunbird  0.9+nobinonly
mach_dep.c
Go to the documentation of this file.
00001 /* 
00002  * Copyright 1988, 1989 Hans-J. Boehm, Alan J. Demers
00003  * Copyright (c) 1991-1994 by Xerox Corporation.  All rights reserved.
00004  *
00005  * THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY EXPRESSED
00006  * OR IMPLIED.  ANY USE IS AT YOUR OWN RISK.
00007  *
00008  * Permission is hereby granted to use or copy this program
00009  * for any purpose,  provided the above notices are retained on all copies.
00010  * Permission to modify the code and to distribute modified code is granted,
00011  * provided the above notices are retained, and a notice that the code was
00012  * modified is included with the above copyright notice.
00013  */
00014 /* Boehm, November 17, 1995 12:13 pm PST */
00015 # include "gc_priv.h"
00016 # include <stdio.h>
00017 # include <setjmp.h>
00018 # if defined(OS2) || defined(CX_UX)
00019 #   define _setjmp(b) setjmp(b)
00020 #   define _longjmp(b,v) longjmp(b,v)
00021 # endif
00022 # ifdef AMIGA
00023 #   include <dos.h>
00024 # endif
00025 
00026 void foo()
00027 {
00028        foo();
00029 }
00030 
00031 #if defined(MACOS) && defined(__MWERKS__)
00032 
00033 #if defined(POWERPC)
00034 
00035 #define NONVOLATILE_GPR_COUNT 19
00036 
00037 struct ppc_registers {
00038        unsigned long gprs[NONVOLATILE_GPR_COUNT];       /* R13-R31 */
00039 };
00040 typedef struct ppc_registers ppc_registers;
00041 
00042 asm static void getRegisters(register ppc_registers* regs)
00043 {
00044        stmw   r13,regs->gprs                                          /* save R13-R31 */
00045        blr
00046 }
00047 
00048 static void PushMacRegisters()
00049 {
00050        ppc_registers regs;
00051        int i;
00052        getRegisters(&regs);
00053        for (i = 0; i < NONVOLATILE_GPR_COUNT; i++)
00054               GC_push_one(regs.gprs[i]);
00055 }
00056 
00057 #else /* M68K */
00058 
00059 asm static void PushMacRegisters()
00060 {
00061     sub.w   #4,sp                   // reserve space for one parameter.
00062     move.l  a2,(sp)
00063     jsr              GC_push_one
00064     move.l  a3,(sp)
00065     jsr              GC_push_one
00066     move.l  a4,(sp)
00067     jsr              GC_push_one
00068 #   if !__option(a6frames)
00069        // <pcb> perhaps a6 should be pushed if stack frames are not being used.    
00070        move.l a6,(sp)
00071        jsr           GC_push_one
00072 #   endif
00073        // skip a5 (globals), a6 (frame pointer), and a7 (stack pointer)
00074     move.l  d2,(sp)
00075     jsr              GC_push_one
00076     move.l  d3,(sp)
00077     jsr              GC_push_one
00078     move.l  d4,(sp)
00079     jsr              GC_push_one
00080     move.l  d5,(sp)
00081     jsr              GC_push_one
00082     move.l  d6,(sp)
00083     jsr              GC_push_one
00084     move.l  d7,(sp)
00085     jsr              GC_push_one
00086     add.w   #4,sp                   // fix stack.
00087     rts
00088 }
00089 
00090 #endif /* M68K */
00091 
00092 #endif /* MACOS && __MWERKS__ */
00093 
00094 /* Routine to mark from registers that are preserved by the C compiler. */
00095 /* This must be ported to every new architecture.  There is a generic   */
00096 /* version at the end, that is likely, but not guaranteed to work       */
00097 /* on your architecture.  Run the test_setjmp program to see whether    */
00098 /* there is any chance it will work.                                    */
00099 
00100 #ifndef USE_GENERIC_PUSH_REGS
00101 void GC_push_regs()
00102 {
00103 #       ifdef RT
00104          register long TMP_SP; /* must be bound to r11 */
00105 #       endif
00106 #       ifdef VAX
00107          /* VAX - generic code below does not work under 4.2 */
00108          /* r1 through r5 are caller save, and therefore     */
00109          /* on the stack or dead.                            */
00110          asm("pushl r11");     asm("calls $1,_GC_push_one");
00111          asm("pushl r10");  asm("calls $1,_GC_push_one");
00112          asm("pushl r9");   asm("calls $1,_GC_push_one");
00113          asm("pushl r8");   asm("calls $1,_GC_push_one");
00114          asm("pushl r7");   asm("calls $1,_GC_push_one");
00115          asm("pushl r6");   asm("calls $1,_GC_push_one");
00116 #       endif
00117 #       if defined(M68K) && (defined(SUNOS4) || defined(NEXT))
00118        /*  M68K SUNOS - could be replaced by generic code */
00119          /* a0, a1 and d1 are caller save          */
00120          /*  and therefore are on stack or dead.   */
00121        
00122          asm("subqw #0x4,sp");            /* allocate word on top of stack */
00123 
00124          asm("movl a2,sp@");       asm("jbsr _GC_push_one");
00125          asm("movl a3,sp@");       asm("jbsr _GC_push_one");
00126          asm("movl a4,sp@");       asm("jbsr _GC_push_one");
00127          asm("movl a5,sp@");       asm("jbsr _GC_push_one");
00128          /* Skip frame pointer and stack pointer */
00129          asm("movl d1,sp@");       asm("jbsr _GC_push_one");
00130          asm("movl d2,sp@");       asm("jbsr _GC_push_one");
00131          asm("movl d3,sp@");       asm("jbsr _GC_push_one");
00132          asm("movl d4,sp@");       asm("jbsr _GC_push_one");
00133          asm("movl d5,sp@");       asm("jbsr _GC_push_one");
00134          asm("movl d6,sp@");       asm("jbsr _GC_push_one");
00135          asm("movl d7,sp@");       asm("jbsr _GC_push_one");
00136 
00137          asm("addqw #0x4,sp");            /* put stack back where it was     */
00138 #       endif
00139 
00140 #       if defined(M68K) && defined(HP)
00141        /*  M68K HP - could be replaced by generic code */
00142          /* a0, a1 and d1 are caller save.  */
00143        
00144          asm("subq.w &0x4,%sp");   /* allocate word on top of stack */
00145 
00146          asm("mov.l %a2,(%sp)"); asm("jsr _GC_push_one");
00147          asm("mov.l %a3,(%sp)"); asm("jsr _GC_push_one");
00148          asm("mov.l %a4,(%sp)"); asm("jsr _GC_push_one");
00149          asm("mov.l %a5,(%sp)"); asm("jsr _GC_push_one");
00150          /* Skip frame pointer and stack pointer */
00151          asm("mov.l %d1,(%sp)"); asm("jsr _GC_push_one");
00152          asm("mov.l %d2,(%sp)"); asm("jsr _GC_push_one");
00153          asm("mov.l %d3,(%sp)"); asm("jsr _GC_push_one");
00154          asm("mov.l %d4,(%sp)"); asm("jsr _GC_push_one");
00155          asm("mov.l %d5,(%sp)"); asm("jsr _GC_push_one");
00156          asm("mov.l %d6,(%sp)"); asm("jsr _GC_push_one");
00157          asm("mov.l %d7,(%sp)"); asm("jsr _GC_push_one");
00158 
00159          asm("addq.w &0x4,%sp");   /* put stack back where it was     */
00160 #       endif /* M68K HP */
00161 
00162 #       ifdef AMIGA
00163        /*  AMIGA - could be replaced by generic code                  */
00164          /* a0, a1, d0 and d1 are caller save */
00165          GC_push_one(getreg(REG_A2));
00166          GC_push_one(getreg(REG_A3));
00167          GC_push_one(getreg(REG_A4));
00168          GC_push_one(getreg(REG_A5));
00169          GC_push_one(getreg(REG_A6));
00170          /* Skip stack pointer */
00171          GC_push_one(getreg(REG_D2));
00172          GC_push_one(getreg(REG_D3));
00173          GC_push_one(getreg(REG_D4));
00174          GC_push_one(getreg(REG_D5));
00175          GC_push_one(getreg(REG_D6));
00176          GC_push_one(getreg(REG_D7));
00177 #       endif
00178 
00179 #    if defined(MACOS)
00180 #      if defined(M68K) && defined(THINK_C)
00181 #         define PushMacReg(reg) \
00182               move.l  reg,(sp) \
00183               jsr             GC_push_one
00184                        asm {
00185                             sub.w   #4,sp                   ; reserve space for one parameter.
00186                             PushMacReg(a2);
00187                             PushMacReg(a3);
00188                             PushMacReg(a4);
00189                             ; skip a5 (globals), a6 (frame pointer), and a7 (stack pointer)
00190                             PushMacReg(d2);
00191                             PushMacReg(d3);
00192                             PushMacReg(d4);
00193                             PushMacReg(d5);
00194                             PushMacReg(d6);
00195                             PushMacReg(d7);
00196                             add.w   #4,sp                   ; fix stack.
00197                        }
00198 #        undef PushMacReg
00199 #        endif /* THINK_C && M68K */
00200 #        if defined(__MWERKS__)
00201            PushMacRegisters();
00202 #        endif       /* __MWERKS__ */
00203 #   endif     /* MACOS */
00204 
00205 #       if defined(I386) &&!defined(OS2) &&!defined(SVR4) &&!defined(MSWIN32) \
00206        && !defined(SCO) && !defined(SCO_ELF) \
00207        && !(defined(LINUX)       && defined(__ELF__)) \
00208        && !(defined(__FreeBSD__) && defined(__ELF__)) \
00209        && !defined(DOS4GW)
00210        /* I386 code, generic code does not appear to work */
00211        /* It does appear to work under OS2, and asms dont */
00212        /* This is used for some 38g UNIX variants and for CYGWIN32 */
00213          asm("pushl %eax");  asm("call _GC_push_one"); asm("addl $4,%esp");
00214          asm("pushl %ecx");  asm("call _GC_push_one"); asm("addl $4,%esp");
00215          asm("pushl %edx");  asm("call _GC_push_one"); asm("addl $4,%esp");
00216          asm("pushl %ebp");  asm("call _GC_push_one"); asm("addl $4,%esp");
00217          asm("pushl %esi");  asm("call _GC_push_one"); asm("addl $4,%esp");
00218          asm("pushl %edi");  asm("call _GC_push_one"); asm("addl $4,%esp");
00219          asm("pushl %ebx");  asm("call _GC_push_one"); asm("addl $4,%esp");
00220 #       endif
00221 
00222 #      if ( defined(I386) && defined(LINUX) && defined(__ELF__) ) \
00223        || ( defined(I386) && defined(__FreeBSD__) && defined(__ELF__) )
00224 
00225        /* This is modified for Linux with ELF (Note: _ELF_ only) */
00226        /* This section handles FreeBSD with ELF. */
00227          asm("pushl %eax");  asm("call GC_push_one"); asm("addl $4,%esp");
00228          asm("pushl %ecx");  asm("call GC_push_one"); asm("addl $4,%esp");
00229          asm("pushl %edx");  asm("call GC_push_one"); asm("addl $4,%esp");
00230          asm("pushl %ebp");  asm("call GC_push_one"); asm("addl $4,%esp");
00231          asm("pushl %esi");  asm("call GC_push_one"); asm("addl $4,%esp");
00232          asm("pushl %edi");  asm("call GC_push_one"); asm("addl $4,%esp");
00233          asm("pushl %ebx");  asm("call GC_push_one"); asm("addl $4,%esp");
00234 #      endif
00235 
00236 #       if defined(I386) && defined(MSWIN32) && !defined(USE_GENERIC)
00237        /* I386 code, Microsoft variant           */
00238          __asm  push eax
00239          __asm  call GC_push_one
00240          __asm  add esp,4
00241          __asm  push ebx
00242          __asm  call GC_push_one
00243          __asm  add esp,4
00244          __asm  push ecx
00245          __asm  call GC_push_one
00246          __asm  add esp,4
00247          __asm  push edx
00248          __asm  call GC_push_one
00249          __asm  add esp,4
00250          __asm  push ebp
00251          __asm  call GC_push_one
00252          __asm  add esp,4
00253          __asm  push esi
00254          __asm  call GC_push_one
00255          __asm  add esp,4
00256          __asm  push edi
00257          __asm  call GC_push_one
00258          __asm  add esp,4
00259 #       endif
00260 
00261 #       if defined(I386) && (defined(SVR4) || defined(SCO) || defined(SCO_ELF))
00262        /* I386 code, SVR4 variant, generic code does not appear to work */
00263          asm("pushl %eax");  asm("call GC_push_one"); asm("addl $4,%esp");
00264          asm("pushl %ebx");  asm("call GC_push_one"); asm("addl $4,%esp");
00265          asm("pushl %ecx");  asm("call GC_push_one"); asm("addl $4,%esp");
00266          asm("pushl %edx");  asm("call GC_push_one"); asm("addl $4,%esp");
00267          asm("pushl %ebp");  asm("call GC_push_one"); asm("addl $4,%esp");
00268          asm("pushl %esi");  asm("call GC_push_one"); asm("addl $4,%esp");
00269          asm("pushl %edi");  asm("call GC_push_one"); asm("addl $4,%esp");
00270 #       endif
00271 
00272 #       ifdef NS32K
00273          asm ("movd r3, tos"); asm ("bsr ?_GC_push_one"); asm ("adjspb $-4");
00274          asm ("movd r4, tos"); asm ("bsr ?_GC_push_one"); asm ("adjspb $-4");
00275          asm ("movd r5, tos"); asm ("bsr ?_GC_push_one"); asm ("adjspb $-4");
00276          asm ("movd r6, tos"); asm ("bsr ?_GC_push_one"); asm ("adjspb $-4");
00277          asm ("movd r7, tos"); asm ("bsr ?_GC_push_one"); asm ("adjspb $-4");
00278 #       endif
00279 
00280 #       ifdef SPARC
00281          {
00282              word GC_save_regs_in_stack();
00283              
00284              /* generic code will not work */
00285              (void)GC_save_regs_in_stack();
00286          }
00287 #       endif
00288 
00289 #      ifdef RT
00290            GC_push_one(TMP_SP);    /* GC_push_one from r11 */
00291 
00292            asm("cas r11, r6, r0"); GC_push_one(TMP_SP); /* r6 */
00293            asm("cas r11, r7, r0"); GC_push_one(TMP_SP); /* through */
00294            asm("cas r11, r8, r0"); GC_push_one(TMP_SP); /* r10 */
00295            asm("cas r11, r9, r0"); GC_push_one(TMP_SP);
00296            asm("cas r11, r10, r0"); GC_push_one(TMP_SP);
00297 
00298            asm("cas r11, r12, r0"); GC_push_one(TMP_SP); /* r12 */
00299            asm("cas r11, r13, r0"); GC_push_one(TMP_SP); /* through */
00300            asm("cas r11, r14, r0"); GC_push_one(TMP_SP); /* r15 */
00301            asm("cas r11, r15, r0"); GC_push_one(TMP_SP);
00302 #       endif
00303 
00304 #       if defined(M68K) && defined(SYSV)
00305        /*  Once again similar to SUN and HP, though setjmp appears to work.
00306               --Parag
00307         */
00308 #        ifdef __GNUC__
00309          asm("subqw #0x4,%sp");    /* allocate word on top of stack */
00310   
00311          asm("movl %a2,%sp@");     asm("jbsr GC_push_one");
00312          asm("movl %a3,%sp@");     asm("jbsr GC_push_one");
00313          asm("movl %a4,%sp@");     asm("jbsr GC_push_one");
00314          asm("movl %a5,%sp@");     asm("jbsr GC_push_one");
00315          /* Skip frame pointer and stack pointer */
00316          asm("movl %d1,%sp@");     asm("jbsr GC_push_one");
00317          asm("movl %d2,%sp@");     asm("jbsr GC_push_one");
00318          asm("movl %d3,%sp@");     asm("jbsr GC_push_one");
00319          asm("movl %d4,%sp@");     asm("jbsr GC_push_one");
00320          asm("movl %d5,%sp@");     asm("jbsr GC_push_one");
00321          asm("movl %d6,%sp@");     asm("jbsr GC_push_one");
00322          asm("movl %d7,%sp@");     asm("jbsr GC_push_one");
00323   
00324          asm("addqw #0x4,%sp");    /* put stack back where it was     */
00325 #        else /* !__GNUC__*/
00326          asm("subq.w &0x4,%sp");   /* allocate word on top of stack */
00327   
00328          asm("mov.l %a2,(%sp)"); asm("jsr GC_push_one");
00329          asm("mov.l %a3,(%sp)"); asm("jsr GC_push_one");
00330          asm("mov.l %a4,(%sp)"); asm("jsr GC_push_one");
00331          asm("mov.l %a5,(%sp)"); asm("jsr GC_push_one");
00332          /* Skip frame pointer and stack pointer */
00333          asm("mov.l %d1,(%sp)"); asm("jsr GC_push_one");
00334          asm("mov.l %d2,(%sp)"); asm("jsr GC_push_one");
00335          asm("mov.l %d3,(%sp)"); asm("jsr GC_push_one");
00336          asm("mov.l %d4,(%sp)"); asm("jsr GC_push_one");
00337          asm("mov.l %d5,(%sp)"); asm("jsr GC_push_one");
00338          asm("mov.l %d6,(%sp)"); asm("jsr GC_push_one");
00339          asm("mov.l %d7,(%sp)"); asm("jsr GC_push_one");
00340   
00341          asm("addq.w &0x4,%sp");   /* put stack back where it was     */
00342 #        endif /* !__GNUC__ */
00343 #       endif /* M68K/SYSV */
00344 
00345 
00346       /* other machines... */
00347 #       if !(defined M68K) && !(defined VAX) && !(defined RT) 
00348 #      if !(defined SPARC) && !(defined I386) && !(defined NS32K)
00349 #      if !defined(POWERPC) && !defined(UTS4)
00350            --> bad news <--
00351 #       endif
00352 #       endif
00353 #       endif
00354 }
00355 #endif /* !USE_GENERIC_PUSH_REGS */
00356 
00357 #if defined(USE_GENERIC_PUSH_REGS)
00358 void GC_generic_push_regs(cold_gc_frame)
00359 ptr_t cold_gc_frame;
00360 {
00361        /* Generic code                          */
00362        /* The idea is due to Parag Patel at HP. */
00363        /* We're not sure whether he would like  */
00364        /* to be he acknowledged for it or not.  */
00365        {
00366            static jmp_buf regs;
00367            register word * i = (word *) regs;
00368            register ptr_t lim = (ptr_t)(regs) + (sizeof regs);
00369 
00370            /* Setjmp on Sun 3s doesn't clear all of the buffer.  */
00371            /* That tends to preserve garbage.  Clear it.         */
00372               for (; (char *)i < lim; i++) {
00373                   *i = 0;
00374               }
00375 #          if defined(POWERPC) || defined(MSWIN32) || defined(UTS4)
00376               (void) setjmp(regs);
00377 #          else
00378                (void) _setjmp(regs);
00379 #          endif
00380            GC_push_current_stack(cold_gc_frame);
00381        }
00382 }
00383 #endif /* USE_GENERIC_PUSH_REGS */
00384 
00385 /* On register window machines, we need a way to force registers into        */
00386 /* the stack. Return sp.                                       */
00387 # ifdef SPARC
00388     asm("     .seg   \"text\"");
00389 #   ifdef SVR4
00390       asm("   .globl GC_save_regs_in_stack");
00391       asm("GC_save_regs_in_stack:");
00392       asm("   .type GC_save_regs_in_stack,#function");
00393 #   else
00394       asm("   .globl _GC_save_regs_in_stack");
00395       asm("_GC_save_regs_in_stack:");
00396 #   endif
00397     asm("     ta     0x3   ! ST_FLUSH_WINDOWS");
00398     asm("     mov    %sp,%o0");
00399     asm("     retl");
00400     asm("     nop");
00401 #   ifdef SVR4
00402       asm("   .GC_save_regs_in_stack_end:");
00403       asm("   .size GC_save_regs_in_stack,.GC_save_regs_in_stack_end-GC_save_regs_in_stack");
00404 #   endif
00405 #   ifdef LINT
00406        word GC_save_regs_in_stack() { return(0 /* sp really */);}
00407 #   endif
00408 # endif
00409 
00410 
00411 /* GC_clear_stack_inner(arg, limit) clears stack area up to limit and */
00412 /* returns arg.  Stack clearing is crucial on SPARC, so we supply     */
00413 /* an assembly version that's more careful.  Assumes limit is hotter  */
00414 /* than sp, and limit is 8 byte aligned.                       */
00415 #if defined(ASM_CLEAR_CODE) && !defined(THREADS)
00416 #ifndef SPARC
00417        --> fix it
00418 #endif
00419 # ifdef SUNOS4
00420     asm(".globl _GC_clear_stack_inner");
00421     asm("_GC_clear_stack_inner:");
00422 # else
00423     asm(".globl GC_clear_stack_inner");
00424     asm("GC_clear_stack_inner:");
00425     asm(".type GC_save_regs_in_stack,#function");
00426 # endif
00427   asm("mov %sp,%o2");              /* Save sp    */
00428   asm("add %sp,-8,%o3");    /* p = sp-8   */
00429   asm("clr %g1");           /* [g0,g1] = 0       */
00430   asm("add %o1,-0x60,%sp"); /* Move sp out of the way,  */
00431                             /* so that traps still work.       */
00432                             /* Includes some extra words       */
00433                             /* so we can be sloppy below.      */
00434   asm("loop:");
00435   asm("std %g0,[%o3]");            /* *(long long *)p = 0      */
00436   asm("cmp %o3,%o1");
00437   asm("bgu loop      ");           /* if (p > limit) goto loop */
00438     asm("add %o3,-8,%o3");  /* p -= 8 (delay slot) */
00439   asm("retl");
00440     asm("mov %o2,%sp");            /* Restore sp., delay slot  */
00441   /* First argument = %o0 = return value */
00442 #   ifdef SVR4
00443       asm("   .GC_clear_stack_inner_end:");
00444       asm("   .size GC_clear_stack_inner,.GC_clear_stack_inner_end-GC_clear_stack_inner");
00445 #   endif
00446   
00447 # ifdef LINT
00448     /*ARGSUSED*/
00449     ptr_t GC_clear_stack_inner(arg, limit)
00450     ptr_t arg; word limit;
00451     { return(arg); }
00452 # endif
00453 #endif