]> git.ipfire.org Git - thirdparty/openssl.git/blob - crypto/perlasm/x86ms.pl
dd62348b6aa662aea1d57a77a893da6ef0d2965f
[thirdparty/openssl.git] / crypto / perlasm / x86ms.pl
1 #!/usr/local/bin/perl
2
3 package x86ms;
4
5 $label="L000";
6
7 %lb=( 'eax', 'al',
8 'ebx', 'bl',
9 'ecx', 'cl',
10 'edx', 'dl',
11 'ax', 'al',
12 'bx', 'bl',
13 'cx', 'cl',
14 'dx', 'dl',
15 );
16
17 %hb=( 'eax', 'ah',
18 'ebx', 'bh',
19 'ecx', 'ch',
20 'edx', 'dh',
21 'ax', 'ah',
22 'bx', 'bh',
23 'cx', 'ch',
24 'dx', 'dh',
25 );
26
27 sub main'asm_init_output { @out=(); }
28 sub main'asm_get_output { return(@out); }
29 sub main'get_labels { return(@labels); }
30 sub main'external_label { push(@labels,@_); }
31
32 sub main'LB
33 {
34 (defined($lb{$_[0]})) || die "$_[0] does not have a 'low byte'\n";
35 return($lb{$_[0]});
36 }
37
38 sub main'HB
39 {
40 (defined($hb{$_[0]})) || die "$_[0] does not have a 'high byte'\n";
41 return($hb{$_[0]});
42 }
43
44 sub main'BP
45 {
46 &get_mem("BYTE",@_);
47 }
48
49 sub main'DWP
50 {
51 &get_mem("DWORD",@_);
52 }
53
54 sub main'QWP
55 {
56 &get_mem("QWORD",@_);
57 }
58
59 sub main'BC
60 {
61 return @_;
62 }
63
64 sub main'DWC
65 {
66 return @_;
67 }
68
69 sub main'stack_push
70 {
71 local($num)=@_;
72 $stack+=$num*4;
73 &main'sub("esp",$num*4);
74 }
75
76 sub main'stack_pop
77 {
78 local($num)=@_;
79 $stack-=$num*4;
80 &main'add("esp",$num*4);
81 }
82
83 sub get_mem
84 {
85 local($size,$addr,$reg1,$reg2,$idx)=@_;
86 local($t,$post);
87 local($ret)="$size PTR ";
88
89 $addr =~ s/^\s+//;
90 if ($addr =~ /^(.+)\+(.+)$/)
91 {
92 $reg2=&conv($1);
93 $addr="_$2";
94 }
95 elsif ($addr =~ /^[_a-zA-Z]/)
96 {
97 $addr="_$addr";
98 }
99
100 if ($addr =~ /^.+\-.+$/) { $addr="($addr)"; }
101
102 $reg1="$regs{$reg1}" if defined($regs{$reg1});
103 $reg2="$regs{$reg2}" if defined($regs{$reg2});
104 if (($addr ne "") && ($addr ne 0))
105 {
106 if ($addr !~ /^-/)
107 { $ret.=$addr; }
108 else { $post=$addr; }
109 }
110 if ($reg2 ne "")
111 {
112 $t="";
113 $t="*$idx" if ($idx != 0);
114 $reg1="+".$reg1 if ("$reg1$post" ne "");
115 $ret.="[$reg2$t$reg1$post]";
116 }
117 else
118 {
119 $ret.="[$reg1$post]"
120 }
121 $ret =~ s/\[\]//; # in case $addr was the only argument
122 return($ret);
123 }
124
125 sub main'mov { &out2("mov",@_); }
126 sub main'movb { &out2("mov",@_); }
127 sub main'and { &out2("and",@_); }
128 sub main'or { &out2("or",@_); }
129 sub main'shl { &out2("shl",@_); }
130 sub main'shr { &out2("shr",@_); }
131 sub main'xor { &out2("xor",@_); }
132 sub main'xorb { &out2("xor",@_); }
133 sub main'add { &out2("add",@_); }
134 sub main'adc { &out2("adc",@_); }
135 sub main'sub { &out2("sub",@_); }
136 sub main'rotl { &out2("rol",@_); }
137 sub main'rotr { &out2("ror",@_); }
138 sub main'exch { &out2("xchg",@_); }
139 sub main'cmp { &out2("cmp",@_); }
140 sub main'lea { &out2("lea",@_); }
141 sub main'mul { &out1("mul",@_); }
142 sub main'div { &out1("div",@_); }
143 sub main'dec { &out1("dec",@_); }
144 sub main'inc { &out1("inc",@_); }
145 sub main'jmp { &out1("jmp",@_); }
146 sub main'jmp_ptr { &out1p("jmp",@_); }
147 sub main'je { &out1("je",@_); }
148 sub main'jle { &out1("jle",@_); }
149 sub main'jz { &out1("jz",@_); }
150 sub main'jge { &out1("jge",@_); }
151 sub main'jl { &out1("jl",@_); }
152 sub main'ja { &out1("ja",@_); }
153 sub main'jae { &out1("jae",@_); }
154 sub main'jb { &out1("jb",@_); }
155 sub main'jbe { &out1("jbe",@_); }
156 sub main'jc { &out1("jc",@_); }
157 sub main'jnc { &out1("jnc",@_); }
158 sub main'jnz { &out1("jnz",@_); }
159 sub main'jne { &out1("jne",@_); }
160 sub main'jno { &out1("jno",@_); }
161 sub main'push { &out1("push",@_); $stack+=4; }
162 sub main'pop { &out1("pop",@_); $stack-=4; }
163 sub main'bswap { &out1("bswap",@_); &using486(); }
164 sub main'not { &out1("not",@_); }
165 sub main'call { &out1("call",($_[0]=~/^\$L/?'':'_').$_[0]); }
166 sub main'ret { &out0("ret"); }
167 sub main'nop { &out0("nop"); }
168 sub main'test { &out2("test",@_); }
169 sub main'bt { &out2("bt",@_); }
170 sub main'leave { &out0("leave"); }
171
172 # SSE2
173 sub main'emms { &out0("emms"); }
174 sub main'movd { &out2("movd",@_); }
175 sub main'movq { &out2("movq",@_); }
176 sub main'movdqu { &out2("movdqu",@_); }
177 sub main'movdqa { &out2("movdqa",@_); }
178 sub main'movdq2q{ &out2("movdq2q",@_); }
179 sub main'movq2dq{ &out2("movq2dq",@_); }
180 sub main'paddq { &out2("paddq",@_); }
181 sub main'pmuludq{ &out2("pmuludq",@_); }
182 sub main'psrlq { &out2("psrlq",@_); }
183 sub main'psllq { &out2("psllq",@_); }
184 sub main'pxor { &out2("pxor",@_); }
185 sub main'por { &out2("por",@_); }
186 sub main'pand { &out2("pand",@_); }
187
188 sub out2
189 {
190 local($name,$p1,$p2)=@_;
191 local($l,$t);
192
193 push(@out,"\t$name\t");
194 $t=&conv($p1).",";
195 $l=length($t);
196 push(@out,$t);
197 $l=4-($l+9)/8;
198 push(@out,"\t" x $l);
199 push(@out,&conv($p2));
200 push(@out,"\n");
201 }
202
203 sub out0
204 {
205 local($name)=@_;
206
207 push(@out,"\t$name\n");
208 }
209
210 sub out1
211 {
212 local($name,$p1)=@_;
213 local($l,$t);
214
215 push(@out,"\t$name\t".&conv($p1)."\n");
216 }
217
218 sub conv
219 {
220 local($p)=@_;
221
222 $p =~ s/0x([0-9A-Fa-f]+)/0$1h/;
223 return $p;
224 }
225
226 sub using486
227 {
228 return if $using486;
229 $using486++;
230 grep(s/\.386/\.486/,@out);
231 }
232
233 sub main'file
234 {
235 local($file)=@_;
236
237 local($tmp)=<<"EOF";
238 TITLE $file.asm
239 .386
240 .model FLAT
241 EOF
242 push(@out,$tmp);
243 }
244
245 sub main'function_begin
246 {
247 local($func,$extra)=@_;
248
249 push(@labels,$func);
250
251 local($tmp)=<<"EOF";
252 _TEXT SEGMENT
253 PUBLIC _$func
254 $extra
255 _$func PROC NEAR
256 push ebp
257 push ebx
258 push esi
259 push edi
260 EOF
261 push(@out,$tmp);
262 $stack=20;
263 }
264
265 sub main'function_begin_B
266 {
267 local($func,$extra)=@_;
268
269 local($tmp)=<<"EOF";
270 _TEXT SEGMENT
271 PUBLIC _$func
272 $extra
273 _$func PROC NEAR
274 EOF
275 push(@out,$tmp);
276 $stack=4;
277 }
278
279 sub main'function_end
280 {
281 local($func)=@_;
282
283 local($tmp)=<<"EOF";
284 pop edi
285 pop esi
286 pop ebx
287 pop ebp
288 ret
289 _$func ENDP
290 _TEXT ENDS
291 EOF
292 push(@out,$tmp);
293 $stack=0;
294 %label=();
295 }
296
297 sub main'function_end_B
298 {
299 local($func)=@_;
300
301 local($tmp)=<<"EOF";
302 _$func ENDP
303 _TEXT ENDS
304 EOF
305 push(@out,$tmp);
306 $stack=0;
307 %label=();
308 }
309
310 sub main'function_end_A
311 {
312 local($func)=@_;
313
314 local($tmp)=<<"EOF";
315 pop edi
316 pop esi
317 pop ebx
318 pop ebp
319 ret
320 EOF
321 push(@out,$tmp);
322 }
323
324 sub main'file_end
325 {
326 # try to detect if SSE2 or MMX extensions were used...
327 if (grep {/xmm[0-7]\s*,/i} @out) {
328 grep {s/\.[3-7]86/\.786\n\t\.XMM/} @out;
329 }
330 elsif (grep {/mm[0-7]\s*,/i} @out) {
331 grep {s/\.[3-7]86/\.686\n\t\.MMX/} @out;
332 }
333 push(@out,"END\n");
334 }
335
336 sub main'wparam
337 {
338 local($num)=@_;
339
340 return(&main'DWP($stack+$num*4,"esp","",0));
341 }
342
343 sub main'swtmp
344 {
345 return(&main'DWP($_[0]*4,"esp","",0));
346 }
347
348 # Should use swtmp, which is above esp. Linix can trash the stack above esp
349 #sub main'wtmp
350 # {
351 # local($num)=@_;
352 #
353 # return(&main'DWP(-(($num+1)*4),"esp","",0));
354 # }
355
356 sub main'comment
357 {
358 foreach (@_)
359 {
360 push(@out,"\t; $_\n");
361 }
362 }
363
364 sub main'label
365 {
366 if (!defined($label{$_[0]}))
367 {
368 $label{$_[0]}="\$${label}${_[0]}";
369 $label++;
370 }
371 return($label{$_[0]});
372 }
373
374 sub main'set_label
375 {
376 if (!defined($label{$_[0]}))
377 {
378 $label{$_[0]}="\$${label}${_[0]}";
379 $label++;
380 }
381 if((defined $_[2]) && ($_[2] == 1))
382 {
383 push(@out,"$label{$_[0]}::\n");
384 }
385 else
386 {
387 push(@out,"$label{$_[0]}:\n");
388 }
389 }
390
391 sub main'data_word
392 {
393 push(@out,"\tDD\t".join(',',@_)."\n");
394 }
395
396 sub main'align
397 {
398 push(@out,"\tALIGN\t$_[0]\n");
399 }
400
401 sub out1p
402 {
403 local($name,$p1)=@_;
404 local($l,$t);
405
406 push(@out,"\t$name\t ".&conv($p1)."\n");
407 }
408
409 sub main'picmeup
410 {
411 local($dst,$sym)=@_;
412 &main'lea($dst,&main'DWP($sym));
413 }
414
415 sub main'blindpop { &out1("pop",@_); }