xref: /onnv-gate/usr/src/common/openssl/crypto/perlasm/x86nasm.pl (revision 0:68f95e015346)
1*0Sstevel@tonic-gate#!/usr/local/bin/perl
2*0Sstevel@tonic-gate
3*0Sstevel@tonic-gatepackage x86nasm;
4*0Sstevel@tonic-gate
5*0Sstevel@tonic-gate$label="L000";
6*0Sstevel@tonic-gate
7*0Sstevel@tonic-gate%lb=(	'eax',	'al',
8*0Sstevel@tonic-gate	'ebx',	'bl',
9*0Sstevel@tonic-gate	'ecx',	'cl',
10*0Sstevel@tonic-gate	'edx',	'dl',
11*0Sstevel@tonic-gate	'ax',	'al',
12*0Sstevel@tonic-gate	'bx',	'bl',
13*0Sstevel@tonic-gate	'cx',	'cl',
14*0Sstevel@tonic-gate	'dx',	'dl',
15*0Sstevel@tonic-gate	);
16*0Sstevel@tonic-gate
17*0Sstevel@tonic-gate%hb=(	'eax',	'ah',
18*0Sstevel@tonic-gate	'ebx',	'bh',
19*0Sstevel@tonic-gate	'ecx',	'ch',
20*0Sstevel@tonic-gate	'edx',	'dh',
21*0Sstevel@tonic-gate	'ax',	'ah',
22*0Sstevel@tonic-gate	'bx',	'bh',
23*0Sstevel@tonic-gate	'cx',	'ch',
24*0Sstevel@tonic-gate	'dx',	'dh',
25*0Sstevel@tonic-gate	);
26*0Sstevel@tonic-gate
27*0Sstevel@tonic-gatesub main'asm_init_output { @out=(); }
28*0Sstevel@tonic-gatesub main'asm_get_output { return(@out); }
29*0Sstevel@tonic-gatesub main'get_labels { return(@labels); }
30*0Sstevel@tonic-gate
31*0Sstevel@tonic-gatesub main'external_label
32*0Sstevel@tonic-gate{
33*0Sstevel@tonic-gate	push(@labels,@_);
34*0Sstevel@tonic-gate	foreach (@_) {
35*0Sstevel@tonic-gate		push(@out, "extern\t_$_\n");
36*0Sstevel@tonic-gate	}
37*0Sstevel@tonic-gate}
38*0Sstevel@tonic-gate
39*0Sstevel@tonic-gatesub main'LB
40*0Sstevel@tonic-gate	{
41*0Sstevel@tonic-gate	(defined($lb{$_[0]})) || die "$_[0] does not have a 'low byte'\n";
42*0Sstevel@tonic-gate	return($lb{$_[0]});
43*0Sstevel@tonic-gate	}
44*0Sstevel@tonic-gate
45*0Sstevel@tonic-gatesub main'HB
46*0Sstevel@tonic-gate	{
47*0Sstevel@tonic-gate	(defined($hb{$_[0]})) || die "$_[0] does not have a 'high byte'\n";
48*0Sstevel@tonic-gate	return($hb{$_[0]});
49*0Sstevel@tonic-gate	}
50*0Sstevel@tonic-gate
51*0Sstevel@tonic-gatesub main'BP
52*0Sstevel@tonic-gate	{
53*0Sstevel@tonic-gate	&get_mem("BYTE",@_);
54*0Sstevel@tonic-gate	}
55*0Sstevel@tonic-gate
56*0Sstevel@tonic-gatesub main'DWP
57*0Sstevel@tonic-gate	{
58*0Sstevel@tonic-gate	&get_mem("DWORD",@_);
59*0Sstevel@tonic-gate	}
60*0Sstevel@tonic-gate
61*0Sstevel@tonic-gatesub main'BC
62*0Sstevel@tonic-gate	{
63*0Sstevel@tonic-gate	return "BYTE @_";
64*0Sstevel@tonic-gate	}
65*0Sstevel@tonic-gate
66*0Sstevel@tonic-gatesub main'DWC
67*0Sstevel@tonic-gate	{
68*0Sstevel@tonic-gate	return "DWORD @_";
69*0Sstevel@tonic-gate	}
70*0Sstevel@tonic-gate
71*0Sstevel@tonic-gatesub main'stack_push
72*0Sstevel@tonic-gate	{
73*0Sstevel@tonic-gate	my($num)=@_;
74*0Sstevel@tonic-gate	$stack+=$num*4;
75*0Sstevel@tonic-gate	&main'sub("esp",$num*4);
76*0Sstevel@tonic-gate	}
77*0Sstevel@tonic-gate
78*0Sstevel@tonic-gatesub main'stack_pop
79*0Sstevel@tonic-gate	{
80*0Sstevel@tonic-gate	my($num)=@_;
81*0Sstevel@tonic-gate	$stack-=$num*4;
82*0Sstevel@tonic-gate	&main'add("esp",$num*4);
83*0Sstevel@tonic-gate	}
84*0Sstevel@tonic-gate
85*0Sstevel@tonic-gatesub get_mem
86*0Sstevel@tonic-gate	{
87*0Sstevel@tonic-gate	my($size,$addr,$reg1,$reg2,$idx)=@_;
88*0Sstevel@tonic-gate	my($t,$post);
89*0Sstevel@tonic-gate	my($ret)="[";
90*0Sstevel@tonic-gate	$addr =~ s/^\s+//;
91*0Sstevel@tonic-gate	if ($addr =~ /^(.+)\+(.+)$/)
92*0Sstevel@tonic-gate		{
93*0Sstevel@tonic-gate		$reg2=&conv($1);
94*0Sstevel@tonic-gate		$addr="_$2";
95*0Sstevel@tonic-gate		}
96*0Sstevel@tonic-gate	elsif ($addr =~ /^[_a-zA-Z]/)
97*0Sstevel@tonic-gate		{
98*0Sstevel@tonic-gate		$addr="_$addr";
99*0Sstevel@tonic-gate		}
100*0Sstevel@tonic-gate
101*0Sstevel@tonic-gate	if ($addr =~ /^.+\-.+$/) { $addr="($addr)"; }
102*0Sstevel@tonic-gate
103*0Sstevel@tonic-gate	$reg1="$regs{$reg1}" if defined($regs{$reg1});
104*0Sstevel@tonic-gate	$reg2="$regs{$reg2}" if defined($regs{$reg2});
105*0Sstevel@tonic-gate	if (($addr ne "") && ($addr ne 0))
106*0Sstevel@tonic-gate		{
107*0Sstevel@tonic-gate		if ($addr !~ /^-/)
108*0Sstevel@tonic-gate			{ $ret.="${addr}+"; }
109*0Sstevel@tonic-gate		else	{ $post=$addr; }
110*0Sstevel@tonic-gate		}
111*0Sstevel@tonic-gate	if ($reg2 ne "")
112*0Sstevel@tonic-gate		{
113*0Sstevel@tonic-gate		$t="";
114*0Sstevel@tonic-gate		$t="*$idx" if ($idx != 0);
115*0Sstevel@tonic-gate		$reg1="+".$reg1 if ("$reg1$post" ne "");
116*0Sstevel@tonic-gate		$ret.="$reg2$t$reg1$post]";
117*0Sstevel@tonic-gate		}
118*0Sstevel@tonic-gate	else
119*0Sstevel@tonic-gate		{
120*0Sstevel@tonic-gate		$ret.="$reg1$post]"
121*0Sstevel@tonic-gate		}
122*0Sstevel@tonic-gate	$ret =~ s/\+\]/]/; # in case $addr was the only argument
123*0Sstevel@tonic-gate	return($ret);
124*0Sstevel@tonic-gate	}
125*0Sstevel@tonic-gate
126*0Sstevel@tonic-gatesub main'mov	{ &out2("mov",@_); }
127*0Sstevel@tonic-gatesub main'movb	{ &out2("mov",@_); }
128*0Sstevel@tonic-gatesub main'and	{ &out2("and",@_); }
129*0Sstevel@tonic-gatesub main'or	{ &out2("or",@_); }
130*0Sstevel@tonic-gatesub main'shl	{ &out2("shl",@_); }
131*0Sstevel@tonic-gatesub main'shr	{ &out2("shr",@_); }
132*0Sstevel@tonic-gatesub main'xor	{ &out2("xor",@_); }
133*0Sstevel@tonic-gatesub main'xorb	{ &out2("xor",@_); }
134*0Sstevel@tonic-gatesub main'add	{ &out2("add",@_); }
135*0Sstevel@tonic-gatesub main'adc	{ &out2("adc",@_); }
136*0Sstevel@tonic-gatesub main'sub	{ &out2("sub",@_); }
137*0Sstevel@tonic-gatesub main'rotl	{ &out2("rol",@_); }
138*0Sstevel@tonic-gatesub main'rotr	{ &out2("ror",@_); }
139*0Sstevel@tonic-gatesub main'exch	{ &out2("xchg",@_); }
140*0Sstevel@tonic-gatesub main'cmp	{ &out2("cmp",@_); }
141*0Sstevel@tonic-gatesub main'lea	{ &out2("lea",@_); }
142*0Sstevel@tonic-gatesub main'mul	{ &out1("mul",@_); }
143*0Sstevel@tonic-gatesub main'div	{ &out1("div",@_); }
144*0Sstevel@tonic-gatesub main'dec	{ &out1("dec",@_); }
145*0Sstevel@tonic-gatesub main'inc	{ &out1("inc",@_); }
146*0Sstevel@tonic-gatesub main'jmp	{ &out1("jmp",@_); }
147*0Sstevel@tonic-gatesub main'jmp_ptr { &out1p("jmp",@_); }
148*0Sstevel@tonic-gate
149*0Sstevel@tonic-gate# This is a bit of a kludge: declare all branches as NEAR.
150*0Sstevel@tonic-gatesub main'je	{ &out1("je NEAR",@_); }
151*0Sstevel@tonic-gatesub main'jle	{ &out1("jle NEAR",@_); }
152*0Sstevel@tonic-gatesub main'jz	{ &out1("jz NEAR",@_); }
153*0Sstevel@tonic-gatesub main'jge	{ &out1("jge NEAR",@_); }
154*0Sstevel@tonic-gatesub main'jl	{ &out1("jl NEAR",@_); }
155*0Sstevel@tonic-gatesub main'ja	{ &out1("ja NEAR",@_); }
156*0Sstevel@tonic-gatesub main'jae	{ &out1("jae NEAR",@_); }
157*0Sstevel@tonic-gatesub main'jb	{ &out1("jb NEAR",@_); }
158*0Sstevel@tonic-gatesub main'jbe	{ &out1("jbe NEAR",@_); }
159*0Sstevel@tonic-gatesub main'jc	{ &out1("jc NEAR",@_); }
160*0Sstevel@tonic-gatesub main'jnc	{ &out1("jnc NEAR",@_); }
161*0Sstevel@tonic-gatesub main'jnz	{ &out1("jnz NEAR",@_); }
162*0Sstevel@tonic-gatesub main'jne	{ &out1("jne NEAR",@_); }
163*0Sstevel@tonic-gatesub main'jno	{ &out1("jno NEAR",@_); }
164*0Sstevel@tonic-gate
165*0Sstevel@tonic-gatesub main'push	{ &out1("push",@_); $stack+=4; }
166*0Sstevel@tonic-gatesub main'pop	{ &out1("pop",@_); $stack-=4; }
167*0Sstevel@tonic-gatesub main'bswap	{ &out1("bswap",@_); &using486(); }
168*0Sstevel@tonic-gatesub main'not	{ &out1("not",@_); }
169*0Sstevel@tonic-gatesub main'call	{ &out1("call",($_[0]=~/^\$L/?'':'_').$_[0]); }
170*0Sstevel@tonic-gatesub main'ret	{ &out0("ret"); }
171*0Sstevel@tonic-gatesub main'nop	{ &out0("nop"); }
172*0Sstevel@tonic-gate
173*0Sstevel@tonic-gatesub out2
174*0Sstevel@tonic-gate	{
175*0Sstevel@tonic-gate	my($name,$p1,$p2)=@_;
176*0Sstevel@tonic-gate	my($l,$t);
177*0Sstevel@tonic-gate
178*0Sstevel@tonic-gate	push(@out,"\t$name\t");
179*0Sstevel@tonic-gate	$t=&conv($p1).",";
180*0Sstevel@tonic-gate	$l=length($t);
181*0Sstevel@tonic-gate	push(@out,$t);
182*0Sstevel@tonic-gate	$l=4-($l+9)/8;
183*0Sstevel@tonic-gate	push(@out,"\t" x $l);
184*0Sstevel@tonic-gate	push(@out,&conv($p2));
185*0Sstevel@tonic-gate	push(@out,"\n");
186*0Sstevel@tonic-gate	}
187*0Sstevel@tonic-gate
188*0Sstevel@tonic-gatesub out0
189*0Sstevel@tonic-gate	{
190*0Sstevel@tonic-gate	my($name)=@_;
191*0Sstevel@tonic-gate
192*0Sstevel@tonic-gate	push(@out,"\t$name\n");
193*0Sstevel@tonic-gate	}
194*0Sstevel@tonic-gate
195*0Sstevel@tonic-gatesub out1
196*0Sstevel@tonic-gate	{
197*0Sstevel@tonic-gate	my($name,$p1)=@_;
198*0Sstevel@tonic-gate	my($l,$t);
199*0Sstevel@tonic-gate	push(@out,"\t$name\t".&conv($p1)."\n");
200*0Sstevel@tonic-gate	}
201*0Sstevel@tonic-gate
202*0Sstevel@tonic-gatesub conv
203*0Sstevel@tonic-gate	{
204*0Sstevel@tonic-gate	my($p)=@_;
205*0Sstevel@tonic-gate	$p =~ s/0x([0-9A-Fa-f]+)/0$1h/;
206*0Sstevel@tonic-gate	return $p;
207*0Sstevel@tonic-gate	}
208*0Sstevel@tonic-gate
209*0Sstevel@tonic-gatesub using486
210*0Sstevel@tonic-gate	{
211*0Sstevel@tonic-gate	return if $using486;
212*0Sstevel@tonic-gate	$using486++;
213*0Sstevel@tonic-gate	grep(s/\.386/\.486/,@out);
214*0Sstevel@tonic-gate	}
215*0Sstevel@tonic-gate
216*0Sstevel@tonic-gatesub main'file
217*0Sstevel@tonic-gate	{
218*0Sstevel@tonic-gate	push(@out, "segment .text use32\n");
219*0Sstevel@tonic-gate	}
220*0Sstevel@tonic-gate
221*0Sstevel@tonic-gatesub main'function_begin
222*0Sstevel@tonic-gate	{
223*0Sstevel@tonic-gate	my($func,$extra)=@_;
224*0Sstevel@tonic-gate
225*0Sstevel@tonic-gate	push(@labels,$func);
226*0Sstevel@tonic-gate	my($tmp)=<<"EOF";
227*0Sstevel@tonic-gateglobal	_$func
228*0Sstevel@tonic-gate_$func:
229*0Sstevel@tonic-gate	push	ebp
230*0Sstevel@tonic-gate	push	ebx
231*0Sstevel@tonic-gate	push	esi
232*0Sstevel@tonic-gate	push	edi
233*0Sstevel@tonic-gateEOF
234*0Sstevel@tonic-gate	push(@out,$tmp);
235*0Sstevel@tonic-gate	$stack=20;
236*0Sstevel@tonic-gate	}
237*0Sstevel@tonic-gate
238*0Sstevel@tonic-gatesub main'function_begin_B
239*0Sstevel@tonic-gate	{
240*0Sstevel@tonic-gate	my($func,$extra)=@_;
241*0Sstevel@tonic-gate	my($tmp)=<<"EOF";
242*0Sstevel@tonic-gateglobal	_$func
243*0Sstevel@tonic-gate_$func:
244*0Sstevel@tonic-gateEOF
245*0Sstevel@tonic-gate	push(@out,$tmp);
246*0Sstevel@tonic-gate	$stack=4;
247*0Sstevel@tonic-gate	}
248*0Sstevel@tonic-gate
249*0Sstevel@tonic-gatesub main'function_end
250*0Sstevel@tonic-gate	{
251*0Sstevel@tonic-gate	my($func)=@_;
252*0Sstevel@tonic-gate
253*0Sstevel@tonic-gate	my($tmp)=<<"EOF";
254*0Sstevel@tonic-gate	pop	edi
255*0Sstevel@tonic-gate	pop	esi
256*0Sstevel@tonic-gate	pop	ebx
257*0Sstevel@tonic-gate	pop	ebp
258*0Sstevel@tonic-gate	ret
259*0Sstevel@tonic-gateEOF
260*0Sstevel@tonic-gate	push(@out,$tmp);
261*0Sstevel@tonic-gate	$stack=0;
262*0Sstevel@tonic-gate	%label=();
263*0Sstevel@tonic-gate	}
264*0Sstevel@tonic-gate
265*0Sstevel@tonic-gatesub main'function_end_B
266*0Sstevel@tonic-gate	{
267*0Sstevel@tonic-gate	$stack=0;
268*0Sstevel@tonic-gate	%label=();
269*0Sstevel@tonic-gate	}
270*0Sstevel@tonic-gate
271*0Sstevel@tonic-gatesub main'function_end_A
272*0Sstevel@tonic-gate	{
273*0Sstevel@tonic-gate	my($func)=@_;
274*0Sstevel@tonic-gate
275*0Sstevel@tonic-gate	my($tmp)=<<"EOF";
276*0Sstevel@tonic-gate	pop	edi
277*0Sstevel@tonic-gate	pop	esi
278*0Sstevel@tonic-gate	pop	ebx
279*0Sstevel@tonic-gate	pop	ebp
280*0Sstevel@tonic-gate	ret
281*0Sstevel@tonic-gateEOF
282*0Sstevel@tonic-gate	push(@out,$tmp);
283*0Sstevel@tonic-gate	}
284*0Sstevel@tonic-gate
285*0Sstevel@tonic-gatesub main'file_end
286*0Sstevel@tonic-gate	{
287*0Sstevel@tonic-gate	}
288*0Sstevel@tonic-gate
289*0Sstevel@tonic-gatesub main'wparam
290*0Sstevel@tonic-gate	{
291*0Sstevel@tonic-gate	my($num)=@_;
292*0Sstevel@tonic-gate
293*0Sstevel@tonic-gate	return(&main'DWP($stack+$num*4,"esp","",0));
294*0Sstevel@tonic-gate	}
295*0Sstevel@tonic-gate
296*0Sstevel@tonic-gatesub main'swtmp
297*0Sstevel@tonic-gate	{
298*0Sstevel@tonic-gate	return(&main'DWP($_[0]*4,"esp","",0));
299*0Sstevel@tonic-gate	}
300*0Sstevel@tonic-gate
301*0Sstevel@tonic-gate# Should use swtmp, which is above esp.  Linix can trash the stack above esp
302*0Sstevel@tonic-gate#sub main'wtmp
303*0Sstevel@tonic-gate#	{
304*0Sstevel@tonic-gate#	my($num)=@_;
305*0Sstevel@tonic-gate#
306*0Sstevel@tonic-gate#	return(&main'DWP(-(($num+1)*4),"esp","",0));
307*0Sstevel@tonic-gate#	}
308*0Sstevel@tonic-gate
309*0Sstevel@tonic-gatesub main'comment
310*0Sstevel@tonic-gate	{
311*0Sstevel@tonic-gate	foreach (@_)
312*0Sstevel@tonic-gate		{
313*0Sstevel@tonic-gate		push(@out,"\t; $_\n");
314*0Sstevel@tonic-gate		}
315*0Sstevel@tonic-gate	}
316*0Sstevel@tonic-gate
317*0Sstevel@tonic-gatesub main'label
318*0Sstevel@tonic-gate	{
319*0Sstevel@tonic-gate	if (!defined($label{$_[0]}))
320*0Sstevel@tonic-gate		{
321*0Sstevel@tonic-gate		$label{$_[0]}="\$${label}${_[0]}";
322*0Sstevel@tonic-gate		$label++;
323*0Sstevel@tonic-gate		}
324*0Sstevel@tonic-gate	return($label{$_[0]});
325*0Sstevel@tonic-gate	}
326*0Sstevel@tonic-gate
327*0Sstevel@tonic-gatesub main'set_label
328*0Sstevel@tonic-gate	{
329*0Sstevel@tonic-gate	if (!defined($label{$_[0]}))
330*0Sstevel@tonic-gate		{
331*0Sstevel@tonic-gate		$label{$_[0]}="\$${label}${_[0]}";
332*0Sstevel@tonic-gate		$label++;
333*0Sstevel@tonic-gate		}
334*0Sstevel@tonic-gate	push(@out,"$label{$_[0]}:\n");
335*0Sstevel@tonic-gate	}
336*0Sstevel@tonic-gate
337*0Sstevel@tonic-gatesub main'data_word
338*0Sstevel@tonic-gate	{
339*0Sstevel@tonic-gate	push(@out,"\tDD\t$_[0]\n");
340*0Sstevel@tonic-gate	}
341*0Sstevel@tonic-gate
342*0Sstevel@tonic-gatesub out1p
343*0Sstevel@tonic-gate	{
344*0Sstevel@tonic-gate	my($name,$p1)=@_;
345*0Sstevel@tonic-gate	my($l,$t);
346*0Sstevel@tonic-gate
347*0Sstevel@tonic-gate	push(@out,"\t$name\t ".&conv($p1)."\n");
348*0Sstevel@tonic-gate	}
349*0Sstevel@tonic-gate
350*0Sstevel@tonic-gatesub main'picmeup
351*0Sstevel@tonic-gate	{
352*0Sstevel@tonic-gate	local($dst,$sym)=@_;
353*0Sstevel@tonic-gate	&main'lea($dst,&main'DWP($sym));
354*0Sstevel@tonic-gate	}
355*0Sstevel@tonic-gate
356*0Sstevel@tonic-gatesub main'blindpop { &out1("pop",@_); }
357