Subversion Repositories programming

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
117 ira 1
#!/usr/bin/perl -w
2
 
3
$DEBUG = 0;
4
$us = ""; # underscore char. gcc linux does not add `_' to names !?!
5
 
6
%directives = (
7
	       title => AddPrefixDot,
8
	       if => AddPrefixDot,
9
	       ifdef => AddPrefixDot,
10
	       ifndef => AddPrefixDot,
11
	       ifnotdef => AddPrefixDot,
12
	       else => AddPrefixDot,
13
	       endif => AddPrefixDot,
14
	       include => HandleInclude,
15
	       ".586" => IgnoreLine,
16
	       ".mmx" => IgnoreLine,
17
	       ".xmm" => IgnoreLine,
18
	       ".model" => IgnoreLine,
19
	       ".code" => SetTextSect,
20
	       ".const" => SetTextSect,
21
	       public => HandlePublic,
22
	       extrn => HandleExtern,
23
	       extern => HandleExtern,
24
	       externdef => HandleExtern,
25
	       option => HandleOption,
26
	       end => IgnoreLine,
27
	       );
28
 
29
%UsedRegTypes = (
30
		 "eax", "l", "ebx", "l", "ecx", "l", "edx", "l",
31
		 "esi", "l", "edi", "l", "esp", "l", "ebp", "l",
32
		 "ax", "w", "bx", "w", "cx", "w", "dx", "w",
33
		 "si", "w", "di", "w", "sp", "w", "bp", "w",
34
		 );
35
 
36
%RegisterList = ( %UsedRegTypes, 
37
		  (
38
		   "ah", "b", "al", "b", "bh", "b", "bl", "b",
39
		   "ch", "b", "cl", "b", "dh", "b", "dl", "b",
40
		   "st", "f",
41
		   "st(0)", "f", "st(1)", "f", "st(2)", "f", "st(3)", "f",
42
		   "st(4)", "f", "st(5)", "f", "st(6)", "f", "st(7)", "f",
43
		   "mm0", "q", "mm1", "q", "mm2", "q", "mm3", "q",
44
		   "mm4", "q", "mm5", "q", "mm6", "q", "mm7", "q",
45
		   )
46
		  );
47
 
48
%MemoryTypes = (
49
		"byte", "b", "char", "b", "bp", "b",
50
		"word", "w", "sword", "w", "wp", "w",
51
		"dword", "l", "sdword", "l", "dwp", "l",
52
		"qword", "q", "sqword", "q", "qwp", "q",
53
		"real10", "t", "tbyte", "t",
54
		);
55
 
56
%IntToFloatType = ( "b", "???", # Not supposed to happen!
57
		    "w", "???", # Not supposed to happen!
58
		    "l", "s",
59
		    "q", "l",
60
		    "t", "t",
61
		    );
62
 
63
%MemTypeToDef = (
64
		 "b", "byte", "w", "short", "l", "long", "q", "long",
65
		 );
66
 
67
%SegAlignTypes = (
68
		  "byte", "0",
69
		  "word", "1",
70
		  "dword", "2",
71
		  "para", "4",
72
		  "page", "8",
73
		  ); 
74
 
75
%SegCombineTypes = (
76
		    "private", "",
77
		    "public", ".globl",
78
		    "stack", "",
79
		    "common", "",
80
		    "memory", "",
81
		    "at", "",
82
		    );
83
 
84
%SegUseTypes = (
85
		"use16", "",
86
		"use32", "",
87
		"flat", "",
88
		);
89
 
90
%DAllocTypes = (
91
		"byte", ".byte", "db", ".byte",
92
		"sword", ".short", "word", ".word", "dw", ".word",
93
		"sdword", ".long", "dword", ".long", "dd", ".long",
94
		"ptr", ".long",
95
		"fword", "", "df", "",
96
		"sqword", ".quad", "qword", ".quad", "dq", ".quad",
97
		"tbyte", "", "dt", "",
98
		"real4", ".single",
99
		"real8", ".double",
100
		"real10", ".tfloat",
101
		);
102
 
103
%DAllocAlignTypes = (
104
		  ".byte", "0",
105
		  ".word", "1",
106
		  ".short", "1",
107
		  ".long", "2",
108
		  ".quad", "3",
109
		  ".single", "2",
110
		  ".double", "3",
111
		  ".tfloat", "4",
112
		  ); 
113
 
114
%LabelTypeToInst = (
115
		    ".byte", "b",
116
		    ".short", "w", ".word", "w",
117
		    ".long", "l",
118
		    ".quad", "q",
119
		    ".single", "s",
120
		    ".double", "l",
121
		    ".tfloat", "t",
122
		    );
123
 
124
sub PrintHash {
125
    my ( %h ) = @_;
126
    while(($key, $value) = each %h) {
127
	print "#$key: $value\n";
128
    }
129
    print "\n";
130
}
131
 
132
PrintHash( %directives ) if $DEBUG;
133
PrintHash( %UsedRegTypes ) if $DEBUG;
134
PrintHash( %RegisterList ) if $DEBUG;
135
PrintHash( %MemoryTypes ) if $DEBUG;
136
PrintHash( %MemTypeToDef ) if $DEBUG;
137
 
138
print "\nProgram Results:\n\n" if $DEBUG;
139
 
140
$warn_fixed = 0;
141
$first = $second = $body = $rest = $indent = "";
142
$old_prologue = $old_epilogue = $prologue = $epilogue = 1;
143
$FuncName = $FuncType = "";
144
@FuncArgs = ();
145
@FuncArgsRef = ();
146
@UsedRegs = ();
147
@LabelTypes = ();
148
@EquList = ();
149
 
150
unless ( $#ARGV == 1 ) {
151
    printf STDERR "Usages: $0 <in-asm-file> <out-s-file>\n";
152
    exit -1;
153
}
154
 
155
$asmFile = $ARGV[0];
156
open STDIN, $asmFile
157
    or die "Cannot open input file `$asmFile': $!\n";
158
 
159
#($asmOutFile) = (lc($asmFile) =~ /^(.*)\.asm$/);
160
$asmOutFile = $ARGV[1];
161
open STDOUT, ">$asmOutFile"
162
    or die "Cannot open output file `$asmOutFile.s': $!\n";
163
 
164
$warn_fixed = 1 if ( defined($ARGV[1]) && ($ARGV[1] eq "-wfixed") );
165
 
166
$asmFile =~ /[^\/]+$/;
167
print ".file \"$&\"\n";
168
print "# Auto-converted from Intel's assembly format to AT&T's format\n\n";
169
 
170
# Find all labels & equs in advance:
171
while( <> ) {
172
    my ( $ename, $etype, $ltype );
173
 
174
    CanonizeAndComment( $_ );
175
    next unless defined $first;
176
 
177
    # Handle COMMENTS:
178
    if ( uc($first) eq "COMMENT" ) {
179
	while ( ($_ = <>) !~ /\^/ ) {
180
	    ;
181
	}
182
	next;
183
    }
184
 
185
    if ( $first =~ /:$/ ) {
186
	$LabelTypes{ $` } = "";
187
	next;
188
    }
189
 
190
    if ( lc $first eq ".data" ) {
191
	my ( $dtype );
192
 
193
	while ( ($_ = <>) !~ /^\./ ) {
194
	    CanonizeAndComment();
195
	    $etype = $directives{ lc $first };
196
	    if ( defined($etype) &&
197
		 (($etype eq "HandleExtern") || ($etype eq "HandlePublic")) ) {
198
		GetExternOrPublic();
199
	    }
200
	    elsif ( defined($second) && defined($DAllocTypes{ lc $second }) ) {
201
		$dtype = $LabelTypeToInst{ $DAllocTypes{lc $second} };
202
		$LabelTypes{ "$us$first" } = $dtype . "C";
203
	    }
204
	}
205
	next;
206
    }
207
 
208
    next unless defined $second;
209
 
210
    if ( lc $second eq "label" ) {
211
	$ltype = GetLabelType( @arr_line );
212
	if ( $body =~ /\s+C($|[\s,]+)/ ) {
213
	    $first = "$us$first";
214
	    $ltype = $ltype . "C";
215
	}
216
	$LabelTypes{ $first } = $ltype;
217
	next;
218
    }
219
 
220
    if ( defined($DAllocTypes{lc($second)}) ) {
221
	$LabelTypes{ $first } = $LabelTypeToInst{ $DAllocTypes{lc($second)} };
222
	next;
223
    }
224
 
225
    $etype = $directives{ lc $first };
226
    if ( defined($etype) &&
227
	 ( ($etype eq "HandleExtern") || ($etype eq "HandlePublic") ) ) {
228
	GetExternOrPublic();
229
	next;
230
    }
231
 
232
    if ( lc $second eq "equ" ) {
233
	$EquList{ $first } = Enumerate($arr_line[2]);
234
	next;
235
    }
236
 
237
    if ( lc $second eq "proc" ) {
238
	my ( $fname, $ftype ) = ( "", "" );
239
 
240
	if ( $body =~ /\s+C($|[\s,]+)/ ) {
241
	    $fname = "$us" ;
242
	    $ftype = "C";
243
	}
244
	$fname = "$fname$first";
245
	$LabelTypes{ $fname } = "$ftype";
246
    }
247
 
248
}
249
 
250
sub GetExternOrPublic {
251
    my ( $etype, $ename );
252
 
253
    $body =~ /\S+\s*(C?)\s+([^:\s]*)\s*(:?)\s*(\S+)/;
254
    if ( $3 eq ":" ) {
255
	$etype = $DAllocTypes{lc($4)} if defined($4);
256
	$etype = $LabelTypeToInst{ $etype } if defined($etype);
257
	$ename = $2;
258
    }
259
    else {
260
	$body =~ /(\S+)$/;
261
	$ename = $1;
262
	$etype = "l";
263
    }
264
    if ( $body =~ /\s+C($|[\s,])/ ) {
265
	$ename = "$us$ename";
266
	$etype = $etype . "C";
267
    }
268
    $LabelTypes{ $ename } = $etype;
269
}
270
 
271
PrintHash( %LabelTypes ) if $DEBUG;
272
PrintHash( %EquList ) if $DEBUG;
273
 
274
seek STDIN, 0, 0;
275
 
276
while( <> ) {
277
# Any handling that reads more input needs to go back here (COMMENTS & PROC).
278
restart:
279
    CanonizeAndComment( $_ );
280
 
281
    # Handle COMMENTS:
282
    if ( uc($first) eq "COMMENT" ) {
283
	($rest) = $rest =~ /\s*\^(.*)/o;
284
	print "# $rest\n";
285
	while ( ($_ = <>) !~ /\^/ ) {
286
	    print "# $_";
287
	}
288
	$_ =~ /\^/;
289
	print "$`#";
290
	$_ = $';
291
	goto restart;
292
    }
293
 
294
    goto print_end unless defined $first;
295
 
296
    # Handle known directives
297
    my $var = $directives{ lc $first };
298
    if ( (defined $var) && (defined &$var) ) {
299
	$line = &$var( lc $first, $rest );
300
	print $line;
301
	goto print_end;
302
    }
303
 
304
    # Handle labels:
305
    if ( $first =~ /:/ ) {
306
	print "$first";
307
	print " $rest" if defined $rest;
308
	$indent = "    ";
309
	goto print_end;
310
    }
311
 
312
    # Handle ret (pop regs, restore frame):
313
    if ( lc $first eq "ret" ) {
314
	if ( ($FuncName eq "") && ($epilogue) ) {
315
	    print STDERR "Warning: ret on line $.,".
316
		" outside a function context!\n";
317
	}
318
	else {
319
	    HandleRet() if $epilogue;
320
	}
321
	print $indent, "$first";
322
	print " $rest" if defined $rest;
323
	goto print_end;
324
    }
325
 
326
    # Handle .directives, and any stuff which isn't an instruction:
327
    if ( $first eq ".data" ) {
328
	HandleDataSect( @arr_line );
329
	goto restart;
330
    }
331
 
332
    if ( $first eq ".bss" ) {
333
	HandleBssSect( @arr_line );
334
	goto restart;
335
    }
336
 
337
    if ( $first =~ /^\./ ) {
338
	print "$first";
339
	print " $rest" if defined $rest;
340
	goto print_end;
341
    }
342
 
343
    if ( defined $second ) {
344
	# Handle segments
345
	if ( lc $second eq "segment" ) {
346
	    HandleSegment( @arr_line );
347
	    goto print_end;
348
	}
349
 
350
	# Handle EQU
351
	if ( lc $second eq "equ" ) {
352
	    $EquList{ $first } = Enumerate($arr_line[2]);
353
	    print ".equ $first, ", Enumerate($arr_line[2]), "\t";
354
	    goto print_end;
355
	}
356
 
357
	# Handle PROC
358
	if ( lc $second eq "proc" ) {
359
	    $indent = "    ";
360
	    HandleProc( @arr_line );
361
	    goto restart;
362
	}
363
 
364
	# Handle ENDP (for indentation, clearing status, etc.):
365
	if ( lc $second eq "endp" ) {
366
	    HandleENDP( $first );
367
	    $indent = "";
368
	    goto print_end;
369
	}
370
 
371
	# Handle LABEL
372
	if ( lc $second eq "label" ) {
373
	    $first = "$us$first" if ( $body =~ /\s+C($|[\s,]+)/ );
374
	    print "$first:";
375
	    $indent = "    ";
376
	    goto print_end;
377
	}
378
 
379
    }
380
 
381
    # Handle asm instructions:
382
    HandleAsmInst( $body );
383
 
384
print_end:
385
    print "$white" if defined $white;
386
    print "#$comment" if defined $comment;
387
    print "\n";
388
 
389
}
390
 
391
PrintHash( %FuncArgsRef ) if $DEBUG;
392
 
393
sub CanonizeAndComment {
394
    my ( $fw );
395
 
396
    # Do canonization:
397
    $_ =~ s/^(\s*)//o;
398
    ($fw) = ( $1 );
399
    $_ =~ s/[\s]*$//o;
400
 
401
    $_ =~ /(\s*);(.*)$/o;
402
    ($body, $white, $comment) = ($`, $1, $2);
403
 
404
    $white = $fw if ( (defined $body) && ($body eq "") &&
405
		      (defined $comment) && ($comment ne "") );
406
 
407
    @arr_line = split( /\s+/, $body);
408
    ($first, $second) = ($arr_line[0], $arr_line[1]);
409
    ($rest) = ($body =~ /\S+\s+(.*)/o); # rest is all body except for $first
410
}
411
 
412
sub GetLabelType {
413
    my ( $arg, $atype, $ltype );
414
 
415
    while( @_ ) {
416
	$arg = shift @_;
417
	$atype = $DAllocTypes{ lc($arg) };
418
	$ltype = $LabelTypeToInst{ $atype } if defined($atype);
419
	return $ltype if defined($ltype);
420
    }
421
 
422
    return "l";
423
}
424
 
425
sub AddPrefixDot {
426
    my ( $x, $y, $ret ) = @_;
427
 
428
    $ret = "." . $x;
429
    if ( (defined $y) && ($y ne "") ) {
430
	$ret = $ret . " " . $y;
431
    }
432
    return $ret;
433
}
434
 
435
sub HandleInclude {
436
    my ( $x, $y ) = @_;
437
 
438
    PrintHash( %_ );
439
    ($y) =~ /^\S+/;
440
    return ".include " . qq( "$&" ) . $';
441
}
442
 
443
sub IgnoreLine {
444
    return "";
445
}
446
 
447
sub SetTextSect {
448
    return ".text\n.p2align 2";
449
}
450
 
451
sub HandleDataSect {
452
    my ( $ret, $dalign ) = ( ".data", "" );
453
 
454
    while ( ($_ = <>) !~ /^\./ ) {
455
	$ret = "$ret$white" if defined $white;
456
	$ret = "$ret#$comment" if defined $comment;
457
	$ret = "$ret\n";
458
	CanonizeAndComment();
459
	if ( defined($second) && defined($DAllocTypes{ lc $second }) ) {
460
	    $dtype = $DAllocTypes{ lc $second };
461
	    $dalign = $DAllocAlignTypes{ $dtype };
462
	    $ret = "$ret\n.globl $us$first\n.p2align $dalign\n";
463
	    $ret = "$ret\n$us$first:\n\t$dtype";
464
	    $body =~ s/\s*\S+\s+\S+\s*//;
465
	    $body =~ s/\s//og;
466
	    while ( $body ne "" ) {
467
		$body =~ s/^([^,]+),?//;
468
		$ret = "$ret " . Enumerate($1) . ",";
469
	    }
470
	    $ret =~ s/,$//;
471
	}
472
	elsif ( defined($first) ) {
473
	    if ( (lc($first) eq "extrn") ||
474
		 (lc($first) eq "extern") || (lc($first) eq "externdef") ) {
475
		$ret = $ret . HandleExtern( lc($first), $rest );
476
	    }
477
	}
478
    }
479
 
480
    $ret = "$ret$white" if defined $white;
481
    $ret = "$ret#$comment" if defined $comment;
482
    $ret = "$ret\n";
483
 
484
    print "$ret"."\n";
485
}
486
 
487
sub HandleSegment {
488
    my ( $ret, $FuncComment, $segarg, $align, $def ) = ( "", "" );
489
 
490
    $sname = shift @_; # get section name
491
    $ret = ".section $sname, \"a\"";
492
    shift @_; # discard word `section'
493
    $segarg = shift @_;
494
    if ( defined($segarg) ) {
495
	print "segarg3: $segarg\n" if $DEBUG;
496
	$align = $SegAlignTypes{ lc $segarg };
497
	if ( defined($align) ) {
498
	    $segarg = shift @_;
499
	    goto sect_arg_end unless defined($segarg);
500
	}
501
	else {
502
	    $align = "2" unless defined($align);
503
	}
504
 
505
	print "segarg4: $segarg\n" if $DEBUG;
506
	if ( lc($segarg) eq "readonly" ) {
507
	    $ret = "$ret, \"r\"";
508
	    $segarg = shift @_;
509
	    goto sect_arg_end unless defined($segarg);
510
	}
511
 
512
	print "segarg5: $segarg\n" if $DEBUG;
513
	$def = $SegCombineTypes{ lc($segarg) };
514
	if ( defined($def) ) {
515
	    $segarg = shift @_;
516
	    goto sect_arg_end unless defined($segarg);
517
	}
518
 
519
	print "segarg6: $segarg\n" if $DEBUG;
520
	if ( defined( $SegUseTypes{ lc($segarg) } ) ) {
521
	    $segarg = shift @_;
522
	    goto sect_arg_end unless defined($segarg);
523
	}
524
 
525
	print "segarg7: $segarg\n" if $DEBUG;
526
	if ( lc($segarg) =~ /\'(code|data)\'/ ) {
527
	    if ( $1 eq "code" ) {
528
		$ret = ".text\n$ret";
529
	    }
530
	    else {
531
		$ret = ".data\n$ret";
532
	    }
533
	}
534
    }
535
 
536
sect_arg_end:
537
    print "ret=$ret\nalign=$align\ndef=$def\n" if $DEBUG;
538
    $ret = "$ret\n";
539
 
540
    while ( lc($_ = <>) !~ /ends/ ) {
541
	$ret = "$ret$white" if defined $white;
542
	$ret = "$ret#$comment" if defined $comment;
543
	$ret = "$ret\n";
544
	CanonizeAndComment();
545
refind_label:
546
	if ( (defined($first) && ($first =~ /:$/)) ||
547
	     (defined($second) &&
548
	      ( (lc($second) eq "label") ||
549
		defined($DAllocTypes{lc($second)}) )) ) {
550
	    $lname = "";
551
	    $addnl = 0;
552
	    if ( defined($first) && ($first =~ /:$/) ) {
553
		$lname = $`;
554
		$body = $first = "";
555
		$ltype = "l";
556
	    }
557
	    elsif ( lc($second) eq "label" ) {
558
		$ltype = GetLabelType( @arr_line );
559
		if ( $body =~ /\s+C($|[\s,])/ ) {
560
		    $lname = "$us";
561
		    $ltype = $ltype . "C";
562
		}
563
		$lname = "$lname$first";
564
		$body = $first = "";
565
	    }
566
	    else {
567
		$lname = "$first";
568
		$ltype = $LabelTypeToInst{ $DAllocTypes{lc($second)} };
569
		$body =~ s/\s*\S+\s+(\S+)/$1/;
570
		$first = $1;
571
		$addnl = 1;
572
	    }
573
	    $LabelTypes{ $lname } = $ltype;
574
 
575
	    $ret = "$ret$def $lname\n" if ( defined($def) && ($def ne "") );
576
	    $ret = "$ret.p2align $align\n$lname:";
577
	    $ret = "$ret\n" if $addnl;
578
 
579
	    undef $dtype;
580
	    $dtype = $DAllocTypes{ lc $first } if ( defined($first) );
581
	    do {
582
		if ( defined($dtype) ) {
583
		    $ret = "$ret$dtype ";
584
		    $body =~ s/\S+\s+//;
585
		    $body =~ s/\s//og;
586
		    while ( ($body =~ s/^([^,]+),?//) ne "" ) {
587
			$ret = $ret . Enumerate($1) . ", ";
588
		    }
589
		    $ret =~ s/\s*,\s*$//;
590
		}
591
		$ret = "$ret$white" if defined $white;
592
		$ret = "$ret#$comment" if defined $comment;
593
		$ret = "$ret\n";
594
		$_ = <>;
595
		CanonizeAndComment() if defined($_);
596
		undef $dtype;
597
		$dtype = $DAllocTypes{ lc $first } if ( defined($first) );
598
	    }
599
	    while ( defined($_) && (($body eq "") || defined($dtype)) );
600
 
601
	    last if ( $body =~ /ends/ );
602
	    goto refind_label;
603
	}
604
	if ( $body ne "" ) {
605
	    $ret = "$ret$body";
606
	    print STDERR "Warning: not data decl inside section, line $.\n";
607
	}
608
    }
609
 
610
    if ( $first ne $sname ) {
611
	print STDERR "Warning: on line $., sement $sname ends, not $first!\n";
612
    }
613
 
614
    print "$ret"."\n";
615
}
616
 
617
sub HandleBssSect {
618
}
619
 
620
sub HandleExtern {
621
    my ( $x, $y, $name ) = @_;
622
 
623
    ($y) =~ /\s*([^:\s]*):(\S+)/;
624
#    $ltype = $DAllocTypes{lc($2)} if defined($2);
625
#    $ltype = $LabelTypeToInst{ $ltype } if defined($ltype);
626
    $name = $1;
627
    if ( $body =~ /\s+C($|[\s,])/ ) {
628
	$name = "$us$name";
629
#	$ltype = $ltype . "C" if defined($ltype);
630
    }
631
#    $LabelTypes{ $name } = $ltype if defined($ltype);
632
    return ".extern $name";
633
}
634
 
635
sub HandlePublic {
636
    my ( $name );
637
 
638
    $body =~ /\S+\s+(C?)\s+(\S+)/;
639
    $name = $2;
640
    if ( $1 eq "C" ) {
641
	$name = "$us$name";
642
    }
643
    return ".globl $name";
644
}
645
 
646
sub HandleOption {
647
    my ( $x, $y ) = @_;
648
 
649
    if ( $y eq "PROLOGUE:NONE" ) {
650
	$prologue = 0;
651
	print STDERR "Not creating function prologue from input line $.\n"
652
	    if $DEBUG;
653
    }
654
    elsif ( $y eq "EPILOGUE:NONE" ) {
655
	$epilogue = 0;
656
	print STDERR "Not creating function epilogue from input line $.\n"
657
	    if $DEBUG;
658
    }
659
 
660
    return "";
661
}
662
 
663
sub Enumerate {
664
    my ( $num ) = @_;
665
 
666
    if ( $num =~ /^([+\-]?)([0-9a-fA-F]+)h$/ ) {
667
	return "$1"."0x$2";
668
    }
669
 
670
#    if ( $num =~ /^([0-9]+)$/ ) {
671
	return $num;
672
#    }
673
}
674
 
675
sub HandleProc {
676
    my ( @line ) = @_;
677
    my ( $found, $FuncComment );
678
 
679
    $FuncComment = "";
680
    if ( $body =~ /\s+C($|[\s,]+)/ ) {
681
	print STDERR "C funcion!\n" if $DEBUG;
682
	$FuncName = "$us" ;
683
	$FuncType = "C";
684
    }
685
    $FuncName = "$FuncName$line[0]";
686
    $LabelTypes{ $FuncName } = "l$FuncType";
687
 
688
    for ( $i = 0; $i <= $#line; $i++ ) {
689
	if ( lc $line[$i] eq "uses" ) {
690
	    for ( $i++; $i <= $#line; $i++ ) {
691
		$found = $line[$i] =~ /e?([abcd]x|[sd]i|[sb]p)/io;
692
		if ( $found ) {
693
		     push( @UsedRegs, lc $& );
694
		}
695
		else {
696
		    print STDERR "Warning: unknown or invalid register ";
697
		    print STDERR "`$line[$i]\' on line $.\n";
698
		}
699
	    }
700
	}
701
    }
702
 
703
    while ( ($_ = <>) =~ /:/ ) {
704
	if ( (defined $comment) && ($comment ne "") ) {
705
	    $FuncComment = $FuncComment . "\n#$comment";
706
	}
707
	CanonizeAndComment();
708
	push @FuncArgs, ($body =~ /(\S+)\s*:\s*([^,\n]*)/og);
709
    }
710
    if ( (defined $comment) && ($comment ne "") ) {
711
	$FuncComment = $FuncComment . "\n#$comment";
712
    }
713
 
714
    if ( $FuncType ne "C" ) {
715
	$old_prologue = $prologue;
716
	$old_epilogue = $epilogue;
717
	$prologue = $epilogue = 0;
718
	while ( $#FuncArgs >= 0 ) { pop @FuncArgs };
719
	while ( $#UsedRegs >= 0 ) { pop @UsedRegs };
720
    }
721
 
722
    if ( (! $prologue) && ($#FuncArgs >= 0) ) {
723
	print STDERR "Warning: Function `$FuncName\' has arguments,\n".
724
	    "         but `OPTION PROLOGUE:NONE\' is set! args ignored.\n";
725
	while ( $#FuncArgs >= 0 ) { pop @FuncArgs };
726
    }
727
 
728
    if ( ($#UsedRegs >= 0) && (! ($prologue || $epilogue) ) ) {
729
	print STDERR "Warning: Function `$FuncName\' declares used ".
730
	    "registers,\n         but no EPILOGUE and no PROLOGUE ",
731
	    "requeted.\n         Regs will not be saved or restored!\n";
732
	while ( $#UsedRegs >= 0 ) { pop @UsedRegs };
733
    }
734
 
735
    print $FuncComment, "\n" unless ($FuncComment eq "");
736
 
737
    if ( $prologue ) {
738
	ProcessPrintFuncArgs() if ($#FuncArgs > -1);
739
	print ".globl $FuncName\n\n$FuncName:\n";
740
	PrintFuncFrame( "enter" );
741
	ProcessUsedRegs( "enter" ) if ($#UsedRegs > -1);
742
    }
743
    else {
744
	print ".globl $FuncName\n\n$FuncName:\n";
745
    }
746
 
747
}
748
 
749
sub ProcessPrintFuncArgs {
750
    my ( $offset, $i, $type, $offs_name, $arg_type, $maxlen );
751
 
752
    $offset = 8;
753
    print "\n";
754
 
755
    $maxlen = 0;
756
    for ( $i = 0; $i <= $#FuncArgs-1; $i += 2 ) {
757
	$maxlen = length($FuncArgs[$i]) if ( length($FuncArgs[$i]) > $maxlen );
758
    }
759
 
760
    for ( $i = 0; $i <= $#FuncArgs-1; $i += 2 ) {
761
	$offs_name = "PRM_" . uc $FuncArgs[$i];
762
	$arg_type = $FuncArgs[$i+1];
763
	if ( lc($arg_type) =~ /^ptr\s*/ ) {
764
	    ($type) = ($' =~ /\s*(\S*)\s*/);
765
#	    print STDERR "Warning: Function `$FuncName\'s argument ".
766
#		"`$FuncArgs[$i]\'s size is not 4!\n";
767
	}
768
	else {
769
	    $type = $arg_type;
770
	}
771
	print ".equ $offs_name, $offset";
772
	printf "%*s", $maxlen - length($offs_name) + 8 - length($offset), "";
773
	print "# ", uc $type, "\t$FuncArgs[$i]";
774
	if ( lc($arg_type) =~ /^ptr\s*/ ) {
775
	    printf "%*spointer", $maxlen - length($offs_name) + 5;
776
	}
777
	print "\n";
778
	$offset += 4;
779
	$FuncArgsRef{ $FuncArgs[$i] } = "$offs_name(%ebp)";
780
    }
781
 
782
    print "\n";
783
 
784
#    PrintHash( %FuncArgsRef ) if $DEBUG;
785
}
786
 
787
sub PrintFuncFrame {
788
 
789
    print "\n";
790
    if ( $_[0] eq "enter" ) {
791
	print $indent, "pushl	%ebp\n";
792
	print $indent, "movl	%esp, %ebp\n";
793
    }
794
    else {
795
	print $indent, "movl	%ebp, %esp\n";
796
	print $indent, "popl	%ebp\n";
797
    }
798
}
799
 
800
sub ProcessUsedRegs {
801
    my ( $i, $type );
802
 
803
    print "\n";
804
    if ( $_[0] eq "enter" ) {
805
	for ( $i = 0; $i <= $#UsedRegs; $i++ ) {
806
	    $type = $UsedRegTypes{ $UsedRegs[$i] };
807
	    if ( $type eq "w" ) {
808
		print STDERR "Warning: function `$FuncName\' saves a 16-bit ".
809
		    "register ($UsedRegs[$i]).\n";
810
	    }
811
	    print "$indent", "push$type\t%$UsedRegs[$i]\n";
812
	}
813
    }
814
    else {
815
	for ( $i = $#UsedRegs; $i >= 0 ; $i-- ) {
816
	    $type = $UsedRegTypes{ $UsedRegs[$i] };
817
	    print "$indent", "pop$type\t%$UsedRegs[$i]\n";
818
	}
819
    }
820
}
821
 
822
sub HandleRet {
823
 
824
    ProcessUsedRegs( "leave" ) if ($#UsedRegs > -1);
825
    PrintFuncFrame( "leave" );
826
    print "\n";
827
}
828
 
829
sub HandleENDP {
830
    my ( $fname ) = @_;
831
 
832
    $fname = "$us$fname" if ( $FuncType eq "C" );
833
    unless ( $fname eq $FuncName ) {
834
	print STDERR "Warning: on line $. `$fname\' ends, inside $FuncName!\n";
835
    }
836
 
837
    if ( $FuncType ne "C" ) {
838
	$prologue = $old_prologue;
839
	$epilogue = $old_epilogue;
840
    }
841
    $FuncName = $FuncType = "";
842
 
843
    while ( $#FuncArgs >= 0 ) { pop @FuncArgs };
844
    while ( $#FuncArgsRef >= 0 ) { pop @FuncArgsRef };
845
    while ( $#UsedRegs >= 0 ) { pop @UsedRegs };
846
 
847
    print "\n# $fname ends here.\n\n";
848
 
849
    if ( $prologue ^ $epilogue ) {
850
	print STDERR "Warning: only one of PROLUGE and EPILOGUE is defined.\n".
851
	    "         Make sure prologue and epilogue are consistent!\n";
852
    }
853
}
854
 
855
sub ParseIndexRef {
856
    my ( $ireg, $idx ) = @_;
857
 
858
    if ( defined $RegisterList{ $ireg } ) {
859
	$ireg = "%".$ireg;
860
    }
861
    else {
862
	print STDERR "Error: in instruction on line $.: ".
863
	    "register `$ireg' unknown!\n";
864
	exit -1;
865
    }
866
 
867
    print ",$ireg,$idx)\n" if $DEBUG;
868
 
869
    return ( $ireg, $idx );
870
}
871
 
872
sub ParseMemRef {
873
    my ( $ref ) = @_;
874
    my ( $dsign, $disp, $base_reg, $index_reg, $index ) =
875
	( "", "", "", "", "1" );
876
 
877
    $ref =~ s/\s*//og;
878
    print "$ref\n" if $DEBUG;
879
 
880
    $found = $ref =~ /([+\-]?)([01248])\*([^+\-*]+)/;
881
    if ( $found && defined($RegisterList{$3}) ) {
882
	print "found 1: $3\n" if $DEBUG;
883
	if ( defined($1) && ($1 eq "-") ) {
884
	    print STDERR "Error: negative register indexing on line $.!\n";
885
	    exit -3;
886
	}
887
	($index_reg, $index) = ParseIndexRef( lc $3, $2 ) unless( $2 eq "0");
888
	$ref =~ s/([+\-]?)([01248])\*([^+\-*]+)//;
889
    }
890
    else {
891
	$found = $ref =~ s/([+\-]?)([^+\-*]+)\*([01248])//;
892
	if ( $found ) {
893
	    if ( defined($RegisterList{$2}) ) {
894
		print "found 2: $2\n" if $DEBUG;
895
		if ( defined($1) && ($1 eq "-") ) {
896
		    print STDERR "Error: negative register indexing".
897
			" on line $.!\n";
898
		    exit -3;
899
		}
900
		($index_reg, $index) =
901
		    ParseIndexRef(lc $2, $3) unless( $3 eq "0");
902
	    }
903
	    else {
904
		$disp = $1 if defined($1);
905
		$disp = $disp . Enumerate($2) . "*" . Enumerate($3);
906
	    }
907
	}
908
    }
909
 
910
    $fn = 2;
911
    while ( $ref =~ s/([+\-]?)([^+\-*]+)\*([^+\-*]+)// ) {
912
#	print STDERR "Error: in instruction on line $.: too many `*'!\n";
913
#	exit -3;
914
	$fn++;
915
	print STDERR "found $fn"."*: $2*$3\n" if $DEBUG;
916
	$disp = "$disp$1" if defined($1);
917
	$disp = $disp . Enumerate($2) . "*" . Enumerate($3);
918
	print STDERR "$disp(\n" if $DEBUG;
919
    }
920
 
921
    while ( $ref =~ s/((^|[+\-])[0-9][0-9a-fA-F]*h?)// ) {
922
	$fn++;
923
	print STDERR "found $fn"."i: $1\n" if $DEBUG;
924
	$disp = $disp . Enumerate($1);
925
	print STDERR "$disp(\n" if $DEBUG;
926
    }
927
 
928
    while ( $ref =~ /[^+\-]/ ) {
929
	$fn++;
930
	$found = $ref =~ s/^([+\-]?)([^+\-]+)//;
931
	if ( $found ) {
932
	    print STDERR "found $fn"."g: $1$2\n" if $DEBUG;
933
	    if ( defined $RegisterList{ lc $2 } ) {
934
		if ( defined($1) && ($1 eq "-") ) {
935
		    print STDERR "negative register reference on line $.!\n";
936
		    exit -4;
937
		}
938
		if ( $base_reg ne "" ) {
939
		    if ( $index_reg ne "" ) {
940
			print STDERR "Error: in instruction on line $.: ".
941
			    "base_reg & index_reg already defined!\n";
942
			exit -4;
943
		    }
944
		    ($index_reg, $index) = ParseIndexRef( lc $2, "1" );
945
		}
946
		else {
947
		    $base_reg = "%".lc($2);
948
		    print STDERR "($base_reg,\n" if $DEBUG;
949
		}
950
	    }
951
	    else {
952
		$cdisp = $2;
953
		$cdisp = "$1$cdisp" if defined($1);
954
		my( $lbt );
955
		if ( defined($lbt = $LabelTypes{ "$us$cdisp" }) &&
956
		     $lbt =~ /C$/ ) {
957
		    $cdisp = "$us$cdisp";
958
		}
959
		$dsign = "+" if ( ($disp ne "") && ($disp !~ /^[+\-]/ ) );
960
		$disp = "$cdisp$dsign$disp";
961
		print STDERR "$disp(\n" if $DEBUG;
962
	    }
963
	}
964
    }
965
 
966
    if ( $ref ne "" ) {
967
	print STDERR "Error: Not all memory reference parsed! (Rest=$ref)\n";
968
	exit -6;
969
    }
970
 
971
    $memref = "$disp($base_reg,$index_reg,$index)";
972
    print "$memref\n" if $DEBUG;
973
    $memref =~ s/\(([^,]+),,1\)/($1)/;
974
    print "$memref\n" if $DEBUG;
975
    $memref =~ s/,,/,/;
976
    print "$memref\n" if $DEBUG;
977
    $memref =~ s/\(,1\)//;
978
    print "$memref\n" if $DEBUG;
979
    $memref =~ s/^\+//;
980
    print "$memref\n" if $DEBUG;
981
    return $memref;
982
}
983
 
984
sub HandleSrcDstType {
985
    my ( $sd, $ref_type, $mem_ref, $sd_type, $lbt, $num, $tmp, $s, $m ) = @_;
986
 
987
    if ( defined $sd ) {
988
	$sd_type = $RegisterList{ $sd };
989
	unless ( defined $sd_type ) {
990
	    ($ref_type, $mem_ref) = ($sd =~ /([^\[]*)\[([^\]\n\r]+)\]$/);
991
	    if ( !defined($mem_ref) ) { # maybe [] was missing:
992
		($ref_type, $mem_ref)= ($sd =~ /(\S*\s*[pP][tT][rR])\s*(.+)$/);
993
	    }
994
	    if ( defined $mem_ref ) {
995
		($sd_type) = (lc($ref_type) =~ /^(\S+)/);
996
		$sd_type = "dword" if ( ! defined($sd_type) );
997
		($sd_type) = $MemoryTypes{ $sd_type };
998
		print "mem ref: [$mem_ref] ($sd_type)\n" if $DEBUG;
999
		if ( defined $FuncArgsRef{ $mem_ref } ) {
1000
		    $sd = $FuncArgsRef{ $mem_ref };
1001
		    print "matched in arg-list: $sd\n" if $DEBUG;
1002
		}
1003
		else {
1004
		    $sd = ParseMemRef( $mem_ref );
1005
		}
1006
	    }
1007
	    else {
1008
		print "constant: $sd " if $DEBUG;
1009
		if ( defined $FuncArgsRef{ $sd } ) {
1010
		    $sd = $FuncArgsRef{ $sd };
1011
		    print "matched in arg-list: $sd\n" if $DEBUG;
1012
		}
1013
		else {
1014
		    $tmp = $sd;
1015
		    $sd = "";
1016
		    while( $tmp ne "" ) {
1017
			$tmp =~ s/^\s*([+\-]?[^\s+\-]+)\s*([+\-]?)/$2/;
1018
  			print "const=$tmp,match=$1" if $DEBUG;
1019
			$1 =~ /[^+\-]+/;
1020
			$s = $`;
1021
			$m = $&;
1022
			print ",net=$m\n" if $DEBUG;
1023
			if ( ( defined($lbt = $LabelTypes{ "$us$m" }) &&
1024
			       $lbt =~ s/C$// ) ||
1025
			     defined($lbt = $LabelTypes{ $m }) ) {
1026
			    if ( defined( $sd_type ) ) {
1027
				print STDERR "Warning: 2 labels on line $.!\n";
1028
			    }
1029
			    $m = "$us$m" if ( $& eq "C" );
1030
			    $sd = "$sd$s$m";
1031
			    $sd_type = $lbt;
1032
			    print"#label `($s)$m',type `$sd_type'\n" if $DEBUG;
1033
			}
1034
			elsif ( defined($EquList{ $m }) ) {
1035
			    $sd = "$sd$s$m";
1036
			    print "found equ `($s)$m'\n" if $DEBUG;
1037
			}
1038
			else {
1039
			    $sd = "$sd$s" . Enumerate( $m );
1040
			    print "found const `$s$m'\n" if $DEBUG;
1041
			}
1042
		    }
1043
		    $sd =~ s/^\+//;
1044
		    $sd = "\$$sd" unless ( defined($sd_type ) );
1045
		}
1046
		print "($sd_type)" if ( $DEBUG && defined($sd_type) );
1047
		print "\n" if $DEBUG;
1048
	    }
1049
	}
1050
	else {
1051
	    print "reg ref: $sd ($sd_type)\n" if $DEBUG;
1052
	    $sd = "%" . $sd;
1053
	}
1054
    }
1055
 
1056
    return ( $sd, $sd_type );
1057
}
1058
 
1059
sub HandleAsmInst {
1060
    my ( $inst ) = @_;
1061
    my ( $opcode, $dst, $src, $extra, $src_type, $dst_type, $mem_ref );
1062
 
1063
    ($opcode) = ($inst =~ /^(\S+)\s*/);
1064
    $opcode = lc $opcode;
1065
    ($dst) = ($' =~ /^([^,\n\r]+)\s*,?\s*/);
1066
    ($src) = ($' =~ /^([^,\n\r]+)\s*,?\s*/) if defined $dst;
1067
    ($extra) = ($' =~ /^([^,\n\r]+)\s*,?\s*/) if defined $src;
1068
 
1069
    ($src, $src_type) = HandleSrcDstType( $src ) if defined $src;
1070
    ($dst, $dst_type) = HandleSrcDstType( $dst ) if defined $dst;
1071
 
1072
    $print_adj = 0;
1073
    if ( $opcode =~ /^f(.)/ ) { # Handle float commands:
1074
	if ( $1 ne "i" ) { # Handle commands without integer:
1075
	    $src_type = $IntToFloatType{ $src_type } if defined($src_type);
1076
	    $dst_type = $IntToFloatType{ $dst_type } if defined($dst_type);
1077
	}
1078
	else { # Handle commands with integer: put `' instead of `w'.
1079
#	    $src_type = "" if ( defined($src_type) && ($src_type eq "w") );
1080
#	    $dst_type = "" if ( defined($dst_type) && ($dst_type eq "w") );
1081
	}
1082
    }
1083
    else {
1084
	# Adjust mmx-instructions:
1085
	if ( #($opcode eq "movd") &&
1086
	     ( (defined $src_type) && (defined $dst_type) ) &&
1087
	     ( (($src_type eq "l") && ($dst_type eq "q")) ||
1088
	       (($src_type eq "q") && ($dst_type eq "l")) ) ) {
1089
	    $print_adj = 1 if $warn_fixed;
1090
	    $dst_type = $src_type = "q";
1091
	}
1092
	# if src or dst_type is `q' (for mmx), no need to put it
1093
	$dst_type = "" if ( defined($dst_type) && ($dst_type eq "q") );
1094
	$src_type = "" if ( defined($src_type) && ($src_type eq "q") );
1095
    }
1096
 
1097
    if ( (defined $src_type) && (defined $dst_type) &&
1098
	 ($src_type ne $dst_type) ) {
1099
	print STDERR "Warning: instruction on line $. has different ".
1100
	    "SRC ($src_type) and DST ($dst_type) types!\n";
1101
    }
1102
    $dst_type = $src_type if ( defined($src_type) && (!defined($dst_type)) );
1103
 
1104
    $cmd = $indent . "$opcode";
1105
    $cmd = $cmd . $dst_type if defined($dst_type);
1106
    $cmd = $cmd . "  ";
1107
    $cmd = $cmd . "\t" if defined $dst;
1108
    $cmd = $cmd . $src . ", " if defined $src;
1109
    $cmd = $cmd . "$dst" if defined $dst;
1110
    $cmd = $cmd . ", $extra" if defined $extra;
1111
 
1112
    print $cmd;
1113
 
1114
    $cmd =~ s/^\s*//;
1115
    print STDERR "Fixed types for `$cmd' (this is OK).\n" if $print_adj;
1116
 
1117
}