Add emacs cache files to .cvsignore.
[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 =~ /ia64/)  { ia64ias();   }
33 elsif ($arg =~ /amd64/) { amd64masm(); }
34 else    { die "nonsense $arg"; }
35
36 sub ia32masm() {
37 print <<___;
38 .386P
39 .model  FLAT
40
41 _DATA   SEGMENT
42 PUBLIC  _OPENSSL_UplinkTable
43 _OPENSSL_UplinkTable    DD      $N      ; amount of following entries
44 ___
45 for ($i=1;$i<=$N;$i++) {   print "      DD      FLAT:\$lazy$i\n";   }
46 print <<___;
47 _DATA   ENDS
48
49 _TEXT   SEGMENT
50 EXTRN   _OPENSSL_Uplink:NEAR
51 ___
52 for ($i=1;$i<=$N;$i++) {
53 print <<___;
54 ALIGN   4
55 \$lazy$i        PROC NEAR
56         push    $i
57         push    OFFSET FLAT:_OPENSSL_UplinkTable
58         call    _OPENSSL_Uplink
59         add     esp,8
60         jmp     DWORD PTR _OPENSSL_UplinkTable+4*$i
61 \$lazy$i        ENDP
62 ___
63 }
64 print <<___;
65 ALIGN   4
66 _TEXT   ENDS
67 END
68 ___
69 }
70
71 sub ia32nasm() {
72 print <<___;
73 SEGMENT .data
74 GLOBAL  _OPENSSL_UplinkTable
75 _OPENSSL_UplinkTable    DD      $N      ; amount of following entries
76 ___
77 for ($i=1;$i<=$N;$i++) {   print "      DD      \$lazy$i\n";   }
78 print <<___;
79
80 SEGMENT .text
81 EXTERN  _OPENSSL_Uplink
82 ___
83 for ($i=1;$i<=$N;$i++) {
84 print <<___;
85 ALIGN   4
86 \$lazy$i:
87         push    $i
88         push    _OPENSSL_UplinkTable
89         call    _OPENSSL_Uplink
90         add     esp,8
91         jmp     [_OPENSSL_UplinkTable+4*$i]
92 ___
93 }
94 print <<___;
95 ALIGN   4
96 END
97 ___
98 }
99
100 sub ia64ias () {
101 local $V=8;     # max number of args uplink functions may accept...
102 print <<___;
103 .data
104 .global OPENSSL_UplinkTable#
105 OPENSSL_UplinkTable:    data8   $N      // amount of following entries
106 ___
107 for ($i=1;$i<=$N;$i++) {   print "      data8   \@fptr(lazy$i#)\n";   }
108 print <<___;
109 .size   OPENSSL_UplinkTable,.-OPENSSL_UplinkTable#
110
111 .text
112 .global OPENSSL_Uplink#
113 .type   OPENSSL_Uplink#,\@function
114 ___
115 for ($i=1;$i<=$N;$i++) {
116 print <<___;
117 .proc   lazy$i
118 lazy$i:
119 { .mii; alloc   loc0=ar.pfs,$V,3,2,0
120         mov     loc1=b0
121         addl    loc2=\@ltoff(OPENSSL_UplinkTable#),gp   };;
122 { .mmi; ld8     out0=[loc2]
123         mov     out1=$i                                 };;
124 { .mib; adds    loc2=8*$i,out0
125         br.call.sptk.many       b0=OPENSSL_Uplink#      };;
126 { .mmi; ld8     r31=[loc2];;
127         ld8     r30=[r31],8                             };;
128 { .mii; ld8     gp=[r31]
129         mov     b6=r30
130         mov     b0=loc1                                 };;
131 { .mib; mov     ar.pfs=loc0
132         br.many b6                                      };;
133 .endp   lazy$i#
134 ___
135 }
136 }
137
138 sub amd64masm() {
139 print <<___;
140 _DATA   SEGMENT
141 PUBLIC  OPENSSL_UplinkTable
142 OPENSSL_UplinkTable     DQ      $N
143 ___
144 for ($i=1;$i<=$N;$i++) {   print "      DQ      FLAT:\$lazy$i\n";   }
145 print <<___;
146 _DATA   ENDS
147
148 TEXT    SEGMENT
149 EXTERN  OPENSSL_Uplink:NEAR
150 ___
151 for ($i=1;$i<=$N;$i++) {
152 print <<___;
153 ALIGN   4
154 \$lazy$i        PROC NEAR
155         push    r9
156         push    r8
157         push    rdx
158         push    rcx
159         sub     rsp,40
160         mov     rcx,OFFSET FLAT:OPENSSL_UplinkTable
161         mov     rdx,$i
162         call    OPENSSL_Uplink
163         add     rsp,40
164         pop     rcx
165         pop     rdx
166         pop     r8
167         pop     r9
168         jmp     QWORD PTR OPENSSL_UplinkTable+8*$i
169 \$lazy$i        ENDP
170 ___
171 }
172 print <<___;
173 TEXT    ENDS
174 END
175 ___
176 }
177