uplink.pl 4.0 KB

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