Don't use __try+__except unless on VC++
[openssl.git] / ms / uplink.pl
1 #!/usr/bin/env perl
2 #
3 # For Microsoft CL this is implemented as inline assembler. So that
4 # even though this script can generate even Win32 code, we'll be
5 # using it primarily to generate Win64 modules. Both IA-64 and AMD64
6 # are supported...
7
8 # pull APPLINK_MAX value from applink.c...
9 $applink_c=$0;
10 $applink_c=~s|[^/\\]+$||g;
11 $applink_c.="applink.c";
12 open(INPUT,$applink_c) || die "can't open $applink_c: $!";
13 @max=grep {/APPLINK_MAX\s+(\d+)/} <INPUT>;
14 close(INPUT);
15 ($#max==0) or die "can't find APPLINK_MAX in $applink_c";
16
17 $max[0]=~/APPLINK_MAX\s+(\d+)/;
18 $N=$1;  # number of entries in OPENSSL_UplinkTable not including
19         # OPENSSL_UplinkTable[0], which contains this value...
20
21 # Idea is to fill the OPENSSL_UplinkTable with pointers to stubs
22 # which invoke 'void OPENSSL_Uplink (ULONG_PTR *table,int index)';
23 # and then dereference themselves. Latter shall result in endless
24 # loop *unless* OPENSSL_Uplink does not replace 'table[index]' with
25 # something else, e.g. as 'table[index]=unimplemented;'...
26
27 $arg = shift;
28 #( defined shift || open STDOUT,">$arg" ) || die "can't open $arg: $!";
29
30 if ($arg =~ /win32n/)   { ia32nasm();  }
31 elsif ($arg =~ /win32/) { ia32masm();  }
32 elsif ($arg =~ /coff/)  { ia32gas();   }
33 elsif ($arg =~ /win64i/ or $arg =~ /ia64/)      { ia64ias();   }
34 elsif ($arg =~ /win64a/ or $arg =~ /amd64/)     { amd64masm(); }
35 else    { die "nonsense $arg"; }
36
37 sub ia32gas() {
38 print <<___;
39 .text
40 ___
41 for ($i=1;$i<=$N;$i++) {
42 print <<___;
43 .def    .Lazy$i;        .scl    3;      .type   32;     .endef
44 .align  4
45 .Lazy$i:
46         pushl   \$$i
47         pushl   \$_OPENSSL_UplinkTable
48         call    _OPENSSL_Uplink
49         addl    \$8,%esp
50         jmp     *(_OPENSSL_UplinkTable+4*$i)
51 ___
52 }
53 print <<___;
54 .data
55 .align  4
56 .globl  _OPENSSL_UplinkTable
57 _OPENSSL_UplinkTable:
58         .long   $N
59 ___
60 for ($i=1;$i<=$N;$i++) {   print "      .long   .Lazy$i\n";   }
61 }
62
63 sub ia32masm() {
64 print <<___;
65 .386P
66 .model  FLAT
67
68 _DATA   SEGMENT
69 PUBLIC  _OPENSSL_UplinkTable
70 _OPENSSL_UplinkTable    DD      $N      ; amount of following entries
71 ___
72 for ($i=1;$i<=$N;$i++) {   print "      DD      FLAT:\$lazy$i\n";   }
73 print <<___;
74 _DATA   ENDS
75
76 _TEXT   SEGMENT
77 EXTRN   _OPENSSL_Uplink:NEAR
78 ___
79 for ($i=1;$i<=$N;$i++) {
80 print <<___;
81 ALIGN   4
82 \$lazy$i        PROC NEAR
83         push    $i
84         push    OFFSET FLAT:_OPENSSL_UplinkTable
85         call    _OPENSSL_Uplink
86         add     esp,8
87         jmp     DWORD PTR _OPENSSL_UplinkTable+4*$i
88 \$lazy$i        ENDP
89 ___
90 }
91 print <<___;
92 ALIGN   4
93 _TEXT   ENDS
94 END
95 ___
96 }
97
98 sub ia32nasm() {
99 print <<___;
100 SEGMENT .data
101 GLOBAL  _OPENSSL_UplinkTable
102 _OPENSSL_UplinkTable    DD      $N      ; amount of following entries
103 ___
104 for ($i=1;$i<=$N;$i++) {   print "      DD      \$lazy$i\n";   }
105 print <<___;
106
107 SEGMENT .text
108 EXTERN  _OPENSSL_Uplink
109 ___
110 for ($i=1;$i<=$N;$i++) {
111 print <<___;
112 ALIGN   4
113 \$lazy$i:
114         push    $i
115         push    _OPENSSL_UplinkTable
116         call    _OPENSSL_Uplink
117         add     esp,8
118         jmp     [_OPENSSL_UplinkTable+4*$i]
119 ___
120 }
121 print <<___;
122 ALIGN   4
123 END
124 ___
125 }
126
127 sub ia64ias () {
128 local $V=8;     # max number of args uplink functions may accept...
129 print <<___;
130 .data
131 .global OPENSSL_UplinkTable#
132 OPENSSL_UplinkTable:    data8   $N      // amount of following entries
133 ___
134 for ($i=1;$i<=$N;$i++) {   print "      data8   \@fptr(lazy$i#)\n";   }
135 print <<___;
136 .size   OPENSSL_UplinkTable,.-OPENSSL_UplinkTable#
137
138 .text
139 .global OPENSSL_Uplink#
140 .type   OPENSSL_Uplink#,\@function
141 ___
142 for ($i=1;$i<=$N;$i++) {
143 print <<___;
144 .proc   lazy$i
145 lazy$i:
146 { .mii; alloc   loc0=ar.pfs,$V,3,2,0
147         mov     loc1=b0
148         addl    loc2=\@ltoff(OPENSSL_UplinkTable#),gp   };;
149 { .mmi; ld8     out0=[loc2]
150         mov     out1=$i                                 };;
151 { .mib; adds    loc2=8*$i,out0
152         br.call.sptk.many       b0=OPENSSL_Uplink#      };;
153 { .mmi; ld8     r31=[loc2];;
154         ld8     r30=[r31],8                             };;
155 { .mii; ld8     gp=[r31]
156         mov     b6=r30
157         mov     b0=loc1                                 };;
158 { .mib; mov     ar.pfs=loc0
159         br.many b6                                      };;
160 .endp   lazy$i#
161 ___
162 }
163 }
164
165 sub amd64masm() {
166 print <<___;
167 _DATA   SEGMENT
168 PUBLIC  OPENSSL_UplinkTable
169 OPENSSL_UplinkTable     DQ      $N
170 ___
171 for ($i=1;$i<=$N;$i++) {   print "      DQ      \$lazy$i\n";   }
172 print <<___;
173 _DATA   ENDS
174
175 _TEXT   SEGMENT
176 EXTERN  OPENSSL_Uplink:PROC
177 ___
178 for ($i=1;$i<=$N;$i++) {
179 print <<___;
180 ALIGN   4
181 \$lazy$i        PROC
182         push    r9
183         push    r8
184         push    rdx
185         push    rcx
186         sub     rsp,40
187         lea     rcx,OFFSET OPENSSL_UplinkTable
188         mov     rdx,$i
189         call    OPENSSL_Uplink
190         add     rsp,40
191         pop     rcx
192         pop     rdx
193         pop     r8
194         pop     r9
195         jmp     QWORD PTR OPENSSL_UplinkTable+8*$i
196 \$lazy$i        ENDP
197 ___
198 }
199 print <<___;
200 _TEXT   ENDS
201 END
202 ___
203 }
204