6
$under=($main'netware)?'':'_';
28
sub main'asm_init_output { @out=(); }
29
sub main'asm_get_output { return(@out); }
30
sub main'get_labels { return(@labels); }
32
sub main'external_label
36
push(@out,".") if ($main'mwerks);
37
push(@out, "extern\t${under}$_\n");
7
$::lbdecor="L\$"; # local label decoration
8
$nmdecor=$::netware?"":"_"; # external name decoration
9
$drdecor=$::mwerks?".":""; # directive decoration
18
{ if ($opcode =~ m/^j/o && $#_==0) # optimize jumps
19
{ $_[0] = "NEAR $_[0]"; }
20
elsif ($opcode eq "lea" && $#_==1) # wipe storage qualifier from lea
21
{ $_[1] =~ s/^[^\[]*\[/\[/o; }
43
(defined($lb{$_[0]})) || die "$_[0] does not have a 'low byte'\n";
49
(defined($hb{$_[0]})) || die "$_[0] does not have a 'high byte'\n";
70
return (($main'mwerks)?"":"BYTE ")."@_";
75
return (($main'mwerks)?"":"DWORD ")."@_";
82
&main'sub("esp",$num*4);
89
&main'add("esp",$num*4);
27
# opcodes not covered by ::generic above, mostly inconsistent namings...
29
sub ::call { &::emit("call",(&::islabel($_[0]) or "$nmdecor$_[0]")); }
30
sub ::call_ptr { &::emit("call",@_); }
31
sub ::jmp_ptr { &::emit("jmp",@_); }
94
my($size,$addr,$reg1,$reg2,$idx)=@_;
99
$ret .= " PTR" if ($main'mwerks);
104
if ($addr =~ /^(.+)\+(.+)$/)
109
elsif ($addr =~ /^[_a-z][_a-z0-9]*$/i)
114
if ($addr =~ /^.+\-.+$/) { $addr="($addr)"; }
116
$reg1="$regs{$reg1}" if defined($regs{$reg1});
117
$reg2="$regs{$reg2}" if defined($regs{$reg2});
118
if (($addr ne "") && ($addr ne 0))
121
{ $ret.="${addr}+"; }
122
else { $post=$addr; }
127
$t="*$idx" if ($idx != 0);
128
$reg1="+".$reg1 if ("$reg1$post" ne "");
129
$ret.="$reg2$t$reg1$post]";
135
$ret =~ s/\+\]/]/; # in case $addr was the only argument
139
sub main'mov { &out2("mov",@_); }
140
sub main'movb { &out2("mov",@_); }
141
sub main'and { &out2("and",@_); }
142
sub main'or { &out2("or",@_); }
143
sub main'shl { &out2("shl",@_); }
144
sub main'shr { &out2("shr",@_); }
145
sub main'xor { &out2("xor",@_); }
146
sub main'xorb { &out2("xor",@_); }
147
sub main'add { &out2("add",@_); }
148
sub main'adc { &out2("adc",@_); }
149
sub main'sub { &out2("sub",@_); }
150
sub main'sbb { &out2("sbb",@_); }
151
sub main'rotl { &out2("rol",@_); }
152
sub main'rotr { &out2("ror",@_); }
153
sub main'exch { &out2("xchg",@_); }
154
sub main'cmp { &out2("cmp",@_); }
155
sub main'lea { &out2("lea",@_); }
156
sub main'mul { &out1("mul",@_); }
157
sub main'imul { &out2("imul",@_); }
158
sub main'div { &out1("div",@_); }
159
sub main'dec { &out1("dec",@_); }
160
sub main'inc { &out1("inc",@_); }
161
sub main'jmp { &out1("jmp",@_); }
162
sub main'jmp_ptr { &out1p("jmp",@_); }
164
# This is a bit of a kludge: declare all branches as NEAR.
165
$near=($main'mwerks)?'':'NEAR';
166
sub main'je { &out1("je $near",@_); }
167
sub main'jle { &out1("jle $near",@_); }
168
sub main'jz { &out1("jz $near",@_); }
169
sub main'jge { &out1("jge $near",@_); }
170
sub main'jl { &out1("jl $near",@_); }
171
sub main'ja { &out1("ja $near",@_); }
172
sub main'jae { &out1("jae $near",@_); }
173
sub main'jb { &out1("jb $near",@_); }
174
sub main'jbe { &out1("jbe $near",@_); }
175
sub main'jc { &out1("jc $near",@_); }
176
sub main'jnc { &out1("jnc $near",@_); }
177
sub main'jnz { &out1("jnz $near",@_); }
178
sub main'jne { &out1("jne $near",@_); }
179
sub main'jno { &out1("jno $near",@_); }
181
sub main'push { &out1("push",@_); $stack+=4; }
182
sub main'pop { &out1("pop",@_); $stack-=4; }
183
sub main'pushf { &out0("pushfd"); $stack+=4; }
184
sub main'popf { &out0("popfd"); $stack-=4; }
185
sub main'bswap { &out1("bswap",@_); &using486(); }
186
sub main'not { &out1("not",@_); }
187
sub main'call { &out1("call",($_[0]=~/^\@L/?'':$under).$_[0]); }
188
sub main'call_ptr { &out1p("call",@_); }
189
sub main'ret { &out0("ret"); }
190
sub main'nop { &out0("nop"); }
191
sub main'test { &out2("test",@_); }
192
sub main'bt { &out2("bt",@_); }
193
sub main'leave { &out0("leave"); }
194
sub main'cpuid { &out0("cpuid"); }
195
sub main'rdtsc { &out0("rdtsc"); }
196
sub main'halt { &out0("hlt"); }
197
sub main'movz { &out2("movzx",@_); }
198
sub main'neg { &out1("neg",@_); }
199
sub main'cld { &out0("cld"); }
202
sub main'emms { &out0("emms"); }
203
sub main'movd { &out2("movd",@_); }
204
sub main'movq { &out2("movq",@_); }
205
sub main'movdqu { &out2("movdqu",@_); }
206
sub main'movdqa { &out2("movdqa",@_); }
207
sub main'movdq2q{ &out2("movdq2q",@_); }
208
sub main'movq2dq{ &out2("movq2dq",@_); }
209
sub main'paddq { &out2("paddq",@_); }
210
sub main'pmuludq{ &out2("pmuludq",@_); }
211
sub main'psrlq { &out2("psrlq",@_); }
212
sub main'psllq { &out2("psllq",@_); }
213
sub main'pxor { &out2("pxor",@_); }
214
sub main'por { &out2("por",@_); }
215
sub main'pand { &out2("pand",@_); }
219
my($name,$p1,$p2)=@_;
222
push(@out,"\t$name\t");
223
if (!$main'mwerks and $name eq "lea")
225
$p1 =~ s/^[^\[]*\[/\[/;
226
$p2 =~ s/^[^\[]*\[/\[/;
232
push(@out,"\t" x $l);
233
push(@out,&conv($p2));
241
push(@out,"\t$name\n");
248
push(@out,"\t$name\t".&conv($p1)."\n");
254
$p =~ s/0x([0-9A-Fa-f]+)/0$1h/;
262
grep(s/\.386/\.486/,@out);
267
if ($main'mwerks) { push(@out,".section\t.text\n"); }
271
section code use32 class=code
34
{ my($size,$addr,$reg1,$reg2,$idx)=@_;
39
$ret .= " PTR" if ($::mwerks);
45
# prepend global references with optional underscore
46
$addr =~ s/^([^\+\-0-9][^\+\-]*)/::islabel($1) or "$nmdecor$1"/ige;
47
# put address arithmetic expression in parenthesis
48
$addr="($addr)" if ($addr =~ /^.+[\-\+].+$/);
50
if (($addr ne "") && ($addr ne 0))
51
{ if ($addr !~ /^-/) { $ret .= "$addr+"; }
58
$ret .= "+$reg1" if ($reg1 ne "");
64
$ret =~ s/\+\]/]/; # in case $addr was the only argument
68
sub ::BP { &get_mem("BYTE",@_); }
69
sub ::DWP { &get_mem("DWORD",@_); }
70
sub ::QWP { &get_mem("",@_); }
71
sub ::BC { (($::mwerks)?"":"BYTE ")."@_"; }
72
sub ::DWC { (($::mwerks)?"":"DWORD ")."@_"; }
75
{ if ($::mwerks) { push(@out,".section\t.text,64\n"); }
78
%ifidn __OUTPUT_FORMAT__,obj
79
section code use32 class=code align=64
80
%elifidn __OUTPUT_FORMAT__,win32
82
section .text code align=64
280
sub main'function_begin
285
push(@out,".") if ($main'mwerks);
298
sub main'function_begin_B
301
push(@out,".") if ($main'mwerks);
310
sub main'function_end
326
sub main'function_end_B
332
sub main'function_end_A
354
return(&main'DWP($stack+$num*4,"esp","",0));
359
return(&main'DWP($_[0]*4,"esp","",0));
362
# Should use swtmp, which is above esp. Linix can trash the stack above esp
367
# return(&main'DWP(-(($num+1)*4),"esp","",0));
374
push(@out,"\t; $_\n");
378
sub main'public_label
380
$label{$_[0]}="${under}${_[0]}" if (!defined($label{$_[0]}));
381
push(@out,".") if ($main'mwerks);
382
push(@out,"global\t$label{$_[0]}\n");
387
if (!defined($label{$_[0]}))
389
$label{$_[0]}="\@${label}${_[0]}";
392
return($label{$_[0]});
397
if (!defined($label{$_[0]}))
399
$label{$_[0]}="\@${label}${_[0]}";
402
if ($_[1]!=0 && $_[1]>1)
406
push(@out,"$label{$_[0]}:\n");
411
push(@out,(($main'mwerks)?".byte\t":"DB\t").join(',',@_)."\n");
416
push(@out,(($main'mwerks)?".long\t":"DD\t").join(',',@_)."\n");
421
push(@out,".") if ($main'mwerks);
422
push(@out,"align\t$_[0]\n");
430
push(@out,"\t$name\t".&conv($p1)."\n");
436
&main'lea($dst,&main'DWP($sym));
439
sub main'blindpop { &out1("pop",@_); }
447
segment .CRT\$XCU data
91
sub ::function_begin_B
93
my $global=($func !~ /^_/);
94
my $begin="${::lbdecor}_${func}_begin";
96
$begin =~ s/^\@/./ if ($::mwerks); # the torture never stops
98
&::LABEL($func,$global?"$begin":"$nmdecor$func");
101
push(@out,"${drdecor}global $func\n") if ($global);
102
push(@out,"${drdecor}align 16\n");
103
push(@out,"$func:\n");
104
push(@out,"$begin:\n") if ($global);
114
{ if (grep {/\b${nmdecor}OPENSSL_ia32cap_P\b/i} @out)
116
${drdecor}segment .bss
117
${drdecor}common ${nmdecor}OPENSSL_ia32cap_P 4
119
# comment out OPENSSL_ia32cap_P declarations
120
grep {s/(^extern\s+${nmdecor}OPENSSL_ia32cap_P)/\;$1/} @out;
123
push (@out,$initseg) if ($initseg);
126
sub ::comment { foreach (@_) { push(@out,"\t; $_\n"); } }
130
{ push(@out,"${drdecor}extern\t".&::LABEL($_,$nmdecor.$_)."\n"); }
134
{ push(@out,"${drdecor}global\t".&::LABEL($_[0],$nmdecor.$_[0])."\n"); }
137
{ push(@out,(($::mwerks)?".byte\t":"db\t").join(',',@_)."\n"); }
140
{ push(@out,(($::mwerks)?".long\t":"dd\t").join(',',@_)."\n"); }
143
{ push(@out,"${drdecor}align\t$_[0]\n"); }
147
&::lea($dst,&::DWP($sym));
151
{ my $f=$nmdecor.shift;
154
segment .CRT\$XCU data align=4
162
{ if ($mwerks) { push(@out,".section\t.data,4\n"); }
163
else { push(@out,"section\t.data align=4\n"); }