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

Generated by: LCOV version 1.11