#!/usr/bin/perl -w

#
# fixpic -- Take an assembler source generated by m68k-linux/cc1 (gcc 2.7.0/ELF)
#	    with the `-fPIC' option and convert it to a real position
#	    independent (PC-relative) assembler source.
#
# Caveats:  This doesn't catch pointers that are initialized at compile time,
#	    like e.g.
#
#		u_char *ptr = "text";
#
#	    in the data part of your C-code. As a workaround you must
#	    explicitly initialize `ptr' at run time.
#
#  Copyright 1995 by Geert Uytterhoeven (Geert.Uytterhoeven@cs.kuleuven.ac.be)
#
# This file is subject to the terms and conditions of the GNU General Public
# License.  See the file README.legal in the main directory of the Linux/m68k
# distribution for more details.
#

die("Usage: fixpic infile\n") unless $#ARGV == 0;

$inname = $ARGV[0];
$outname = $inname;
$outname =~ s/\.s$/.pic.s/;

open(IN, "<$inname") || die("Can't open $inname for reading, stopped");
open(OUT, ">$outname") || die("Can't open $outname for writing, stopped");

print OUT <<EOF;
|
|   This file was generated from `$inname' by `fixpic'. Do not edit!!
|

EOF

while ($line = <IN>) {
    if ($line =~ /_GLOBAL_OFFSET_TABLE_\@GOTPC/) {
	# deleting line
    } elsif ($line =~ s/\@GOT\(%a5\)/\(%pc\)/g) {
	if (($opc, $src, $dst) = ($line =~ /[ \t]([^\s]+) ([^\s]+),([^\s]+)/)) {
	    if (($opc eq "move.l") && ($dst =~ /^%a\d$/)) {
		# move to address reg -> lea
		print OUT "\tlea $src,$dst\n";
	    } elsif (($opc eq "move.l") && ($dst eq "-(%sp)")) {
		# push to stack -> pea
		print OUT "\tpea $src\n";
	    } else {
		# other -> pea/$opc
		print OUT "\tpea $src\n";
		print OUT "\t$opc (%sp)+,$dst\n";
	    }
	} else {
	    close(OUT);
	    unlink($outname);
	    die("Unknown case, stopped");
	}
    } else {
	$line =~ s/\@PLTPC//;
	$line =~ s/[ \t]bsr.l/\tjbsr/;
	print OUT "$line";
    }
}

close(OUT);
close(IN);
