~ubuntu-branches/ubuntu/quantal/libgc/quantal

« back to all changes in this revision

Viewing changes to .pc/03-add-avr32-support.diff/mach_dep.c

  • Committer: Bazaar Package Importer
  • Author(s): Christoph Egger
  • Date: 2011-02-19 12:19:56 UTC
  • mfrom: (1.3.2 upstream) (0.1.5 experimental)
  • mto: This revision was merged to the branch mainline in revision 14.
  • Revision ID: james.westby@ubuntu.com-20110219121956-67rb69xlt5nud3v2
Tags: 1:7.1-5
Upload to unstable

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
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
/* Boehm, November 17, 1995 12:13 pm PST */
 
15
# include "private/gc_priv.h"
 
16
# include <stdio.h>
 
17
# include <setjmp.h>
 
18
# if defined(OS2) || defined(CX_UX)
 
19
#   define _setjmp(b) setjmp(b)
 
20
#   define _longjmp(b,v) longjmp(b,v)
 
21
# endif
 
22
# ifdef AMIGA
 
23
#   ifndef __GNUC__
 
24
#     include <dos.h>
 
25
#   else
 
26
#     include <machine/reg.h>
 
27
#   endif
 
28
# endif
 
29
 
 
30
#if defined(__MWERKS__) && !defined(POWERPC)
 
31
 
 
32
asm static void PushMacRegisters()
 
33
{
 
34
    sub.w   #4,sp                   // reserve space for one parameter.
 
35
    move.l  a2,(sp)
 
36
    jsr         GC_push_one
 
37
    move.l  a3,(sp)
 
38
    jsr         GC_push_one
 
39
    move.l  a4,(sp)
 
40
    jsr         GC_push_one
 
41
#   if !__option(a6frames)
 
42
        // <pcb> perhaps a6 should be pushed if stack frames are not being used.    
 
43
        move.l  a6,(sp)
 
44
        jsr             GC_push_one
 
45
#   endif
 
46
        // skip a5 (globals), a6 (frame pointer), and a7 (stack pointer)
 
47
    move.l  d2,(sp)
 
48
    jsr         GC_push_one
 
49
    move.l  d3,(sp)
 
50
    jsr         GC_push_one
 
51
    move.l  d4,(sp)
 
52
    jsr         GC_push_one
 
53
    move.l  d5,(sp)
 
54
    jsr         GC_push_one
 
55
    move.l  d6,(sp)
 
56
    jsr         GC_push_one
 
57
    move.l  d7,(sp)
 
58
    jsr         GC_push_one
 
59
    add.w   #4,sp                   // fix stack.
 
60
    rts
 
61
}
 
62
 
 
63
#endif /* __MWERKS__ */
 
64
 
 
65
# if defined(SPARC) || defined(IA64)
 
66
    /* Value returned from register flushing routine; either sp (SPARC) */
 
67
    /* or ar.bsp (IA64)                                                 */
 
68
    ptr_t GC_save_regs_ret_val;
 
69
# endif
 
70
 
 
71
/* Routine to mark from registers that are preserved by the C compiler. */
 
72
/* This must be ported to every new architecture.  It is noe optional,  */
 
73
/* and should not be used on platforms that are either UNIX-like, or    */
 
74
/* require thread support.                                              */
 
75
 
 
76
#undef HAVE_PUSH_REGS
 
77
 
 
78
#if defined(USE_ASM_PUSH_REGS)
 
79
#  define HAVE_PUSH_REGS
 
80
#else  /* No asm implementation */
 
81
void GC_push_regs()
 
82
{
 
83
#       if defined(M68K) && defined(AMIGA)
 
84
         /*  AMIGA - could be replaced by generic code                  */
 
85
         /* a0, a1, d0 and d1 are caller save */
 
86
 
 
87
#        ifdef __GNUC__
 
88
          asm("subq.w &0x4,%sp");       /* allocate word on top of stack */
 
89
 
 
90
          asm("mov.l %a2,(%sp)"); asm("jsr _GC_push_one");
 
91
          asm("mov.l %a3,(%sp)"); asm("jsr _GC_push_one");
 
92
          asm("mov.l %a4,(%sp)"); asm("jsr _GC_push_one");
 
93
          asm("mov.l %a5,(%sp)"); asm("jsr _GC_push_one");
 
94
          asm("mov.l %a6,(%sp)"); asm("jsr _GC_push_one");
 
95
          /* Skip frame pointer and stack pointer */
 
96
          asm("mov.l %d2,(%sp)"); asm("jsr _GC_push_one");
 
97
          asm("mov.l %d3,(%sp)"); asm("jsr _GC_push_one");
 
98
          asm("mov.l %d4,(%sp)"); asm("jsr _GC_push_one");
 
99
          asm("mov.l %d5,(%sp)"); asm("jsr _GC_push_one");
 
100
          asm("mov.l %d6,(%sp)"); asm("jsr _GC_push_one");
 
101
          asm("mov.l %d7,(%sp)"); asm("jsr _GC_push_one");
 
102
 
 
103
          asm("addq.w &0x4,%sp");       /* put stack back where it was  */
 
104
#         define HAVE_PUSH_REGS
 
105
#        else /* !__GNUC__ */
 
106
          GC_push_one(getreg(REG_A2));
 
107
          GC_push_one(getreg(REG_A3));
 
108
#         ifndef __SASC
 
109
              /* Can probably be changed to #if 0 -Kjetil M. (a4=globals)*/
 
110
            GC_push_one(getreg(REG_A4));
 
111
#         endif
 
112
          GC_push_one(getreg(REG_A5));
 
113
          GC_push_one(getreg(REG_A6));
 
114
          /* Skip stack pointer */
 
115
          GC_push_one(getreg(REG_D2));
 
116
          GC_push_one(getreg(REG_D3));
 
117
          GC_push_one(getreg(REG_D4));
 
118
          GC_push_one(getreg(REG_D5));
 
119
          GC_push_one(getreg(REG_D6));
 
120
          GC_push_one(getreg(REG_D7));
 
121
#         define HAVE_PUSH_REGS
 
122
#        endif /* !__GNUC__ */
 
123
#       endif /* AMIGA */
 
124
 
 
125
#       if defined(M68K) && defined(MACOS)
 
126
#       if defined(THINK_C)
 
127
#         define PushMacReg(reg) \
 
128
              move.l  reg,(sp) \
 
129
              jsr             GC_push_one
 
130
          asm {
 
131
              sub.w   #4,sp                   ; reserve space for one parameter.
 
132
              PushMacReg(a2);
 
133
              PushMacReg(a3);
 
134
              PushMacReg(a4);
 
135
              ; skip a5 (globals), a6 (frame pointer), and a7 (stack pointer)
 
136
              PushMacReg(d2);
 
137
              PushMacReg(d3);
 
138
              PushMacReg(d4);
 
139
              PushMacReg(d5);
 
140
              PushMacReg(d6);
 
141
              PushMacReg(d7);
 
142
              add.w   #4,sp                   ; fix stack.
 
143
          }
 
144
#         define HAVE_PUSH_REGS
 
145
#         undef PushMacReg
 
146
#       endif /* THINK_C */
 
147
#       if defined(__MWERKS__)
 
148
          PushMacRegisters();
 
149
#         define HAVE_PUSH_REGS
 
150
#       endif   /* __MWERKS__ */
 
151
#   endif       /* MACOS */
 
152
}
 
153
#endif /* !USE_ASM_PUSH_REGS */
 
154
 
 
155
#if defined(HAVE_PUSH_REGS) && defined(THREADS)
 
156
# error GC_push_regs cannot be used with threads
 
157
 /* Would fail for GC_do_blocking.  There are probably other safety     */
 
158
 /* issues.                                                             */
 
159
# undef HAVE_PUSH_REGS
 
160
#endif
 
161
 
 
162
#if !defined(HAVE_PUSH_REGS) && defined(UNIX_LIKE)
 
163
# include <ucontext.h>
 
164
#endif
 
165
 
 
166
/* Ensure that either registers are pushed, or callee-save registers    */
 
167
/* are somewhere on the stack, and then call fn(arg, ctxt).             */
 
168
/* ctxt is either a pointer to a ucontext_t we generated, or NULL.      */
 
169
void GC_with_callee_saves_pushed(void (*fn)(ptr_t, void *),
 
170
                                 ptr_t arg)
 
171
{
 
172
    word dummy;
 
173
    void * context = 0;
 
174
 
 
175
#   if defined(HAVE_PUSH_REGS)
 
176
      GC_push_regs();
 
177
#   elif defined(UNIX_LIKE) && !defined(DARWIN) && !defined(ARM32) && \
 
178
         !defined(HURD)
 
179
      /* Older versions of Darwin seem to lack getcontext(). */
 
180
      /* ARM Linux often doesn't support a real getcontext(). */
 
181
      ucontext_t ctxt;
 
182
      if (getcontext(&ctxt) < 0)
 
183
        ABORT ("Getcontext failed: Use another register retrieval method?");
 
184
      context = &ctxt;
 
185
#     if defined(SPARC) || defined(IA64)
 
186
        /* On a register window machine, we need to save register       */
 
187
        /* contents on the stack for this to work.  This may already be */
 
188
        /* subsumed by the getcontext() call.                           */
 
189
        {
 
190
          GC_save_regs_ret_val = GC_save_regs_in_stack();
 
191
        }
 
192
#     endif /* register windows. */
 
193
#   elif defined(HAVE_BUILTIN_UNWIND_INIT)
 
194
      /* This was suggested by Richard Henderson as the way to  */
 
195
      /* force callee-save registers and register windows onto  */
 
196
      /* the stack.                                             */
 
197
      __builtin_unwind_init();
 
198
#   else /* !HAVE_BUILTIN_UNWIND_INIT && !UNIX_LIKE  */
 
199
         /* && !HAVE_PUSH_REGS                       */
 
200
        /* Generic code                          */
 
201
        /* The idea is due to Parag Patel at HP. */
 
202
        /* We're not sure whether he would like  */
 
203
        /* to be he acknowledged for it or not.  */
 
204
        jmp_buf regs;
 
205
        register word * i = (word *) regs;
 
206
        register ptr_t lim = (ptr_t)(regs) + (sizeof regs);
 
207
  
 
208
        /* Setjmp doesn't always clear all of the buffer.               */
 
209
        /* That tends to preserve garbage.  Clear it.                   */
 
210
        for (; (char *)i < lim; i++) {
 
211
            *i = 0;
 
212
        }
 
213
#       if defined(MSWIN32) || defined(MSWINCE) \
 
214
                  || defined(UTS4) || defined(LINUX) || defined(EWS4800)
 
215
          (void) setjmp(regs);
 
216
#       else
 
217
          (void) _setjmp(regs);
 
218
          /* We don't want to mess with signals. According to   */
 
219
          /* SUSV3, setjmp() may or may not save signal mask.   */
 
220
          /* _setjmp won't, but is less portable.               */
 
221
#       endif
 
222
#   endif /* !HAVE_PUSH_REGS ... */
 
223
    /* FIXME: context here is sometimes just zero.  At the moment the callees   */
 
224
    /* don't really need it.                                                    */
 
225
    fn(arg, context);
 
226
    /* Strongly discourage the compiler from treating the above */
 
227
    /* as a tail-call, since that would pop the register        */
 
228
    /* contents before we get a chance to look at them.         */
 
229
    GC_noop1((word)(&dummy));
 
230
}
 
231
 
 
232
void GC_push_regs_and_stack(ptr_t cold_gc_frame)
 
233
{
 
234
    GC_with_callee_saves_pushed(GC_push_current_stack, cold_gc_frame);
 
235
}
 
236
 
 
237
#if defined(ASM_CLEAR_CODE)
 
238
# ifdef LINT
 
239
    /*ARGSUSED*/
 
240
    ptr_t GC_clear_stack_inner(arg, limit)
 
241
    ptr_t arg; word limit;
 
242
    { return(arg); }
 
243
    /* The real version is in a .S file */
 
244
# endif
 
245
#endif /* ASM_CLEAR_CODE */