aboutsummaryrefslogtreecommitdiffstats
path: root/src/grt/config
diff options
context:
space:
mode:
authorTristan Gingold <tgingold@free.fr>2014-11-05 05:11:00 +0100
committerTristan Gingold <tgingold@free.fr>2014-11-05 05:11:00 +0100
commit3fddf1c59fd7a8fcd260bb9e05c611bef3dd141b (patch)
treecbfe6d75f8e09db8b98f335406fb6ecb2fce3e0c /src/grt/config
parent0a088b311ed2fcebc542f8a2e42d09e2e3c9311c (diff)
downloadghdl-3fddf1c59fd7a8fcd260bb9e05c611bef3dd141b.tar.gz
ghdl-3fddf1c59fd7a8fcd260bb9e05c611bef3dd141b.tar.bz2
ghdl-3fddf1c59fd7a8fcd260bb9e05c611bef3dd141b.zip
Move files and dirs from translate/
Diffstat (limited to 'src/grt/config')
-rw-r--r--src/grt/config/Makefile14
-rw-r--r--src/grt/config/amd64.S131
-rw-r--r--src/grt/config/chkstk.S53
-rw-r--r--src/grt/config/clock.c43
-rw-r--r--src/grt/config/i386.S141
-rw-r--r--src/grt/config/ia64.S331
-rw-r--r--src/grt/config/linux.c361
-rw-r--r--src/grt/config/ppc.S334
-rw-r--r--src/grt/config/pthread.c239
-rw-r--r--src/grt/config/sparc.S141
-rw-r--r--src/grt/config/teststack.c174
-rw-r--r--src/grt/config/times.c55
-rw-r--r--src/grt/config/win32.c265
-rw-r--r--src/grt/config/win32thr.c167
14 files changed, 2449 insertions, 0 deletions
diff --git a/src/grt/config/Makefile b/src/grt/config/Makefile
new file mode 100644
index 000000000..7d5f57def
--- /dev/null
+++ b/src/grt/config/Makefile
@@ -0,0 +1,14 @@
+CFLAGS=-Wall -g
+
+#ARCH_OBJS=i386.o linux.o
+ARCH_OBJS=ppc.o linux.o
+
+teststack: teststack.o $(ARCH_OBJS)
+ $(CC) -o $@ $< $(ARCH_OBJS)
+
+ppc.o: ppc.S
+ $(CC) -c -o $@ -g $<
+
+clean:
+ $(RM) -f *.o *~ teststack
+
diff --git a/src/grt/config/amd64.S b/src/grt/config/amd64.S
new file mode 100644
index 000000000..0a7f0044b
--- /dev/null
+++ b/src/grt/config/amd64.S
@@ -0,0 +1,131 @@
+/* GRT stack implementation for amd64 (x86_64)
+ Copyright (C) 2005 - 2014 Tristan Gingold.
+
+ GHDL is free software; you can redistribute it and/or modify it under
+ the terms of the GNU General Public License as published by the Free
+ Software Foundation; either version 2, or (at your option) any later
+ version.
+
+ GHDL is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with GCC; see the file COPYING. If not, write to the Free
+ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
+ 02111-1307, USA.
+
+ As a special exception, if other files instantiate generics from this
+ unit, or you link this unit with other files to produce an executable,
+ this unit does not by itself cause the resulting executable to be
+ covered by the GNU General Public License. This exception does not
+ however invalidate any other reasons why the executable file might be
+ covered by the GNU Public License.
+*/
+ .file "amd64.S"
+
+#ifdef __ELF__
+#define ENTRY(func) .align 4; .globl func; .type func,@function; func:
+#define END(func) .size func, . - func
+#define NAME(name) name
+#elif __APPLE__
+#define ENTRY(func) .align 4; .globl _##func; _##func:
+#define END(func)
+#define NAME(name) _##name
+#else
+#define ENTRY(func) .align 4; func:
+#define END(func)
+#define NAME(name) name
+#endif
+ .text
+
+ /* Function called to loop on the process. */
+ENTRY(grt_stack_loop)
+ mov 0(%rsp),%rdi
+ call *8(%rsp)
+ jmp NAME(grt_stack_loop)
+END(grt_stack_loop)
+
+ /* function Stack_Create (Func : Address; Arg : Address)
+ return Stack_Type;
+ Args: FUNC (RDI), ARG (RSI)
+ */
+ENTRY(grt_stack_create)
+ /* Standard prologue. */
+ pushq %rbp
+ movq %rsp,%rbp
+ /* Save args. */
+ sub $0x10,%rsp
+ mov %rdi,-8(%rbp)
+ mov %rsi,-16(%rbp)
+
+ /* Allocate the stack, and exit in case of failure */
+ callq NAME(grt_stack_allocate)
+ test %rax,%rax
+ je .Ldone
+
+ /* Note: %RAX contains the address of the stack_context. This is
+ also the top of the stack. */
+
+ /* Prepare stack. */
+ /* The function to be executed. */
+ mov -8(%rbp), %rdi
+ mov %rdi, -8(%rax)
+ /* The argument. */
+ mov -16(%rbp), %rsi
+ mov %rsi, -16(%rax)
+ /* The return function. Must be 8 mod 16. */
+#if __APPLE__
+ movq _grt_stack_loop@GOTPCREL(%rip), %rsi
+ movq %rsi, -24(%rax)
+#else
+ movq $grt_stack_loop, -24(%rax)
+#endif
+ /* The context. */
+ mov %rbp, -32(%rax)
+ mov %rbx, -40(%rax)
+ mov %r12, -48(%rax)
+ mov %r13, -56(%rax)
+ mov %r14, -64(%rax)
+ mov %r15, -72(%rax)
+
+ /* Save the new stack pointer to the stack context. */
+ lea -72(%rax), %rsi
+ mov %rsi, (%rax)
+
+.Ldone:
+ leave
+ ret
+END(grt_stack_create)
+
+
+
+ /* Arguments: TO (RDI), FROM (RSI) [VAL (RDX)]
+ Both are pointers to a stack_context. */
+ENTRY(grt_stack_switch)
+ /* Save call-used registers. */
+ pushq %rbp
+ pushq %rbx
+ pushq %r12
+ pushq %r13
+ pushq %r14
+ pushq %r15
+ /* Save the current stack. */
+ movq %rsp, (%rsi)
+ /* Stack switch. */
+ movq (%rdi), %rsp
+ /* Restore call-used registers. */
+ popq %r15
+ popq %r14
+ popq %r13
+ popq %r12
+ popq %rbx
+ popq %rbp
+ /* Return val. */
+ movq %rdx, %rax
+ /* Run. */
+ ret
+END(grt_stack_switch)
+
+ .ident "Written by T.Gingold"
diff --git a/src/grt/config/chkstk.S b/src/grt/config/chkstk.S
new file mode 100644
index 000000000..ab244d0cd
--- /dev/null
+++ b/src/grt/config/chkstk.S
@@ -0,0 +1,53 @@
+/* GRT stack implementation for x86.
+ Copyright (C) 2002 - 2014 Tristan Gingold.
+
+ GHDL is free software; you can redistribute it and/or modify it under
+ the terms of the GNU General Public License as published by the Free
+ Software Foundation; either version 2, or (at your option) any later
+ version.
+
+ GHDL is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with GCC; see the file COPYING. If not, write to the Free
+ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
+ 02111-1307, USA.
+
+ As a special exception, if other files instantiate generics from this
+ unit, or you link this unit with other files to produce an executable,
+ this unit does not by itself cause the resulting executable to be
+ covered by the GNU General Public License. This exception does not
+ however invalidate any other reasons why the executable file might be
+ covered by the GNU Public License.
+*/
+ .file "chkstk.S"
+ .version "01.01"
+
+ .text
+
+#ifdef __APPLE__
+#define __chkstk ___chkstk
+#endif
+
+ /* Function called to loop on the process. */
+ .align 4
+#ifdef __ELF__
+ .type __chkstk,@function
+#endif
+ .globl __chkstk
+__chkstk:
+ testl %eax,%eax
+ je 0f
+ subl $4,%eax /* 4 bytes already used by call. */
+ subl %eax,%esp
+ jmp *(%esp,%eax)
+0:
+ ret
+#ifdef __ELF__
+ .size __chkstk, . - __chkstk
+#endif
+
+ .ident "Written by T.Gingold"
diff --git a/src/grt/config/clock.c b/src/grt/config/clock.c
new file mode 100644
index 000000000..242af604b
--- /dev/null
+++ b/src/grt/config/clock.c
@@ -0,0 +1,43 @@
+/* GRT C bindings for time.
+ Copyright (C) 2002 - 2014 Tristan Gingold.
+
+ GHDL is free software; you can redistribute it and/or modify it under
+ the terms of the GNU General Public License as published by the Free
+ Software Foundation; either version 2, or (at your option) any later
+ version.
+
+ GHDL is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with GCC; see the file COPYING. If not, write to the Free
+ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
+ 02111-1307, USA.
+
+ As a special exception, if other files instantiate generics from this
+ unit, or you link this unit with other files to produce an executable,
+ this unit does not by itself cause the resulting executable to be
+ covered by the GNU General Public License. This exception does not
+ however invalidate any other reasons why the executable file might be
+ covered by the GNU Public License.
+*/
+#include <time.h>
+
+int
+grt_get_clk_tck (void)
+{
+ return CLOCKS_PER_SEC;
+}
+
+void
+grt_get_times (int *wall, int *user, int *sys)
+{
+ clock_t res;
+
+ *wall = clock ();
+ *user = 0;
+ *sys = 0;
+}
+
diff --git a/src/grt/config/i386.S b/src/grt/config/i386.S
new file mode 100644
index 000000000..00d4719ac
--- /dev/null
+++ b/src/grt/config/i386.S
@@ -0,0 +1,141 @@
+/* GRT stack implementation for x86.
+ Copyright (C) 2002 - 2014 Tristan Gingold.
+
+ GHDL is free software; you can redistribute it and/or modify it under
+ the terms of the GNU General Public License as published by the Free
+ Software Foundation; either version 2, or (at your option) any later
+ version.
+
+ GHDL is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with GCC; see the file COPYING. If not, write to the Free
+ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
+ 02111-1307, USA.
+
+ As a special exception, if other files instantiate generics from this
+ unit, or you link this unit with other files to produce an executable,
+ this unit does not by itself cause the resulting executable to be
+ covered by the GNU General Public License. This exception does not
+ however invalidate any other reasons why the executable file might be
+ covered by the GNU Public License.
+*/
+ .file "i386.S"
+ .version "01.01"
+
+ .text
+
+#ifdef __ELF__
+#define ENTRY(func) .align 4; .globl func; .type func,@function; func:
+#define END(func) .size func, . - func
+#define NAME(name) name
+#elif __APPLE__
+#define ENTRY(func) .align 4; .globl _##func; _##func:
+#define END(func)
+#define NAME(name) _##name
+#else
+#define ENTRY(func) .align 4; func:
+#define END(func)
+#define NAME(name) name
+#endif
+
+ /* Function called to loop on the process. */
+ENTRY(grt_stack_loop)
+ call *4(%esp)
+ jmp NAME(grt_stack_loop)
+END(grt_stack_loop)
+
+ /* function Stack_Create (Func : Address; Arg : Address)
+ return Stack_Type;
+ */
+ENTRY(grt_stack_create)
+ /* Standard prologue. */
+ pushl %ebp
+ movl %esp,%ebp
+ /* Keep aligned (call + pushl + 8 = 16 bytes). */
+ subl $8,%esp
+
+ /* Allocate the stack, and exit in case of failure */
+ call NAME(grt_stack_allocate)
+ testl %eax,%eax
+ je .Ldone
+
+ /* Note: %EAX contains the address of the stack_context. This is
+ also the top of the stack. */
+
+ /* Prepare stack. */
+ /* The function to be executed. */
+ movl 8(%ebp), %ecx
+ movl %ecx, -4(%eax)
+ /* The argument. */
+ movl 12(%ebp), %ecx
+ movl %ecx, -8(%eax)
+ /* The return function. */
+#if __APPLE__
+ call ___x86.get_pc_thunk.cx
+L1$pb:
+ movl L_grt_stack_loop$non_lazy_ptr-L1$pb(%ecx), %ecx
+ movl %ecx,-12(%eax)
+#else
+ movl $NAME(grt_stack_loop), -12(%eax)
+#endif
+ /* The context. */
+ movl %ebx, -16(%eax)
+ movl %esi, -20(%eax)
+ movl %edi, -24(%eax)
+ movl %ebp, -28(%eax)
+
+ /* Save the new stack pointer to the stack context. */
+ leal -28(%eax), %ecx
+ movl %ecx, (%eax)
+
+.Ldone:
+ leave
+ ret
+END(grt_stack_create)
+
+
+ /* Arguments: TO, FROM
+ Both are pointers to a stack_context. */
+ENTRY(grt_stack_switch)
+ /* TO -> ECX. */
+ movl 4(%esp), %ecx
+ /* FROM -> EDX. */
+ movl 8(%esp), %edx
+ /* Save call-used registers. */
+ pushl %ebx
+ pushl %esi
+ pushl %edi
+ pushl %ebp
+ /* Save the current stack. */
+ movl %esp, (%edx)
+ /* Stack switch. */
+ movl (%ecx), %esp
+ /* Restore call-used registers. */
+ popl %ebp
+ popl %edi
+ popl %esi
+ popl %ebx
+ /* Run. */
+ ret
+END(grt_stack_switch)
+
+
+#if __APPLE__
+ .section __TEXT,__textcoal_nt,coalesced,pure_instructions
+ .weak_definition ___x86.get_pc_thunk.cx
+ .private_extern ___x86.get_pc_thunk.cx
+___x86.get_pc_thunk.cx:
+ movl (%esp), %ecx
+ ret
+
+ .section __IMPORT,__pointers,non_lazy_symbol_pointers
+L_grt_stack_loop$non_lazy_ptr:
+ .indirect_symbol _grt_stack_loop
+ .long 0
+#endif
+
+ .ident "Written by T.Gingold"
diff --git a/src/grt/config/ia64.S b/src/grt/config/ia64.S
new file mode 100644
index 000000000..9ce3800bb
--- /dev/null
+++ b/src/grt/config/ia64.S
@@ -0,0 +1,331 @@
+/* GRT stack implementation for ia64.
+ Copyright (C) 2002 - 2014 Tristan Gingold.
+
+ GHDL is free software; you can redistribute it and/or modify it under
+ the terms of the GNU General Public License as published by the Free
+ Software Foundation; either version 2, or (at your option) any later
+ version.
+
+ GHDL is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with GCC; see the file COPYING. If not, write to the Free
+ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
+ 02111-1307, USA.
+
+ As a special exception, if other files instantiate generics from this
+ unit, or you link this unit with other files to produce an executable,
+ this unit does not by itself cause the resulting executable to be
+ covered by the GNU General Public License. This exception does not
+ however invalidate any other reasons why the executable file might be
+ covered by the GNU Public License.
+*/
+ .file "ia64.S"
+ .pred.safe_across_calls p1-p5,p16-p63
+
+ .text
+ .align 16
+ .proc grt_stack_loop
+grt_stack_loop:
+ alloc r32 = ar.pfs, 0, 1, 1, 0
+ .body
+ ;;
+1: mov r33 = r4
+ br.call.sptk.many b0 = b1
+ ;;
+ br 1b
+ .endp
+
+ frame_size = 480
+
+ .global grt_stack_switch#
+ .proc grt_stack_switch#
+ /* r32: struct stack_context *TO, r33: struct stack_context *FROM. */
+ // Registers to be saved:
+ // ar.rsc, ar.bsp, ar.pfs, ar.lc, ar.rnat [5]
+ // gp, r4-r7 (+ Nat) [6]
+ // f2-f5, f16-f31 [20]
+ // p1-p5, p16-p63 [1] ???
+ // b1-b5 [5]
+ // f2-f5, f16-f31 [20*16]
+grt_stack_switch:
+ .prologue 2, 2
+ .vframe r2
+ {
+ alloc r31=ar.pfs, 2, 0, 0, 0
+ mov r14 = ar.rsc
+ adds r12 = -frame_size, r12
+ .body
+ ;;
+ }
+ // Save ar.rsc, ar.bsp, ar.pfs
+ {
+ st8 [r12] = r14 // sp + 0 <- ar.rsc
+ mov r15 = ar.bsp
+ adds r22 = (5*8), r12
+ ;;
+ }
+ {
+ st8.spill [r22] = r1, 8 // sp + 40 <- r1
+ ;;
+ st8.spill [r22] = r4, 8 // sp + 48 <- r4
+ adds r20 = 8, r12
+ ;;
+ }
+ st8 [r20] = r15, 8 // sp + 8 <- ar.bsp
+ st8.spill [r22] = r5, 8 // sp + 56 <- r5
+ mov r15 = ar.lc
+ ;;
+ {
+ st8 [r20] = r31, 8 // sp + 16 <- ar.pfs
+ // Flush dirty registers to the backing store
+ flushrs
+ mov r14 = b0
+ ;;
+ }
+ {
+ st8 [r20] = r15, 8 // sp + 24 <- ar.lc
+ // Set the RSE in enforced lazy mode.
+ mov ar.rsc = 0
+ ;;
+ }
+ {
+ // Save sp.
+ st8 [r33] = r12
+ mov r15 = ar.rnat
+ mov r16 = b1
+ ;;
+ }
+ {
+ st8.spill [r22] = r6, 8 // sp + 64 <- r6
+ st8 [r20] = r15, 64 // sp + 32 <- ar.rnat
+ ;;
+ }
+ {
+ st8.spill [r22] = r7, 16 // sp + 72 <- r7
+ st8 [r20] = r14, 8 // sp + 96 <- b0
+ mov r15 = b2
+ ;;
+ }
+ {
+ mov r17 = ar.unat
+ ;;
+ st8 [r22] = r17, 24 // sp + 88 <- ar.unat
+ mov r14 = b3
+ ;;
+ }
+ {
+ st8 [r20] = r16, 16 // sp + 104 <- b1
+ st8 [r22] = r15, 16 // sp + 112 <- b2
+ mov r17 = b4
+ ;;
+ }
+ {
+ st8 [r20] = r14, 16 // sp + 120 <- b3
+ st8 [r22] = r17, 16 // sp + 128 <- b4
+ mov r15 = b5
+ ;;
+ }
+ {
+ // Read new sp.
+ ld8 r21 = [r32]
+ ;;
+ st8 [r20] = r15, 24 // sp + 136 <- b5
+ mov r14 = pr
+ ;;
+ }
+ ;;
+ st8 [r22] = r14, 32 // sp + 144 <- pr
+ stf.spill [r20] = f2, 32 // sp + 160 <- f2
+ ;;
+ stf.spill [r22] = f3, 32 // sp + 176 <- f3
+ stf.spill [r20] = f4, 32 // sp + 192 <- f4
+ ;;
+ stf.spill [r22] = f5, 32 // sp + 208 <- f5
+ stf.spill [r20] = f16, 32 // sp + 224 <- f16
+ ;;
+ stf.spill [r22] = f17, 32 // sp + 240 <- f17
+ stf.spill [r20] = f18, 32 // sp + 256 <- f18
+ ;;
+ stf.spill [r22] = f19, 32 // sp + 272 <- f19
+ stf.spill [r20] = f20, 32 // sp + 288 <- f20
+ ;;
+ stf.spill [r22] = f21, 32 // sp + 304 <- f21
+ stf.spill [r20] = f22, 32 // sp + 320 <- f22
+ ;;
+ stf.spill [r22] = f23, 32 // sp + 336 <- f23
+ stf.spill [r20] = f24, 32 // sp + 352 <- f24
+ ;;
+ stf.spill [r22] = f25, 32 // sp + 368 <- f25
+ stf.spill [r20] = f26, 32 // sp + 384 <- f26
+ ;;
+ stf.spill [r22] = f27, 32 // sp + 400 <- f27
+ stf.spill [r20] = f28, 32 // sp + 416 <- f28
+ ;;
+ stf.spill [r22] = f29, 32 // sp + 432 <- f29
+ stf.spill [r20] = f30, 32 // sp + 448 <- f30
+ ;;
+ {
+ stf.spill [r22] = f31, 32 // sp + 464 <- f31
+ invala
+ adds r20 = 8, r21
+ ;;
+ }
+ ld8 r14 = [r21], 88 // sp + 0 (ar.rsc)
+ ld8 r16 = [r20], 8 // sp + 8 (ar.bsp)
+ ;;
+ ld8 r15 = [r21], -56 // sp + 88 (ar.unat)
+ ;;
+ ld8 r18 = [r20], 8 // sp + 16 (ar.pfs)
+ mov ar.unat = r15
+ ld8 r17 = [r21], 8 // sp + 32 (ar.rnat)
+ ;;
+ ld8 r15 = [r20], 72 // sp + 24 (ar.lc)
+ ld8.fill r1 = [r21], 8 // sp + 40 (r1)
+ mov ar.bspstore = r16
+ ;;
+ ld8.fill r4 = [r21], 8 // sp + 48 (r4)
+ mov ar.pfs = r18
+ mov ar.rnat = r17
+ ;;
+ mov ar.rsc = r14
+ mov ar.lc = r15
+ ld8 r17 = [r20], 8 // sp + 96 (b0)
+ ;;
+ {
+ ld8.fill r5 = [r21], 8 // sp + 56 (r5)
+ ld8 r14 = [r20], 8 // sp + 104 (b1)
+ mov b0 = r17
+ ;;
+ }
+ {
+ ld8.fill r6 = [r21], 8 // sp + 64 (r6)
+ ld8 r15 = [r20], 8 // sp + 112 (b2)
+ mov b1 = r14
+ ;;
+ }
+ ld8.fill r7 = [r21], 64 // sp + 72 (r7)
+ ld8 r14 = [r20], 8 // sp + 120 (b3)
+ mov b2 = r15
+ ;;
+ ld8 r15 = [r20], 16 // sp + 128 (b4)
+ ld8 r16 = [r21], 40 // sp + 136 (b5)
+ mov b3 = r14
+ ;;
+ {
+ ld8 r14 = [r20], 16 // sp + 144 (pr)
+ ;;
+ ldf.fill f2 = [r20], 32 // sp + 160 (f2)
+ mov b4 = r15
+ ;;
+ }
+ ldf.fill f3 = [r21], 32 // sp + 176 (f3)
+ ldf.fill f4 = [r20], 32 // sp + 192 (f4)
+ mov b5 = r16
+ ;;
+ ldf.fill f5 = [r21], 32 // sp + 208 (f5)
+ ldf.fill f16 = [r20], 32 // sp + 224 (f16)
+ mov pr = r14, -1
+ ;;
+ ldf.fill f17 = [r21], 32 // sp + 240 (f17)
+ ldf.fill f18 = [r20], 32 // sp + 256 (f18)
+ ;;
+ ldf.fill f19 = [r21], 32 // sp + 272 (f19)
+ ldf.fill f20 = [r20], 32 // sp + 288 (f20)
+ ;;
+ ldf.fill f21 = [r21], 32 // sp + 304 (f21)
+ ldf.fill f22 = [r20], 32 // sp + 320 (f22)
+ ;;
+ ldf.fill f23 = [r21], 32 // sp + 336 (f23)
+ ldf.fill f24 = [r20], 32 // sp + 352 (f24)
+ ;;
+ ldf.fill f25 = [r21], 32 // sp + 368 (f25)
+ ldf.fill f26 = [r20], 32 // sp + 384 (f26)
+ ;;
+ ldf.fill f27 = [r21], 32 // sp + 400 (f27)
+ ldf.fill f28 = [r20], 32 // sp + 416 (f28)
+ ;;
+ ldf.fill f29 = [r21], 32 // sp + 432 (f29)
+ ldf.fill f30 = [r20], 32 // sp + 448 (f30)
+ ;;
+ ldf.fill f31 = [r21], 32 // sp + 464 (f31)
+ mov r12 = r20
+ br.ret.sptk.many b0
+ ;;
+ .endp grt_stack_switch#
+
+ .align 16
+ // r32: func, r33: arg
+ .global grt_stack_create#
+ .proc grt_stack_create#
+grt_stack_create:
+ .prologue 14, 34
+ .save ar.pfs, r35
+ alloc r35 = ar.pfs, 2, 3, 0, 0
+ .save rp, r34
+ // Compute backing store.
+ movl r14 = stack_max_size
+ ;;
+ .body
+ {
+ ld4 r36 = [r14] // r14: bsp
+ mov r34 = b0
+ br.call.sptk.many b0 = grt_stack_allocate#
+ ;;
+ }
+ {
+ ld8 r22 = [r32], 8 // read ip (-> b1)
+ ;;
+ ld8 r23 = [r32] // read r1 from func
+ adds r21 = -(frame_size + 16) + 32, r8
+ ;;
+ }
+ {
+ st8 [r21] = r0, -32 // sp + 32 (ar.rnat = 0)
+ ;;
+ st8 [r8] = r21 // Save cur_sp
+ mov r18 = 0x0f // ar.rsc: LE, PL=3, Eager
+ ;;
+ }
+ {
+ st8 [r21] = r18, 40 // sp + 0 (ar.rsc)
+ ;;
+ st8 [r21] = r23, 64 // sp + 40 (r1 = func.r1)
+ mov b0 = r34
+ ;;
+ }
+ {
+ st8 [r21] = r22, -96 // sp + 104 (b1 = func.ip)
+ movl r15 = grt_stack_loop
+ ;;
+ }
+ sub r14 = r8, r36 // Backing store base
+ ;;
+ adds r14 = 16, r14 // Add sizeof (stack_context)
+ adds r20 = 40, r21
+ ;;
+ {
+ st8 [r21] = r14, 88 // sp + 8 (ar.bsp)
+ ;;
+ st8 [r21] = r15, -80 // sp + 96 (b0 = grt_stack_loop)
+ mov r16 = (0 << 7) | 1 // CFM: sol=0, sof=1
+ ;;
+ }
+ {
+ st8 [r21] = r16, 8 // sp + 16 (ar.pfs)
+ ;;
+ st8 [r21] = r0, 24 // sp + 24 (ar.lc)
+ mov ar.pfs = r35
+ ;;
+ }
+ {
+ st8 [r20] = r0, 8 // sp + 32 (ar.rnat)
+ st8 [r21] = r33 // sp + 48 (r4 = arg)
+ br.ret.sptk.many b0
+ ;;
+ }
+ .endp grt_stack_create#
+ .ident "GCC: (GNU) 4.0.2"
diff --git a/src/grt/config/linux.c b/src/grt/config/linux.c
new file mode 100644
index 000000000..74dce0903
--- /dev/null
+++ b/src/grt/config/linux.c
@@ -0,0 +1,361 @@
+/* GRT stacks implementation for linux and other *nix.
+ Copyright (C) 2002 - 2014 Tristan Gingold.
+
+ GHDL is free software; you can redistribute it and/or modify it under
+ the terms of the GNU General Public License as published by the Free
+ Software Foundation; either version 2, or (at your option) any later
+ version.
+
+ GHDL is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with GCC; see the file COPYING. If not, write to the Free
+ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
+ 02111-1307, USA.
+
+ As a special exception, if other files instantiate generics from this
+ unit, or you link this unit with other files to produce an executable,
+ this unit does not by itself cause the resulting executable to be
+ covered by the GNU General Public License. This exception does not
+ however invalidate any other reasons why the executable file might be
+ covered by the GNU Public License.
+*/
+#define _GNU_SOURCE
+#include <unistd.h>
+#include <sys/mman.h>
+#include <signal.h>
+#include <fcntl.h>
+#include <sys/ucontext.h>
+#include <stdlib.h>
+//#include <stdint.h>
+
+#ifdef __APPLE__
+#define MAP_ANONYMOUS MAP_ANON
+#endif
+
+/* On x86, the stack growns downward. */
+#define STACK_GROWNS_DOWNWARD 1
+
+#ifdef __linux__
+/* If set, SIGSEGV is caught in order to automatically grow the stacks. */
+#define EXTEND_STACK 1
+#define STACK_SIGNAL SIGSEGV
+#endif
+#ifdef __FreeBSD__
+/* If set, SIGSEGV is caught in order to automatically grow the stacks. */
+#define EXTEND_STACK 1
+#define STACK_SIGNAL SIGSEGV
+#endif
+#ifdef __APPLE__
+/* If set, SIGSEGV is caught in order to automatically grow the stacks. */
+#define EXTEND_STACK 1
+#define STACK_SIGNAL SIGBUS
+#endif
+
+/* Defined in Grt.Options. */
+extern unsigned int stack_size;
+extern unsigned int stack_max_size;
+
+/* Size of a memory page. */
+static size_t page_size;
+
+extern void grt_stack_error_grow_failed (void);
+extern void grt_stack_error_null_access (void);
+extern void grt_stack_error_memory_access (void);
+extern void grt_overflow_error (void);
+
+/* Definitions:
+ The base of the stack is the address before the first available byte on the
+ stack. If the stack grows downward, the base is equal to the high bound.
+*/
+
+/* Per stack context.
+ This context is allocated at the top (or bottom if the stack grows
+ upward) of the stack.
+ Therefore, the base of the stack can be easily deduced from the context. */
+struct stack_context
+{
+ /* The current stack pointer. */
+ void *cur_sp;
+ /* The current stack length. */
+ size_t cur_length;
+};
+
+/* If MAP_ANONYMOUS is not defined, use /dev/zero. */
+#ifndef MAP_ANONYMOUS
+#define USE_DEV_ZERO
+static int dev_zero_fd;
+#define MAP_ANONYMOUS 0
+#define MMAP_FILEDES dev_zero_fd
+#else
+#define MMAP_FILEDES -1
+#endif
+
+#if EXTEND_STACK
+/* This is the current process being run. */
+extern struct stack_context *grt_get_current_process (void);
+
+/* Stack used for signals.
+ The stack must be different from the running stack, because we want to be
+ able to extend the running stack. When the stack need to be extended, the
+ current stack pointer does not point to a valid address. Therefore, the
+ stack cannot be used or else a second SIGSEGV is generated while the
+ arguments are pushed. */
+static unsigned long sig_stack[SIGSTKSZ / sizeof (long)];
+
+/* Signal stack descriptor. */
+static stack_t sig_stk;
+
+static struct sigaction prev_sigsegv_act;
+static struct sigaction sigsegv_act;
+
+/* The following code assumes stack grows downward. */
+#if !STACK_GROWNS_DOWNWARD
+#error "Not implemented"
+#endif
+
+#ifdef __APPLE__
+/* Handler for SIGFPE signal, raised in case of overflow (i386). */
+static void grt_overflow_handler (int signo, siginfo_t *info, void *ptr)
+{
+ grt_overflow_error ();
+}
+#endif
+
+/* Handler for SIGSEGV signal, which grow the stack. */
+static void grt_sigsegv_handler (int signo, siginfo_t *info, void *ptr)
+{
+ static int in_handler;
+ void *addr;
+ struct stack_context *ctxt;
+ void *stack_high;
+ void *stack_low;
+ void *n_low;
+ size_t n_len;
+ ucontext_t *uctxt = (ucontext_t *)ptr;
+
+ in_handler++;
+
+#ifdef __linux__
+#ifdef __i386__
+ /* Linux generates a SIGSEGV (!) for an overflow exception. */
+ if (uctxt->uc_mcontext.gregs[REG_TRAPNO] == 4)
+ {
+ grt_overflow_error ();
+ }
+#endif
+#endif
+
+ if (info == NULL || grt_get_current_process () == NULL || in_handler > 1)
+ {
+ /* We loose. */
+ sigaction (STACK_SIGNAL, &prev_sigsegv_act, NULL);
+ return;
+ }
+
+ addr = info->si_addr;
+
+ /* Check ADDR belong to the stack. */
+ ctxt = grt_get_current_process ()->cur_sp;
+ stack_high = (void *)(ctxt + 1);
+ stack_low = stack_high - stack_max_size;
+ if (addr > stack_high || addr < stack_low)
+ {
+ /* Out of the stack. */
+ if (addr < (void *)page_size)
+ grt_stack_error_null_access ();
+ else
+ grt_stack_error_memory_access ();
+ }
+ /* Compute the address of the faulting page. */
+ n_low = (void *)((unsigned long)addr & ~(page_size - 1));
+
+ /* Should not happen. */
+ if (n_low < stack_low)
+ abort ();
+
+ /* Allocate one more page, if possible. */
+ if (n_low != stack_low)
+ n_low -= page_size;
+
+ /* Compute the new length. */
+ n_len = stack_high - n_low;
+
+ if (mmap (n_low, n_len - ctxt->cur_length, PROT_READ | PROT_WRITE,
+ MAP_FIXED | MAP_PRIVATE | MAP_ANONYMOUS, MMAP_FILEDES, 0)
+ != n_low)
+ {
+ /* Cannot grow the stack. */
+ grt_stack_error_grow_failed ();
+ }
+
+ ctxt->cur_length = n_len;
+
+ sigaction (STACK_SIGNAL, &sigsegv_act, NULL);
+
+ in_handler--;
+
+ /* Hopes we can resume! */
+ return;
+}
+
+static void grt_signal_setup (void)
+{
+ sigsegv_act.sa_sigaction = &grt_sigsegv_handler;
+ sigemptyset (&sigsegv_act.sa_mask);
+ sigsegv_act.sa_flags = SA_ONSTACK | SA_SIGINFO;
+#ifdef SA_ONESHOT
+ sigsegv_act.sa_flags |= SA_ONESHOT;
+#elif defined (SA_RESETHAND)
+ sigsegv_act.sa_flags |= SA_RESETHAND;
+#endif
+
+ /* Use an alternate stack during signals. */
+ sig_stk.ss_sp = sig_stack;
+ sig_stk.ss_size = sizeof (sig_stack);
+ sig_stk.ss_flags = 0;
+ sigaltstack (&sig_stk, NULL);
+
+ /* We don't care about the return status.
+ If the handler is not installed, then some feature are lost. */
+ sigaction (STACK_SIGNAL, &sigsegv_act, &prev_sigsegv_act);
+
+#ifdef __APPLE__
+ {
+ struct sigaction sig_ovf_act;
+
+ sig_ovf_act.sa_sigaction = &grt_overflow_handler;
+ sigemptyset (&sig_ovf_act.sa_mask);
+ sig_ovf_act.sa_flags = SA_SIGINFO;
+
+ sigaction (SIGFPE, &sig_ovf_act, NULL);
+ }
+#endif
+}
+#endif
+
+/* Context for the main stack. */
+#ifdef USE_THREADS
+#define THREAD __thread
+#else
+#define THREAD
+#endif
+static THREAD struct stack_context main_stack_context;
+
+extern void grt_set_main_stack (struct stack_context *stack);
+
+void
+grt_stack_new_thread (void)
+{
+ main_stack_context.cur_sp = NULL;
+ main_stack_context.cur_length = 0;
+ grt_set_main_stack (&main_stack_context);
+}
+
+void
+grt_stack_init (void)
+{
+ size_t pg_round;
+
+ page_size = getpagesize ();
+ pg_round = page_size - 1;
+
+ /* Align size. */
+ stack_size = (stack_size + pg_round) & ~pg_round;
+ stack_max_size = (stack_max_size + pg_round) & ~pg_round;
+
+ /* Set mimum values. */
+ if (stack_size < 2 * page_size)
+ stack_size = 2 * page_size;
+ if (stack_max_size < (stack_size + 2 * page_size))
+ stack_max_size = stack_size + 2 * page_size;
+
+ /* Initialize the main stack context. */
+ main_stack_context.cur_sp = NULL;
+ main_stack_context.cur_length = 0;
+ grt_set_main_stack (&main_stack_context);
+
+#ifdef USE_DEV_ZERO
+ dev_zero_fd = open ("/dev/zero", O_RDWR);
+ if (dev_zero_fd < 0)
+ abort ();
+#endif
+
+#if EXTEND_STACK
+ grt_signal_setup ();
+#endif
+}
+
+/* Allocate a stack.
+ Called by i386.S */
+struct stack_context *
+grt_stack_allocate (void)
+{
+ struct stack_context *res;
+ void *r;
+ void *base;
+
+ /* Allocate the stack, but without any rights. This is a guard. */
+ base = (void *)mmap (NULL, stack_max_size, PROT_NONE,
+ MAP_PRIVATE | MAP_ANONYMOUS, MMAP_FILEDES, 0);
+
+ if (base == (void *)-1)
+ return NULL;
+
+ /* Set rights on the allocated stack. */
+#if STACK_GROWNS_DOWNWARD
+ r = base + stack_max_size - stack_size;
+#else
+ r = base;
+#endif
+ if (mmap (r, stack_size, PROT_READ | PROT_WRITE,
+ MAP_FIXED | MAP_PRIVATE | MAP_ANONYMOUS, MMAP_FILEDES, 0)
+ != r)
+ return NULL;
+
+#if STACK_GROWNS_DOWNWARD
+ res = (struct stack_context *)
+ (base + stack_max_size - sizeof (struct stack_context));
+#else
+ res = (struct stack_context *)(base + sizeof (struct stack_context));
+#endif
+
+#ifdef __ia64__
+ /* Also allocate BSP. */
+ if (mmap (base, page_size, PROT_READ | PROT_WRITE,
+ MAP_FIXED | MAP_PRIVATE | MAP_ANONYMOUS, MMAP_FILEDES, 0) != base)
+ return NULL;
+#endif
+
+ res->cur_sp = (void *)res;
+ res->cur_length = stack_size;
+ return res;
+}
+
+#include <setjmp.h>
+static int run_env_en;
+static jmp_buf run_env;
+
+void
+__ghdl_maybe_return_via_longjump (int val)
+{
+ if (run_env_en)
+ longjmp (run_env, val);
+}
+
+int
+__ghdl_run_through_longjump (int (*func)(void))
+{
+ int res;
+
+ run_env_en = 1;
+ res = setjmp (run_env);
+ if (res == 0)
+ res = (*func)();
+ run_env_en = 0;
+ return res;
+}
+
diff --git a/src/grt/config/ppc.S b/src/grt/config/ppc.S
new file mode 100644
index 000000000..bedd48ab4
--- /dev/null
+++ b/src/grt/config/ppc.S
@@ -0,0 +1,334 @@
+/* GRT stack implementation for ppc.
+ Copyright (C) 2005 - 2014 Tristan Gingold.
+
+ GHDL is free software; you can redistribute it and/or modify it under
+ the terms of the GNU General Public License as published by the Free
+ Software Foundation; either version 2, or (at your option) any later
+ version.
+
+ GHDL is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with GCC; see the file COPYING. If not, write to the Free
+ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
+ 02111-1307, USA.
+
+ As a special exception, if other files instantiate generics from this
+ unit, or you link this unit with other files to produce an executable,
+ this unit does not by itself cause the resulting executable to be
+ covered by the GNU General Public License. This exception does not
+ however invalidate any other reasons why the executable file might be
+ covered by the GNU Public License.
+*/
+ .file "ppc.S"
+
+ .section ".text"
+
+#define OFF 240
+
+#define GREG(x) x
+#define FREG(x) x
+
+#define r0 GREG(0)
+#define r1 GREG(1)
+#define r2 GREG(2)
+#define r3 GREG(3)
+#define r4 GREG(4)
+#define r5 GREG(5)
+#define r6 GREG(6)
+#define r7 GREG(7)
+#define r8 GREG(8)
+#define r9 GREG(9)
+#define r10 GREG(10)
+#define r11 GREG(11)
+#define r12 GREG(12)
+#define r13 GREG(13)
+#define r14 GREG(14)
+#define r15 GREG(15)
+#define r16 GREG(16)
+#define r17 GREG(17)
+#define r18 GREG(18)
+#define r19 GREG(19)
+#define r20 GREG(20)
+#define r21 GREG(21)
+#define r22 GREG(22)
+#define r23 GREG(23)
+#define r24 GREG(24)
+#define r25 GREG(25)
+#define r26 GREG(26)
+#define r27 GREG(27)
+#define r28 GREG(28)
+#define r29 GREG(29)
+#define r30 GREG(30)
+#define r31 GREG(31)
+
+#define f0 FREG(0)
+#define f1 FREG(1)
+#define f2 FREG(2)
+#define f3 FREG(3)
+#define f4 FREG(4)
+#define f5 FREG(5)
+#define f6 FREG(6)
+#define f7 FREG(7)
+#define f8 FREG(8)
+#define f9 FREG(9)
+#define f10 FREG(10)
+#define f11 FREG(11)
+#define f12 FREG(12)
+#define f13 FREG(13)
+#define f14 FREG(14)
+#define f15 FREG(15)
+#define f16 FREG(16)
+#define f17 FREG(17)
+#define f18 FREG(18)
+#define f19 FREG(19)
+#define f20 FREG(20)
+#define f21 FREG(21)
+#define f22 FREG(22)
+#define f23 FREG(23)
+#define f24 FREG(24)
+#define f25 FREG(25)
+#define f26 FREG(26)
+#define f27 FREG(27)
+#define f28 FREG(28)
+#define f29 FREG(29)
+#define f30 FREG(30)
+#define f31 FREG(31)
+
+ /* Stack structure is:
+ +4 : cur_length \ Stack
+ +0 : cur_sp / Context
+ -4 : arg
+ -8 : func
+
+ -12: pad
+ -16: pad
+ -20: LR save word
+ -24: Back chain
+
+ -28: fp/gp saved registers.
+ -4 : return address
+ -8 : process function to be executed
+ -12: function argument
+ ...
+ -72: %sp
+ */
+
+ /* Function called to loop on the process. */
+ .align 4
+ .type grt_stack_loop,@function
+grt_stack_loop:
+ /* Get function. */
+ lwz r0,16(r1)
+ /* Get argument. */
+ lwz r3,20(r1)
+ mtlr r0
+ blrl
+ b grt_stack_loop
+ .size grt_stack_loop, . - grt_stack_loop
+
+ /* function Stack_Create (Func : Address; Arg : Address)
+ return Stack_Type; */
+ .align 4
+ .global grt_stack_create
+ .type grt_stack_create,@function
+grt_stack_create:
+ /* Standard prologue. */
+ stwu r1,-32(r1)
+ mflr r0
+ stw r0,36(r1)
+
+ /* Save arguments. */
+ stw r3,24(r1)
+ stw r4,28(r1)
+
+ /* Allocate the stack, and exit in case of failure */
+ bl grt_stack_allocate
+ cmpwi 0,r3,0
+ beq- .Ldone
+
+ /* Note: r3 contains the address of the stack_context. This is
+ also the top of the stack. */
+
+ /* Prepare stack. */
+ /* Align the stack. */
+ addi r5,r3,-24
+
+ /* Save the parameters. */
+ lwz r6,24(r1)
+ stw r6,16(r5)
+ lwz r7,28(r1)
+ stw r7,20(r5)
+
+ /* The return function. */
+ lis r4,grt_stack_loop@ha
+ la r4,grt_stack_loop@l(r4)
+ stw r4,4(r5)
+ /* Back-Chain. */
+ addi r4,r1,32
+ stw r4,0(r5)
+
+ /* Save register.
+ They should be considered as garbage. */
+ addi r4,r5,-OFF
+
+ stfd f31,(OFF - 8)(r4)
+ stfd f30,(OFF - 16)(r4)
+ stfd f29,(OFF - 24)(r4)
+ stfd f28,(OFF - 32)(r4)
+ stfd f27,(OFF - 40)(r4)
+ stfd f26,(OFF - 48)(r4)
+ stfd f25,(OFF - 56)(r4)
+ stfd f24,(OFF - 64)(r4)
+ stfd f23,(OFF - 72)(r4)
+ stfd f22,(OFF - 80)(r4)
+ stfd f21,(OFF - 88)(r4)
+ stfd f20,(OFF - 96)(r4)
+ stfd f19,(OFF - 104)(r4)
+ stfd f18,(OFF - 112)(r4)
+ stfd f17,(OFF - 120)(r4)
+ stfd f16,(OFF - 128)(r4)
+ stfd f15,(OFF - 136)(r4)
+ stfd f14,(OFF - 144)(r4)
+ stw r31,(OFF - 148)(r4)
+ stw r30,(OFF - 152)(r4)
+ stw r29,(OFF - 156)(r4)
+ stw r28,(OFF - 160)(r4)
+ stw r27,(OFF - 164)(r4)
+ stw r26,(OFF - 168)(r4)
+ stw r25,(OFF - 172)(r4)
+ stw r24,(OFF - 176)(r4)
+ stw r23,(OFF - 180)(r4)
+ stw r22,(OFF - 184)(r4)
+ stw r21,(OFF - 188)(r4)
+ stw r20,(OFF - 192)(r4)
+ stw r19,(OFF - 196)(r4)
+ stw r18,(OFF - 200)(r4)
+ stw r17,(OFF - 204)(r4)
+ stw r16,(OFF - 208)(r4)
+ stw r15,(OFF - 212)(r4)
+ stw r14,(OFF - 216)(r4)
+ mfcr r0
+ stw r0, (OFF - 220)(r4)
+
+ /* Save stack pointer. */
+ stw r4, 0(r3)
+
+.Ldone:
+ lwz r0,36(r1)
+ mtlr r0
+ addi r1,r1,32
+ blr
+ .size grt_stack_create,. - grt_stack_create
+
+
+ .align 4
+ .global grt_stack_switch
+ /* Arguments: TO, FROM.
+ Both are pointers to a stack_context. */
+ .type grt_stack_switch,@function
+grt_stack_switch:
+ /* Standard prologue, save return address. */
+ stwu r1,(-OFF)(r1)
+ mflr r0
+ stw r0,(OFF + 4)(r1)
+
+ /* Save r14-r31, f14-f31, CR
+ This is 18 words + 18 double words, ie 216 bytes. */
+ /* Maybe use the savefpr function ? */
+ stfd f31,(OFF - 8)(r1)
+ stfd f30,(OFF - 16)(r1)
+ stfd f29,(OFF - 24)(r1)
+ stfd f28,(OFF - 32)(r1)
+ stfd f27,(OFF - 40)(r1)
+ stfd f26,(OFF - 48)(r1)
+ stfd f25,(OFF - 56)(r1)
+ stfd f24,(OFF - 64)(r1)
+ stfd f23,(OFF - 72)(r1)
+ stfd f22,(OFF - 80)(r1)
+ stfd f21,(OFF - 88)(r1)
+ stfd f20,(OFF - 96)(r1)
+ stfd f19,(OFF - 104)(r1)
+ stfd f18,(OFF - 112)(r1)
+ stfd f17,(OFF - 120)(r1)
+ stfd f16,(OFF - 128)(r1)
+ stfd f15,(OFF - 136)(r1)
+ stfd f14,(OFF - 144)(r1)
+ stw r31,(OFF - 148)(r1)
+ stw r30,(OFF - 152)(r1)
+ stw r29,(OFF - 156)(r1)
+ stw r28,(OFF - 160)(r1)
+ stw r27,(OFF - 164)(r1)
+ stw r26,(OFF - 168)(r1)
+ stw r25,(OFF - 172)(r1)
+ stw r24,(OFF - 176)(r1)
+ stw r23,(OFF - 180)(r1)
+ stw r22,(OFF - 184)(r1)
+ stw r21,(OFF - 188)(r1)
+ stw r20,(OFF - 192)(r1)
+ stw r19,(OFF - 196)(r1)
+ stw r18,(OFF - 200)(r1)
+ stw r17,(OFF - 204)(r1)
+ stw r16,(OFF - 208)(r1)
+ stw r15,(OFF - 212)(r1)
+ stw r14,(OFF - 216)(r1)
+ mfcr r0
+ stw r0, (OFF - 220)(r1)
+
+ /* Save stack pointer. */
+ stw r1, 0(r4)
+
+ /* Load stack pointer. */
+ lwz r1, 0(r3)
+
+
+ lfd f31,(OFF - 8)(r1)
+ lfd f30,(OFF - 16)(r1)
+ lfd f29,(OFF - 24)(r1)
+ lfd f28,(OFF - 32)(r1)
+ lfd f27,(OFF - 40)(r1)
+ lfd f26,(OFF - 48)(r1)
+ lfd f25,(OFF - 56)(r1)
+ lfd f24,(OFF - 64)(r1)
+ lfd f23,(OFF - 72)(r1)
+ lfd f22,(OFF - 80)(r1)
+ lfd f21,(OFF - 88)(r1)
+ lfd f20,(OFF - 96)(r1)
+ lfd f19,(OFF - 104)(r1)
+ lfd f18,(OFF - 112)(r1)
+ lfd f17,(OFF - 120)(r1)
+ lfd f16,(OFF - 128)(r1)
+ lfd f15,(OFF - 136)(r1)
+ lfd f14,(OFF - 144)(r1)
+ lwz r31,(OFF - 148)(r1)
+ lwz r30,(OFF - 152)(r1)
+ lwz r29,(OFF - 156)(r1)
+ lwz r28,(OFF - 160)(r1)
+ lwz r27,(OFF - 164)(r1)
+ lwz r26,(OFF - 168)(r1)
+ lwz r25,(OFF - 172)(r1)
+ lwz r24,(OFF - 176)(r1)
+ lwz r23,(OFF - 180)(r1)
+ lwz r22,(OFF - 184)(r1)
+ lwz r21,(OFF - 188)(r1)
+ lwz r20,(OFF - 192)(r1)
+ lwz r19,(OFF - 196)(r1)
+ lwz r18,(OFF - 200)(r1)
+ lwz r17,(OFF - 204)(r1)
+ lwz r16,(OFF - 208)(r1)
+ lwz r15,(OFF - 212)(r1)
+ lwz r14,(OFF - 216)(r1)
+ lwz r0, (OFF - 220)(r1)
+ mtcr r0
+
+ lwz r0,(OFF + 4)(r1)
+ mtlr r0
+ addi r1,r1,OFF
+ blr
+ .size grt_stack_switch, . - grt_stack_switch
+
+
+ .ident "Written by T.Gingold"
diff --git a/src/grt/config/pthread.c b/src/grt/config/pthread.c
new file mode 100644
index 000000000..189ae90c8
--- /dev/null
+++ b/src/grt/config/pthread.c
@@ -0,0 +1,239 @@
+/* GRT stack implementation based on pthreads.
+ Copyright (C) 2003 - 2014 Felix Bertram & Tristan Gingold.
+
+ GHDL is free software; you can redistribute it and/or modify it under
+ the terms of the GNU General Public License as published by the Free
+ Software Foundation; either version 2, or (at your option) any later
+ version.
+
+ GHDL is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with GCC; see the file COPYING. If not, write to the Free
+ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
+ 02111-1307, USA.
+*/
+//-----------------------------------------------------------------------------
+// Project: GHDL - VHDL Simulator
+// Description: pthread port of stacks package, for use with MacOSX
+// Note: Tristan's original i386/Linux used assembly-code
+// to manually switch stacks for performance reasons.
+// History: 2003may22, FB, created.
+//-----------------------------------------------------------------------------
+
+#include <pthread.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <setjmp.h>
+#include <assert.h>
+
+//#define INFO printf
+#define INFO (void)
+
+// GHDL names an endless loop calling FUNC with ARG a 'stack'
+// at a given time, only one stack may be 'executed'
+typedef struct
+{
+ pthread_t thread; // stack's thread
+ pthread_mutex_t mutex; // mutex to suspend/resume thread
+#if defined(__CYGWIN__)
+ pthread_mutexattr_t mxAttr;
+#endif
+ void (*Func)(void*); // stack's FUNC
+ void* Arg; // ARG passed to FUNC
+} Stack_Type_t, *Stack_Type;
+
+static Stack_Type_t main_stack_context;
+static Stack_Type_t *current;
+extern void grt_set_main_stack (Stack_Type_t *stack);
+
+//----------------------------------------------------------------------------
+void grt_stack_init(void)
+// Initialize the stacks package.
+// This may adjust stack sizes.
+// Must be called after grt.options.decode.
+// => procedure Stack_Init;
+{
+ int res;
+ INFO("grt_stack_init\n");
+ INFO(" main_stack_context=0x%08x\n", &main_stack_context);
+
+
+#if defined(__CYGWIN__)
+ res = pthread_mutexattr_init (&main_stack_context.mxAttr);
+ assert (res == 0);
+ res = pthread_mutexattr_settype (&main_stack_context.mxAttr,
+ PTHREAD_MUTEX_DEFAULT);
+ assert (res == 0);
+ res = pthread_mutex_init (&main_stack_context.mutex,
+ &main_stack_context.mxAttr);
+ assert (res == 0);
+#else
+ res = pthread_mutex_init (&main_stack_context.mutex, NULL);
+ assert (res == 0);
+#endif
+ // lock the mutex, as we are currently running
+ res = pthread_mutex_lock (&main_stack_context.mutex);
+ assert (res == 0);
+
+ current = &main_stack_context;
+
+ grt_set_main_stack (&main_stack_context);
+}
+
+//----------------------------------------------------------------------------
+static void* grt_stack_loop(void* pv_myStack)
+{
+ Stack_Type myStack= (Stack_Type)pv_myStack;
+
+ INFO("grt_stack_loop\n");
+
+ INFO(" myStack=0x%08x\n", myStack);
+
+ // block until mutex becomes available again.
+ // this happens when this stack is enabled for the first time
+ pthread_mutex_lock(&(myStack->mutex));
+
+ // run stack's function in endless loop
+ while(1)
+ {
+ INFO(" call 0x%08x with 0x%08x\n", myStack->Func, myStack->Arg);
+ myStack->Func(myStack->Arg);
+ }
+
+ // we never get here...
+ return 0;
+}
+
+//----------------------------------------------------------------------------
+Stack_Type grt_stack_create(void* Func, void* Arg)
+// Create a new stack, which on first execution will call FUNC with
+// an argument ARG.
+// => function Stack_Create (Func : Address; Arg : Address) return Stack_Type;
+{
+ Stack_Type newStack;
+ int res;
+
+ INFO("grt_stack_create\n");
+ INFO(" call 0x%08x with 0x%08x\n", Func, Arg);
+
+ newStack = malloc (sizeof(Stack_Type_t));
+
+ // init function and argument
+ newStack->Func = Func;
+ newStack->Arg = Arg;
+
+ // create mutex
+#if defined(__CYGWIN__)
+ res = pthread_mutexattr_init (&newStack->mxAttr);
+ assert (res == 0);
+ res = pthread_mutexattr_settype (&newStack->mxAttr, PTHREAD_MUTEX_DEFAULT);
+ assert (res == 0);
+ res = pthread_mutex_init (&newStack->mutex, &newStack->mxAttr);
+ assert (res == 0);
+#else
+ res = pthread_mutex_init (&newStack->mutex, NULL);
+ assert (res == 0);
+#endif
+
+ // block the mutex, so that thread will blocked in grt_stack_loop
+ res = pthread_mutex_lock (&newStack->mutex);
+ assert (res == 0);
+
+ INFO(" newStack=0x%08x\n", newStack);
+
+ // create thread, which executes grt_stack_loop
+ pthread_create (&newStack->thread, NULL, grt_stack_loop, newStack);
+
+ return newStack;
+}
+
+static int need_longjmp;
+static int run_env_en;
+static jmp_buf run_env;
+
+//----------------------------------------------------------------------------
+void grt_stack_switch(Stack_Type To, Stack_Type From)
+// Resume stack TO and save the current context to the stack pointed by
+// CUR.
+// => procedure Stack_Switch (To : Stack_Type; From : Stack_Type);
+{
+ int res;
+ INFO("grt_stack_switch\n");
+ INFO(" from 0x%08x to 0x%08x\n", From, To);
+
+ current = To;
+
+ // unlock 'To' mutex. this will make the other thread either
+ // - starts for first time in grt_stack_loop
+ // - resumes at lock below
+ res = pthread_mutex_unlock (&To->mutex);
+ assert (res == 0);
+
+ // block until 'From' mutex becomes available again
+ // as we are running, our mutex is locked and we block here
+ // when stacks are switched, with above unlock, we may proceed
+ res = pthread_mutex_lock (&From->mutex);
+ assert (res == 0);
+
+ if (From == &main_stack_context && need_longjmp != 0)
+ longjmp (run_env, need_longjmp);
+}
+
+//----------------------------------------------------------------------------
+void grt_stack_delete(Stack_Type Stack)
+// Delete stack STACK, which must not be currently executed.
+// => procedure Stack_Delete (Stack : Stack_Type);
+{
+ INFO("grt_stack_delete\n");
+}
+
+void
+__ghdl_maybe_return_via_longjump (int val)
+{
+ if (!run_env_en)
+ return;
+
+ if (current != &main_stack_context)
+ {
+ need_longjmp = val;
+ grt_stack_switch (&main_stack_context, current);
+ }
+ else
+ longjmp (run_env, val);
+}
+
+int
+__ghdl_run_through_longjump (int (*func)(void))
+{
+ int res;
+
+ run_env_en = 1;
+ res = setjmp (run_env);
+ if (res == 0)
+ res = (*func)();
+ run_env_en = 0;
+ return res;
+}
+
+
+//----------------------------------------------------------------------------
+
+#ifndef WITH_GNAT_RUN_TIME
+void __gnat_raise_storage_error(void)
+{
+ abort ();
+}
+
+void __gnat_raise_program_error(void)
+{
+ abort ();
+}
+#endif /* WITH_GNAT_RUN_TIME */
+
+//----------------------------------------------------------------------------
+// end of file
+
diff --git a/src/grt/config/sparc.S b/src/grt/config/sparc.S
new file mode 100644
index 000000000..0ffe412ed
--- /dev/null
+++ b/src/grt/config/sparc.S
@@ -0,0 +1,141 @@
+/* GRT stack implementation for x86.
+ Copyright (C) 2002 - 2014 Tristan Gingold.
+
+ GHDL is free software; you can redistribute it and/or modify it under
+ the terms of the GNU General Public License as published by the Free
+ Software Foundation; either version 2, or (at your option) any later
+ version.
+
+ GHDL is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with GCC; see the file COPYING. If not, write to the Free
+ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
+ 02111-1307, USA.
+
+ As a special exception, if other files instantiate generics from this
+ unit, or you link this unit with other files to produce an executable,
+ this unit does not by itself cause the resulting executable to be
+ covered by the GNU General Public License. This exception does not
+ however invalidate any other reasons why the executable file might be
+ covered by the GNU Public License.
+*/
+ .file "sparc.S"
+
+ .section ".text"
+
+ /* Stack structure is:
+ +4 : cur_length
+ +0 : cur_sp
+ -4 : return address
+ -8 : process function to be executed
+ -12: function argument
+ ...
+ -72: %sp
+ */
+
+ /* Function called to loop on the process. */
+ .align 4
+ .type grt_stack_loop,#function
+grt_stack_loop:
+ ld [%sp + 64], %o1
+ jmpl %o1 + 0, %o7
+ ld [%sp + 68], %o0
+ ba grt_stack_loop
+ nop
+ .size grt_stack_loop, . - grt_stack_loop
+
+ /* function Stack_Create (Func : Address; Arg : Address)
+ return Stack_Type; */
+ .align 4
+ .global grt_stack_create
+ .type grt_stack_create,#function
+grt_stack_create:
+ /* Standard prologue. */
+ save %sp,-80,%sp
+
+ /* Allocate the stack, and exit in case of failure */
+ call grt_stack_allocate
+ nop
+ cmp %o0, 0
+ be .Ldone
+ nop
+
+ /* Note: %o0 contains the address of the stack_context. This is
+ also the top of the stack. */
+
+ /* Prepare stack. */
+
+ /* The return function. */
+ sethi %hi(grt_stack_loop - 8), %l2
+ or %lo(grt_stack_loop - 8), %l2, %l2
+
+ /* Create a frame for grt_stack_loop. */
+ sub %o0, (64 + 8), %l1
+
+ /* The function to be executed. */
+ st %i0, [%l1 + 64]
+ /* The argument. */
+ st %i1, [%l1 + 68]
+
+ /* Create a frame for grt_stack_switch. */
+ sub %l1, 64, %l0
+
+ /* Save frame pointer. */
+ st %l1, [%l0 + 56]
+ /* Save return address. */
+ st %l2, [%l0 + 60]
+
+ /* Save stack pointer. */
+ st %l0, [%o0]
+
+.Ldone:
+ ret
+ restore %o0, %g0, %o0
+ .size grt_stack_create,. - grt_stack_create
+
+
+ .align 4
+ .global grt_stack_switch
+ /* Arguments: TO, FROM.
+ Both are pointers to a stack_context. */
+ .type grt_stack_switch,#function
+grt_stack_switch:
+ /* Standard prologue. */
+ save %sp,-80,%sp
+
+ /* Flush and invalidate windows.
+ It is not clear wether the current window is saved or not,
+ therefore, I assume it is not.
+ */
+ ta 3
+
+ /* Only IN registers %fp and %i7 (return address) must be saved.
+ Of course, I could use std/ldd, but it is not as clear
+ */
+ /* Save current frame pointer. */
+ st %fp, [%sp + 56]
+ /* Save return address. */
+ st %i7, [%sp + 60]
+
+ /* Save stack pointer. */
+ st %sp, [%i1]
+
+ /* Load stack pointer. */
+ ld [%i0], %sp
+
+ /* Load return address. */
+ ld [%sp + 60], %i7
+ /* Load frame pointer. */
+ ld [%sp + 56], %fp
+
+ /* Return. */
+ ret
+ restore
+ .size grt_stack_switch, . - grt_stack_switch
+
+
+ .ident "Written by T.Gingold"
diff --git a/src/grt/config/teststack.c b/src/grt/config/teststack.c
new file mode 100644
index 000000000..6a6966d6f
--- /dev/null
+++ b/src/grt/config/teststack.c
@@ -0,0 +1,174 @@
+#include <stdlib.h>
+#include <stdio.h>
+
+extern void grt_stack_init (void);
+extern void grt_stack_switch (void *from, void *to);
+extern void *grt_stack_create (void (*func)(void *), void *arg);
+
+int stack_size = 4096;
+int stack_max_size = 8 * 4096;
+
+static void *stack1;
+static void *stack2;
+void *grt_stack_main_stack;
+
+void *grt_cur_proc;
+
+static int step;
+
+void
+grt_overflow_error (void)
+{
+ abort ();
+}
+
+void
+grt_stack_error_null_access (void)
+{
+ abort ();
+}
+
+void
+grt_stack_error_memory_access (void)
+{
+ abort ();
+}
+
+void
+grt_stack_error_grow_failed (void)
+{
+ abort ();
+}
+
+void
+error (void)
+{
+ printf ("Test failure at step %d\n", step);
+ fflush (stdout);
+ exit (1);
+}
+
+static void
+func1 (void *ptr)
+{
+ if (ptr != (void *)1)
+ error ();
+
+ if (step != 0)
+ error ();
+
+ step = 1;
+
+ grt_stack_switch (grt_stack_main_stack, stack1);
+
+ if (step != 5)
+ error ();
+
+ step = 6;
+
+ grt_stack_switch (grt_stack_main_stack, stack1);
+
+ if (step != 7)
+ error ();
+
+ step = 8;
+
+ grt_stack_switch (stack2, stack1);
+
+ if (step != 9)
+ error ();
+
+ step = 10;
+
+ grt_stack_switch (grt_stack_main_stack, stack1);
+
+ error ();
+}
+
+static void
+func2 (void *ptr)
+{
+ if (ptr != (void *)2)
+ error ();
+
+ if (step == 11)
+ {
+ step = 12;
+
+ grt_stack_switch (grt_stack_main_stack, stack2);
+
+ error ();
+ }
+
+ if (step != 1)
+ error ();
+
+ step = 2;
+
+ grt_stack_switch (grt_stack_main_stack, stack2);
+
+ if (step != 3)
+ error ();
+
+ step = 4;
+
+ grt_stack_switch (grt_stack_main_stack, stack2);
+
+ if (step != 8)
+ error ();
+
+ step = 9;
+
+ grt_stack_switch (stack1, stack2);
+}
+
+int
+main (void)
+{
+ grt_stack_init ();
+
+ stack1 = grt_stack_create (&func1, (void *)1);
+ stack2 = grt_stack_create (&func2, (void *)2);
+
+ step = 0;
+ grt_stack_switch (stack1, grt_stack_main_stack);
+
+ if (step != 1)
+ error ();
+
+ grt_stack_switch (stack2, grt_stack_main_stack);
+
+ if (step != 2)
+ error ();
+
+ step = 3;
+
+ grt_stack_switch (stack2, grt_stack_main_stack);
+
+ if (step != 4)
+ error ();
+
+ step = 5;
+
+ grt_stack_switch (stack1, grt_stack_main_stack);
+
+ if (step != 6)
+ error ();
+
+ step = 7;
+
+ grt_stack_switch (stack1, grt_stack_main_stack);
+
+ if (step != 10)
+ error ();
+
+ step = 11;
+
+ grt_stack_switch (stack2, grt_stack_main_stack);
+
+ if (step != 12)
+ error ();
+
+ printf ("Test successful\n");
+ return 0;
+}
diff --git a/src/grt/config/times.c b/src/grt/config/times.c
new file mode 100644
index 000000000..9c0b4ebba
--- /dev/null
+++ b/src/grt/config/times.c
@@ -0,0 +1,55 @@
+/* GRT C bindings for time.
+ Copyright (C) 2002 - 2014 Tristan Gingold.
+
+ GHDL is free software; you can redistribute it and/or modify it under
+ the terms of the GNU General Public License as published by the Free
+ Software Foundation; either version 2, or (at your option) any later
+ version.
+
+ GHDL is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with GCC; see the file COPYING. If not, write to the Free
+ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
+ 02111-1307, USA.
+
+ As a special exception, if other files instantiate generics from this
+ unit, or you link this unit with other files to produce an executable,
+ this unit does not by itself cause the resulting executable to be
+ covered by the GNU General Public License. This exception does not
+ however invalidate any other reasons why the executable file might be
+ covered by the GNU Public License.
+*/
+#include <sys/times.h>
+#include <unistd.h>
+
+int
+grt_get_clk_tck (void)
+{
+ return sysconf (_SC_CLK_TCK);
+}
+
+void
+grt_get_times (int *wall, int *user, int *sys)
+{
+ clock_t res;
+ struct tms buf;
+
+ res = times (&buf);
+ if (res == (clock_t)-1)
+ {
+ *wall = 0;
+ *user = 0;
+ *sys = 0;
+ }
+ else
+ {
+ *wall = res;
+ *user = buf.tms_utime;
+ *sys = buf.tms_stime;
+ }
+}
+
diff --git a/src/grt/config/win32.c b/src/grt/config/win32.c
new file mode 100644
index 000000000..35322ba9f
--- /dev/null
+++ b/src/grt/config/win32.c
@@ -0,0 +1,265 @@
+/* GRT stack implementation for Win32 using fibers.
+ Copyright (C) 2005 - 2014 Tristan Gingold.
+
+ GHDL is free software; you can redistribute it and/or modify it under
+ the terms of the GNU General Public License as published by the Free
+ Software Foundation; either version 2, or (at your option) any later
+ version.
+
+ GHDL is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with GCC; see the file COPYING. If not, write to the Free
+ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
+ 02111-1307, USA.
+
+ As a special exception, if other files instantiate generics from this
+ unit, or you link this unit with other files to produce an executable,
+ this unit does not by itself cause the resulting executable to be
+ covered by the GNU General Public License. This exception does not
+ however invalidate any other reasons why the executable file might be
+ covered by the GNU Public License.
+*/
+
+#include <windows.h>
+#include <stdio.h>
+#include <setjmp.h>
+#include <assert.h>
+#include <excpt.h>
+
+static EXCEPTION_DISPOSITION
+ghdl_SEH_handler (struct _EXCEPTION_RECORD* ExceptionRecord,
+ void *EstablisherFrame,
+ struct _CONTEXT* ContextRecord,
+ void *DispatcherContext);
+
+struct exception_registration
+{
+ struct exception_registration *prev;
+ void *handler;
+};
+
+struct stack_type
+{
+ LPVOID fiber; // Win fiber.
+ void (*func)(void *); // Function
+ void *arg; // Function argument.
+};
+
+static struct stack_type main_stack_context;
+static struct stack_type *current;
+extern void grt_set_main_stack (struct stack_type *stack);
+
+void grt_stack_init(void)
+{
+ main_stack_context.fiber = ConvertThreadToFiber (NULL);
+ if (main_stack_context.fiber == NULL)
+ {
+ fprintf (stderr, "convertThreadToFiber failed (err=%lu)\n",
+ GetLastError ());
+ abort ();
+ }
+ grt_set_main_stack (&main_stack_context);
+ current = &main_stack_context;
+}
+
+static VOID __stdcall
+grt_stack_loop (void *v_stack)
+{
+ struct stack_type *stack = (struct stack_type *)v_stack;
+ struct exception_registration er;
+ struct exception_registration *prev;
+
+ /* Get current handler. */
+ asm ("mov %%fs:(0),%0" : "=r" (prev));
+
+ /* Build regisration. */
+ er.prev = prev;
+ er.handler = ghdl_SEH_handler;
+
+ /* Register. */
+ asm ("mov %0,%%fs:(0)" : : "r" (&er));
+
+ while (1)
+ {
+ (*stack->func)(stack->arg);
+ }
+}
+
+struct stack_type *
+grt_stack_create (void (*func)(void *), void *arg)
+{
+ struct stack_type *res;
+
+ res = malloc (sizeof (struct stack_type));
+ if (res == NULL)
+ return NULL;
+ res->func = func;
+ res->arg = arg;
+ res->fiber = CreateFiber (0, &grt_stack_loop, res);
+ if (res->fiber == NULL)
+ {
+ free (res);
+ return NULL;
+ }
+ return res;
+}
+
+static int run_env_en;
+static jmp_buf run_env;
+static int need_longjmp;
+
+void
+grt_stack_switch (struct stack_type *to, struct stack_type *from)
+{
+ assert (current == from);
+ current = to;
+ SwitchToFiber (to->fiber);
+ if (from == &main_stack_context && need_longjmp)
+ {
+ /* We returned to do the longjump. */
+ current = &main_stack_context;
+ longjmp (run_env, need_longjmp);
+ }
+}
+
+void
+grt_stack_delete (struct stack_type *stack)
+{
+ DeleteFiber (stack->fiber);
+ stack->fiber = NULL;
+}
+
+void
+__ghdl_maybe_return_via_longjump (int val)
+{
+ if (!run_env_en)
+ return;
+
+ if (current != &main_stack_context)
+ {
+ /* We are allowed to jump only in the same stack.
+ First switch back to the main thread. */
+ need_longjmp = val;
+ SwitchToFiber (main_stack_context.fiber);
+ }
+ else
+ longjmp (run_env, val);
+}
+
+extern void grt_stack_error_grow_failed (void);
+extern void grt_stack_error_null_access (void);
+extern void grt_stack_error_memory_access (void);
+extern void grt_overflow_error (void);
+
+static EXCEPTION_DISPOSITION
+ghdl_SEH_handler (struct _EXCEPTION_RECORD* ExceptionRecord,
+ void *EstablisherFrame,
+ struct _CONTEXT* ContextRecord,
+ void *DispatcherContext)
+{
+ const char *msg = "";
+
+ switch (ExceptionRecord->ExceptionCode)
+ {
+ case EXCEPTION_ACCESS_VIOLATION:
+ if (ExceptionRecord->ExceptionInformation[1] == 0)
+ grt_stack_error_null_access ();
+ else
+ grt_stack_error_memory_access ();
+ break;
+
+ case EXCEPTION_FLT_DENORMAL_OPERAND:
+ case EXCEPTION_FLT_DIVIDE_BY_ZERO:
+ case EXCEPTION_FLT_INVALID_OPERATION:
+ case EXCEPTION_FLT_OVERFLOW:
+ case EXCEPTION_FLT_STACK_CHECK:
+ case EXCEPTION_FLT_UNDERFLOW:
+ msg = "floating point error";
+ break;
+
+ case EXCEPTION_INT_DIVIDE_BY_ZERO:
+ msg = "division by 0";
+ break;
+
+ case EXCEPTION_INT_OVERFLOW:
+ grt_overflow_error ();
+ break;
+
+ case EXCEPTION_STACK_OVERFLOW:
+ msg = "stack overflow";
+ break;
+
+ default:
+ msg = "unknown reason";
+ break;
+ }
+
+ /* FIXME: is it correct? */
+ fprintf (stderr, "exception raised: %s\n", msg);
+
+ __ghdl_maybe_return_via_longjump (1);
+ return 0; /* This is never reached, avoid compiler warning */
+}
+
+int
+__ghdl_run_through_longjump (int (*func)(void))
+{
+ int res;
+ struct exception_registration er;
+ struct exception_registration *prev;
+
+ /* Get current handler. */
+ asm ("mov %%fs:(0),%0" : "=r" (prev));
+
+ /* Build regisration. */
+ er.prev = prev;
+ er.handler = ghdl_SEH_handler;
+
+ /* Register. */
+ asm ("mov %0,%%fs:(0)" : : "r" (&er));
+
+ run_env_en = 1;
+ res = setjmp (run_env);
+ if (res == 0)
+ res = (*func)();
+ run_env_en = 0;
+
+ /* Restore. */
+ asm ("mov %0,%%fs:(0)" : : "r" (prev));
+
+ return res;
+}
+
+#include <math.h>
+
+double acosh (double x)
+{
+ return log (x + sqrt (x*x - 1));
+}
+
+double asinh (double x)
+{
+ return log (x + sqrt (x*x + 1));
+}
+
+double atanh (double x)
+{
+ return log ((1 + x) / (1 - x)) / 2;
+}
+
+#ifndef WITH_GNAT_RUN_TIME
+void __gnat_raise_storage_error(void)
+{
+ abort ();
+}
+
+void __gnat_raise_program_error(void)
+{
+ abort ();
+}
+#endif
+
diff --git a/src/grt/config/win32thr.c b/src/grt/config/win32thr.c
new file mode 100644
index 000000000..bcebc49d5
--- /dev/null
+++ b/src/grt/config/win32thr.c
@@ -0,0 +1,167 @@
+/* GRT stack implementation for Win32
+ Copyright (C) 2004, 2005 Felix Bertram.
+
+ GHDL is free software; you can redistribute it and/or modify it under
+ the terms of the GNU General Public License as published by the Free
+ Software Foundation; either version 2, or (at your option) any later
+ version.
+
+ GHDL is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with GCC; see the file COPYING. If not, write to the Free
+ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
+ 02111-1307, USA.
+*/
+//-----------------------------------------------------------------------------
+// Project: GHDL - VHDL Simulator
+// Description: Win32 port of stacks package
+// Note: Tristan's original i386/Linux used assembly-code
+// to manually switch stacks for performance reasons.
+// History: 2004feb09, FB, created.
+//-----------------------------------------------------------------------------
+
+#include <windows.h>
+//#include <pthread.h>
+//#include <stdlib.h>
+//#include <stdio.h>
+
+
+//#define INFO printf
+#define INFO (void)
+
+// GHDL names an endless loop calling FUNC with ARG a 'stack'
+// at a given time, only one stack may be 'executed'
+typedef struct
+{ HANDLE thread; // stack's thread
+ HANDLE mutex; // mutex to suspend/resume thread
+ void (*Func)(void*); // stack's FUNC
+ void* Arg; // ARG passed to FUNC
+} Stack_Type_t, *Stack_Type;
+
+
+static Stack_Type_t main_stack_context;
+extern void grt_set_main_stack (Stack_Type_t *stack);
+
+//------------------------------------------------------------------------------
+void grt_stack_init(void)
+// Initialize the stacks package.
+// This may adjust stack sizes.
+// Must be called after grt.options.decode.
+// => procedure Stack_Init;
+{ INFO("grt_stack_init\n");
+ INFO(" main_stack_context=0x%08x\n", &main_stack_context);
+
+ // create event. reset event, as we are currently running
+ main_stack_context.mutex = CreateEvent(NULL, // lpsa
+ FALSE, // fManualReset
+ FALSE, // fInitialState
+ NULL); // lpszEventName
+
+ grt_set_main_stack (&main_stack_context);
+}
+
+//------------------------------------------------------------------------------
+static unsigned long __stdcall grt_stack_loop(void* pv_myStack)
+{
+ Stack_Type myStack= (Stack_Type)pv_myStack;
+
+ INFO("grt_stack_loop\n");
+
+ INFO(" myStack=0x%08x\n", myStack);
+
+ // block until event becomes set again.
+ // this happens when this stack is enabled for the first time
+ WaitForSingleObject(myStack->mutex, INFINITE);
+
+ // run stack's function in endless loop
+ while(1)
+ { INFO(" call 0x%08x with 0x%08x\n", myStack->Func, myStack->Arg);
+ myStack->Func(myStack->Arg);
+ }
+
+ // we never get here...
+ return 0;
+}
+
+//------------------------------------------------------------------------------
+Stack_Type grt_stack_create(void* Func, void* Arg)
+// Create a new stack, which on first execution will call FUNC with
+// an argument ARG.
+// => function Stack_Create (Func : Address; Arg : Address) return Stack_Type;
+{ Stack_Type newStack;
+ DWORD m_IDThread; // Thread's ID (dummy)
+
+ INFO("grt_stack_create\n");
+ INFO(" call 0x%08x with 0x%08x\n", Func, Arg);
+
+ newStack= malloc(sizeof(Stack_Type_t));
+
+ // init function and argument
+ newStack->Func= Func;
+ newStack->Arg= Arg;
+
+ // create event. reset event, so that thread will blocked in grt_stack_loop
+ newStack->mutex= CreateEvent(NULL, // lpsa
+ FALSE, // fManualReset
+ FALSE, // fInitialState
+ NULL); // lpszEventName
+
+ INFO(" newStack=0x%08x\n", newStack);
+
+ // create thread, which executes grt_stack_loop
+ newStack->thread= CreateThread(NULL, // lpsa
+ 0, // cbStack
+ grt_stack_loop, // lpStartAddr
+ newStack, // lpvThreadParm
+ 0, // fdwCreate
+ &m_IDThread); // lpIDThread
+
+ return newStack;
+}
+
+//------------------------------------------------------------------------------
+void grt_stack_switch(Stack_Type To, Stack_Type From)
+// Resume stack TO and save the current context to the stack pointed by
+// CUR.
+// => procedure Stack_Switch (To : Stack_Type; From : Stack_Type);
+{ INFO("grt_stack_switch\n");
+ INFO(" from 0x%08x to 0x%08x\n", From, To);
+
+ // set 'To' event. this will make the other thread either
+ // - start for first time in grt_stack_loop
+ // - resume at WaitForSingleObject below
+ SetEvent(To->mutex);
+
+ // block until 'From' event becomes set again
+ // as we are running, our event is reset and we block here
+ // when stacks are switched, with above SetEvent, we may proceed
+ WaitForSingleObject(From->mutex, INFINITE);
+}
+
+//------------------------------------------------------------------------------
+void grt_stack_delete(Stack_Type Stack)
+// Delete stack STACK, which must not be currently executed.
+// => procedure Stack_Delete (Stack : Stack_Type);
+{ INFO("grt_stack_delete\n");
+}
+
+//----------------------------------------------------------------------------
+#ifndef WITH_GNAT_RUN_TIME
+void __gnat_raise_storage_error(void)
+{
+ abort ();
+}
+
+void __gnat_raise_program_error(void)
+{
+ abort ();
+}
+#endif
+
+//----------------------------------------------------------------------------
+// end of file
+