#!/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);
