]>
Commit | Line | Data |
---|---|---|
4b67fefe | 1 | #!/usr/bin/env perl |
72e2ffee DSH |
2 | |
3 | package x86nasm; | |
4 | ||
4b67fefe | 5 | *out=\@::out; |
72e2ffee | 6 | |
23dcb447 | 7 | $::lbdecor="L\$"; # local label decoration |
8789af8d AP |
8 | $nmdecor=$::netware?"":"_"; # external name decoration |
9 | $drdecor=$::mwerks?".":""; # directive decoration | |
10 | ||
1988a456 | 11 | $initseg=""; |
72e2ffee | 12 | |
4b67fefe AP |
13 | sub ::generic |
14 | { my $opcode=shift; | |
15 | my $tmp; | |
72e2ffee | 16 | |
4b67fefe AP |
17 | if (!$::mwerks) |
18 | { if ($opcode =~ m/^j/o && $#_==0) # optimize jumps | |
19 | { $_[0] = "NEAR $_[0]"; } | |
43d8f27d | 20 | elsif ($opcode eq "lea" && $#_==1) # wipe storage qualifier from lea |
4b67fefe AP |
21 | { $_[1] =~ s/^[^\[]*\[/\[/o; } |
22 | } | |
23 | &::emit($opcode,@_); | |
24 | 1; | |
bbdb5438 | 25 | } |
4b67fefe AP |
26 | # |
27 | # opcodes not covered by ::generic above, mostly inconsistent namings... | |
28 | # | |
43d8f27d | 29 | sub ::call { &::emit("call",(&::islabel($_[0]) or "$nmdecor$_[0]")); } |
4b67fefe AP |
30 | sub ::call_ptr { &::emit("call",@_); } |
31 | sub ::jmp_ptr { &::emit("jmp",@_); } | |
32 | ||
72e2ffee | 33 | sub get_mem |
4b67fefe AP |
34 | { my($size,$addr,$reg1,$reg2,$idx)=@_; |
35 | my($post,$ret); | |
36 | ||
37 | if ($size ne "") | |
38 | { $ret .= "$size"; | |
39 | $ret .= " PTR" if ($::mwerks); | |
40 | $ret .= " "; | |
41 | } | |
42 | $ret .= "["; | |
43 | ||
44 | $addr =~ s/^\s+//; | |
45 | # prepend global references with optional underscore | |
43d8f27d | 46 | $addr =~ s/^([^\+\-0-9][^\+\-]*)/::islabel($1) or "$nmdecor$1"/ige; |
4b67fefe AP |
47 | # put address arithmetic expression in parenthesis |
48 | $addr="($addr)" if ($addr =~ /^.+[\-\+].+$/); | |
49 | ||
50 | if (($addr ne "") && ($addr ne 0)) | |
51 | { if ($addr !~ /^-/) { $ret .= "$addr+"; } | |
52 | else { $post=$addr; } | |
53 | } | |
54 | ||
55 | if ($reg2 ne "") | |
56 | { $idx!=0 or $idx=1; | |
57 | $ret .= "$reg2*$idx"; | |
58 | $ret .= "+$reg1" if ($reg1 ne ""); | |
59 | } | |
60 | else | |
61 | { $ret .= "$reg1"; } | |
62 | ||
63 | $ret .= "$post]"; | |
64 | $ret =~ s/\+\]/]/; # in case $addr was the only argument | |
65 | ||
66 | $ret; | |
67 | } | |
68 | sub ::BP { &get_mem("BYTE",@_); } | |
69 | sub ::DWP { &get_mem("DWORD",@_); } | |
8b71d354 | 70 | sub ::QWP { &get_mem("",@_); } |
4b67fefe AP |
71 | sub ::BC { (($::mwerks)?"":"BYTE ")."@_"; } |
72 | sub ::DWC { (($::mwerks)?"":"DWORD ")."@_"; } | |
73 | ||
74 | sub ::file | |
43d8f27d | 75 | { if ($::mwerks) { push(@out,".section\t.text,64\n"); } |
4b67fefe AP |
76 | else |
77 | { my $tmp=<<___; | |
23dcb447 | 78 | %ifidn __OUTPUT_FORMAT__,obj |
4b67fefe | 79 | section code use32 class=code align=64 |
23dcb447 AP |
80 | %elifidn __OUTPUT_FORMAT__,win32 |
81 | \$\@feat.00 equ 1 | |
4b67fefe | 82 | section .text code align=64 |
23dcb447 AP |
83 | %else |
84 | section .text code | |
9ddeefe3 AP |
85 | %endif |
86 | ___ | |
72e2ffee | 87 | push(@out,$tmp); |
4b67fefe AP |
88 | } |
89 | } | |
72e2ffee | 90 | |
4b67fefe | 91 | sub ::function_begin_B |
c1d2e00e | 92 | { my $func=shift; |
8789af8d | 93 | my $global=($func !~ /^_/); |
43d8f27d | 94 | my $begin="${::lbdecor}_${func}_begin"; |
8789af8d | 95 | |
43d8f27d AP |
96 | $begin =~ s/^\@/./ if ($::mwerks); # the torture never stops |
97 | ||
98 | &::LABEL($func,$global?"$begin":"$nmdecor$func"); | |
8789af8d AP |
99 | $func=$nmdecor.$func; |
100 | ||
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); | |
4b67fefe AP |
105 | $::stack=4; |
106 | } | |
43d8f27d | 107 | |
4b67fefe | 108 | sub ::function_end_B |
43d8f27d AP |
109 | { $::stack=0; |
110 | &::wipe_labels(); | |
4b67fefe | 111 | } |
72e2ffee | 112 | |
4b67fefe | 113 | sub ::file_end |
43d8f27d AP |
114 | { if (grep {/\b${nmdecor}OPENSSL_ia32cap_P\b/i} @out) |
115 | { my $comm=<<___; | |
116 | ${drdecor}segment .bss | |
0ec55604 | 117 | ${drdecor}common ${nmdecor}OPENSSL_ia32cap_P 8 |
1988a456 | 118 | ___ |
8f41e4fa | 119 | # comment out OPENSSL_ia32cap_P declarations |
8789af8d | 120 | grep {s/(^extern\s+${nmdecor}OPENSSL_ia32cap_P)/\;$1/} @out; |
43d8f27d | 121 | push (@out,$comm) |
4b67fefe | 122 | } |
1988a456 | 123 | push (@out,$initseg) if ($initseg); |
4b67fefe | 124 | } |
72e2ffee | 125 | |
4b67fefe | 126 | sub ::comment { foreach (@_) { push(@out,"\t; $_\n"); } } |
d1df5b43 | 127 | |
4b67fefe | 128 | sub ::external_label |
3a87756f AP |
129 | { foreach(@_) |
130 | { push(@out,"${drdecor}extern\t".&::LABEL($_,$nmdecor.$_)."\n"); } | |
131 | } | |
72e2ffee | 132 | |
4b67fefe | 133 | sub ::public_label |
43d8f27d | 134 | { push(@out,"${drdecor}global\t".&::LABEL($_[0],$nmdecor.$_[0])."\n"); } |
72e2ffee | 135 | |
4b67fefe AP |
136 | sub ::data_byte |
137 | { push(@out,(($::mwerks)?".byte\t":"db\t").join(',',@_)."\n"); } | |
72e2ffee | 138 | |
4b67fefe AP |
139 | sub ::data_word |
140 | { push(@out,(($::mwerks)?".long\t":"dd\t").join(',',@_)."\n"); } | |
6f7ac8e1 | 141 | |
4b67fefe | 142 | sub ::align |
8789af8d | 143 | { push(@out,"${drdecor}align\t$_[0]\n"); } |
02bf9a15 | 144 | |
4b67fefe AP |
145 | sub ::picmeup |
146 | { my($dst,$sym)=@_; | |
147 | &::lea($dst,&::DWP($sym)); | |
148 | } | |
a8c65b40 | 149 | |
4b67fefe | 150 | sub ::initseg |
43d8f27d | 151 | { my $f=$nmdecor.shift; |
4b67fefe | 152 | if ($::win32) |
1988a456 AP |
153 | { $initseg=<<___; |
154 | segment .CRT\$XCU data align=4 | |
4b67fefe AP |
155 | extern $f |
156 | dd $f | |
a8c65b40 | 157 | ___ |
4b67fefe AP |
158 | } |
159 | } | |
a8c65b40 | 160 | |
b94551e8 AP |
161 | sub ::dataseg |
162 | { if ($mwerks) { push(@out,".section\t.data,4\n"); } | |
163 | else { push(@out,"section\t.data align=4\n"); } | |
164 | } | |
165 | ||
a8c65b40 | 166 | 1; |