LCOV - code coverage report
Current view: top level - mm/boehm-gc - mach_dep.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 13 14 92.9 %
Date: 2015-06-10 18:10:59 Functions: 1 1 100.0 %

          Line data    Source code
       1             : /*
       2             :  * Copyright 1988, 1989 Hans-J. Boehm, Alan J. Demers
       3             :  * Copyright (c) 1991-1994 by Xerox Corporation.  All rights reserved.
       4             :  *
       5             :  * THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY EXPRESSED
       6             :  * OR IMPLIED.  ANY USE IS AT YOUR OWN RISK.
       7             :  *
       8             :  * Permission is hereby granted to use or copy this program
       9             :  * for any purpose,  provided the above notices are retained on all copies.
      10             :  * Permission to modify the code and to distribute modified code is granted,
      11             :  * provided the above notices are retained, and a notice that the code was
      12             :  * modified is included with the above copyright notice.
      13             :  */
      14             : 
      15             : #include "private/gc_priv.h"
      16             : 
      17             : #include <stdio.h>
      18             : #include <setjmp.h>
      19             : 
      20             : #if defined(OS2) || defined(CX_UX) || defined(__CC_ARM)
      21             : # define _setjmp(b) setjmp(b)
      22             : # define _longjmp(b,v) longjmp(b,v)
      23             : #endif
      24             : 
      25             : #ifdef AMIGA
      26             : # ifndef __GNUC__
      27             : #   include <dos.h>
      28             : # else
      29             : #   include <machine/reg.h>
      30             : # endif
      31             : #endif
      32             : 
      33             : #if defined(__MWERKS__) && !defined(POWERPC)
      34             : 
      35             : asm static void PushMacRegisters()
      36             : {
      37             :     sub.w   #4,sp                   // reserve space for one parameter.
      38             :     move.l  a2,(sp)
      39             :     jsr         GC_push_one
      40             :     move.l  a3,(sp)
      41             :     jsr         GC_push_one
      42             :     move.l  a4,(sp)
      43             :     jsr         GC_push_one
      44             : #   if !__option(a6frames)
      45             :         // <pcb> perhaps a6 should be pushed if stack frames are not being used.
      46             :         move.l  a6,(sp)
      47             :         jsr             GC_push_one
      48             : #   endif
      49             :         // skip a5 (globals), a6 (frame pointer), and a7 (stack pointer)
      50             :     move.l  d2,(sp)
      51             :     jsr         GC_push_one
      52             :     move.l  d3,(sp)
      53             :     jsr         GC_push_one
      54             :     move.l  d4,(sp)
      55             :     jsr         GC_push_one
      56             :     move.l  d5,(sp)
      57             :     jsr         GC_push_one
      58             :     move.l  d6,(sp)
      59             :     jsr         GC_push_one
      60             :     move.l  d7,(sp)
      61             :     jsr         GC_push_one
      62             :     add.w   #4,sp                   // fix stack.
      63             :     rts
      64             : }
      65             : 
      66             : #endif /* __MWERKS__ */
      67             : 
      68             : # if defined(SPARC) || defined(IA64)
      69             :     /* Value returned from register flushing routine; either sp (SPARC) */
      70             :     /* or ar.bsp (IA64).                                                */
      71             :     GC_INNER ptr_t GC_save_regs_ret_val = NULL;
      72             : # endif
      73             : 
      74             : /* Routine to mark from registers that are preserved by the C compiler. */
      75             : /* This must be ported to every new architecture.  It is not optional,  */
      76             : /* and should not be used on platforms that are either UNIX-like, or    */
      77             : /* require thread support.                                              */
      78             : 
      79             : #undef HAVE_PUSH_REGS
      80             : 
      81             : #if defined(USE_ASM_PUSH_REGS)
      82             : # define HAVE_PUSH_REGS
      83             : #else  /* No asm implementation */
      84             : 
      85             : # if defined(M68K) && defined(AMIGA)
      86             :     /* This function is not static because it could also be             */
      87             :     /* errorneously defined in .S file, so this error would be caught   */
      88             :     /* by the linker.                                                   */
      89             :     void GC_push_regs(void)
      90             :     {
      91             :          /*  AMIGA - could be replaced by generic code                  */
      92             :          /* a0, a1, d0 and d1 are caller save */
      93             : 
      94             : #       ifdef __GNUC__
      95             :           asm("subq.w &0x4,%sp");       /* allocate word on top of stack */
      96             : 
      97             :           asm("mov.l %a2,(%sp)"); asm("jsr _GC_push_one");
      98             :           asm("mov.l %a3,(%sp)"); asm("jsr _GC_push_one");
      99             :           asm("mov.l %a4,(%sp)"); asm("jsr _GC_push_one");
     100             :           asm("mov.l %a5,(%sp)"); asm("jsr _GC_push_one");
     101             :           asm("mov.l %a6,(%sp)"); asm("jsr _GC_push_one");
     102             :           /* Skip frame pointer and stack pointer */
     103             :           asm("mov.l %d2,(%sp)"); asm("jsr _GC_push_one");
     104             :           asm("mov.l %d3,(%sp)"); asm("jsr _GC_push_one");
     105             :           asm("mov.l %d4,(%sp)"); asm("jsr _GC_push_one");
     106             :           asm("mov.l %d5,(%sp)"); asm("jsr _GC_push_one");
     107             :           asm("mov.l %d6,(%sp)"); asm("jsr _GC_push_one");
     108             :           asm("mov.l %d7,(%sp)"); asm("jsr _GC_push_one");
     109             : 
     110             :           asm("addq.w &0x4,%sp");       /* put stack back where it was  */
     111             : #       else /* !__GNUC__ */
     112             :           GC_push_one(getreg(REG_A2));
     113             :           GC_push_one(getreg(REG_A3));
     114             : #         ifndef __SASC
     115             :             /* Can probably be changed to #if 0 -Kjetil M. (a4=globals) */
     116             :             GC_push_one(getreg(REG_A4));
     117             : #         endif
     118             :           GC_push_one(getreg(REG_A5));
     119             :           GC_push_one(getreg(REG_A6));
     120             :           /* Skip stack pointer */
     121             :           GC_push_one(getreg(REG_D2));
     122             :           GC_push_one(getreg(REG_D3));
     123             :           GC_push_one(getreg(REG_D4));
     124             :           GC_push_one(getreg(REG_D5));
     125             :           GC_push_one(getreg(REG_D6));
     126             :           GC_push_one(getreg(REG_D7));
     127             : #       endif /* !__GNUC__ */
     128             :     }
     129             : #   define HAVE_PUSH_REGS
     130             : 
     131             : # elif defined(M68K) && defined(MACOS)
     132             : 
     133             : #   if defined(THINK_C)
     134             : #     define PushMacReg(reg) \
     135             :               move.l  reg,(sp) \
     136             :               jsr             GC_push_one
     137             :       void GC_push_regs(void)
     138             :       {
     139             :           asm {
     140             :               sub.w   #4,sp          ; reserve space for one parameter.
     141             :               PushMacReg(a2);
     142             :               PushMacReg(a3);
     143             :               PushMacReg(a4);
     144             :               ; skip a5 (globals), a6 (frame pointer), and a7 (stack pointer)
     145             :               PushMacReg(d2);
     146             :               PushMacReg(d3);
     147             :               PushMacReg(d4);
     148             :               PushMacReg(d5);
     149             :               PushMacReg(d6);
     150             :               PushMacReg(d7);
     151             :               add.w   #4,sp          ; fix stack.
     152             :           }
     153             :       }
     154             : #     define HAVE_PUSH_REGS
     155             : #     undef PushMacReg
     156             : #   elif defined(__MWERKS__)
     157             :       void GC_push_regs(void)
     158             :       {
     159             :           PushMacRegisters();
     160             :       }
     161             : #     define HAVE_PUSH_REGS
     162             : #   endif /* __MWERKS__ */
     163             : # endif /* MACOS */
     164             : 
     165             : #endif /* !USE_ASM_PUSH_REGS */
     166             : 
     167             : #if defined(HAVE_PUSH_REGS) && defined(THREADS)
     168             : # error GC_push_regs cannot be used with threads
     169             :  /* Would fail for GC_do_blocking.  There are probably other safety     */
     170             :  /* issues.                                                             */
     171             : # undef HAVE_PUSH_REGS
     172             : #endif
     173             : 
     174             : #if !defined(HAVE_PUSH_REGS) && defined(UNIX_LIKE)
     175             : # include <signal.h>
     176             : # ifndef NO_GETCONTEXT
     177             : #   include <ucontext.h>
     178             : #   ifdef GETCONTEXT_FPU_EXCMASK_BUG
     179             : #     include <fenv.h>
     180             : #   endif
     181             : # endif
     182             : #endif /* !HAVE_PUSH_REGS */
     183             : 
     184             : /* Ensure that either registers are pushed, or callee-save registers    */
     185             : /* are somewhere on the stack, and then call fn(arg, ctxt).             */
     186             : /* ctxt is either a pointer to a ucontext_t we generated, or NULL.      */
     187         258 : GC_INNER void GC_with_callee_saves_pushed(void (*fn)(ptr_t, void *),
     188             :                                           ptr_t arg)
     189             : {
     190             :     volatile int dummy;
     191         258 :     void * context = 0;
     192             : 
     193             : #   if defined(HAVE_PUSH_REGS)
     194             :       GC_push_regs();
     195             : #   elif defined(UNIX_LIKE) && !defined(NO_GETCONTEXT)
     196             :       /* Older versions of Darwin seem to lack getcontext(). */
     197             :       /* ARM and MIPS Linux often doesn't support a real     */
     198             :       /* getcontext().                                       */
     199             :       ucontext_t ctxt;
     200             : #     ifdef GETCONTEXT_FPU_EXCMASK_BUG
     201             :         /* Workaround a bug (clearing the FPU exception mask) in        */
     202             :         /* getcontext on Linux/x86_64.                                  */
     203             : #       ifdef X86_64
     204             :           /* We manipulate FPU control word here just not to force the  */
     205             :           /* client application to use -lm linker option.               */
     206             :           unsigned short old_fcw;
     207         258 :           __asm__ __volatile__ ("fstcw %0" : "=m" (*&old_fcw));
     208             : #       else
     209             :           int except_mask = fegetexcept();
     210             : #       endif
     211             : #     endif
     212         258 :       if (getcontext(&ctxt) < 0)
     213           0 :         ABORT ("getcontext failed: Use another register retrieval method?");
     214             : #     ifdef GETCONTEXT_FPU_EXCMASK_BUG
     215             : #       ifdef X86_64
     216         258 :           __asm__ __volatile__ ("fldcw %0" : : "m" (*&old_fcw));
     217             :           {
     218             :             unsigned mxcsr;
     219             :             /* And now correct the exception mask in SSE MXCSR. */
     220         258 :             __asm__ __volatile__ ("stmxcsr %0" : "=m" (*&mxcsr));
     221         516 :             mxcsr = (mxcsr & ~(FE_ALL_EXCEPT << 7)) |
     222         258 :                         ((old_fcw & FE_ALL_EXCEPT) << 7);
     223         258 :             __asm__ __volatile__ ("ldmxcsr %0" : : "m" (*&mxcsr));
     224             :           }
     225             : #       else /* !X86_64 */
     226             :           if (feenableexcept(except_mask) < 0)
     227             :             ABORT("feenableexcept failed");
     228             : #       endif
     229             : #     endif
     230         258 :       context = &ctxt;
     231             : #     if defined(SPARC) || defined(IA64)
     232             :         /* On a register window machine, we need to save register       */
     233             :         /* contents on the stack for this to work.  This may already be */
     234             :         /* subsumed by the getcontext() call.                           */
     235             :         GC_save_regs_ret_val = GC_save_regs_in_stack();
     236             : #     endif /* register windows. */
     237             : #   elif defined(HAVE_BUILTIN_UNWIND_INIT) \
     238             :          && !(defined(POWERPC) && defined(DARWIN)) \
     239             :          && !(defined(I386) && defined(RTEMS))
     240             :       /* This was suggested by Richard Henderson as the way to  */
     241             :       /* force callee-save registers and register windows onto  */
     242             :       /* the stack.                                             */
     243             :       /* Mark Sibly points out that this doesn't seem to work   */
     244             :       /* on MacOS 10.3.9/PowerPC.                               */
     245             :       __builtin_unwind_init();
     246             : #   else /* !HAVE_BUILTIN_UNWIND_INIT && !UNIX_LIKE  */
     247             :          /* && !HAVE_PUSH_REGS                       */
     248             :         /* Generic code                          */
     249             :         /* The idea is due to Parag Patel at HP. */
     250             :         /* We're not sure whether he would like  */
     251             :         /* to be he acknowledged for it or not.  */
     252             :         jmp_buf regs;
     253             :         register word * i = (word *) regs;
     254             :         register ptr_t lim = (ptr_t)(regs) + (sizeof regs);
     255             : 
     256             :         /* Setjmp doesn't always clear all of the buffer.               */
     257             :         /* That tends to preserve garbage.  Clear it.                   */
     258             :         for (; (char *)i < lim; i++) {
     259             :             *i = 0;
     260             :         }
     261             : #       if defined(MSWIN32) || defined(MSWINCE) || defined(UTS4) \
     262             :            || defined(LINUX) || defined(EWS4800) || defined(RTEMS)
     263             :           (void) setjmp(regs);
     264             : #       else
     265             :           (void) _setjmp(regs);
     266             :           /* We don't want to mess with signals. According to   */
     267             :           /* SUSV3, setjmp() may or may not save signal mask.   */
     268             :           /* _setjmp won't, but is less portable.               */
     269             : #       endif
     270             : #   endif /* !HAVE_PUSH_REGS ... */
     271             :     /* FIXME: context here is sometimes just zero.  At the moment the   */
     272             :     /* callees don't really need it.                                    */
     273         258 :     fn(arg, context);
     274             :     /* Strongly discourage the compiler from treating the above */
     275             :     /* as a tail-call, since that would pop the register        */
     276             :     /* contents before we get a chance to look at them.         */
     277         258 :     GC_noop1((word)(&dummy));
     278         258 : }
     279             : 
     280             : #if defined(ASM_CLEAR_CODE)
     281             : # ifdef LINT
     282             :     /*ARGSUSED*/
     283             :     ptr_t GC_clear_stack_inner(ptr_t arg, word limit)
     284             :     {
     285             :       return(arg);
     286             :     }
     287             :     /* The real version is in a .S file */
     288             : # endif
     289             : #endif /* ASM_CLEAR_CODE */

Generated by: LCOV version 1.11