Home | History | Annotate | Line # | Download | only in bfd
mep-relocs.pl revision 1.1.1.7.2.1
      1          1.1  christos #!/usr/bin/perl
      2          1.1  christos # -*- perl -*-
      3          1.1  christos #
      4          1.1  christos # Toshiba MeP Media Engine Relocation Generator
      5  1.1.1.7.2.1  perseant # Copyright (C) 2001-2024 Free Software Foundation, Inc.
      6          1.1  christos # This file is part of BFD.
      7          1.1  christos # Originally written by DJ Delorie <dj (at] redhat.com>
      8          1.1  christos #
      9          1.1  christos # This program is free software; you can redistribute it and/or modify
     10          1.1  christos # it under the terms of the GNU General Public License as published by
     11          1.1  christos # the Free Software Foundation; either version 3 of the License, or
     12          1.1  christos # (at your option) any later version.
     13      1.1.1.3  christos #
     14          1.1  christos # This program is distributed in the hope that it will be useful,
     15          1.1  christos # but WITHOUT ANY WARRANTY; without even the implied warranty of
     16          1.1  christos # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     17          1.1  christos # GNU General Public License for more details.
     18      1.1.1.3  christos #
     19          1.1  christos # You should have received a copy of the GNU General Public License
     20          1.1  christos # along with this program; if not, write to the Free Software
     21          1.1  christos # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
     22          1.1  christos # MA 02110-1301, USA.
     23          1.1  christos 
     24          1.1  christos 
     25          1.1  christos # Usage: Run this anywhere inside your source tree.  It will read
     26          1.1  christos # include/elf/mep.h and scan the comments therein.  It will renumber
     27          1.1  christos # the relocs to be sequential (this is needed so that bfd/elf32-mep.h
     28          1.1  christos # works) if needed.  It will then update the reloc list in bfd/reloc.c
     29          1.1  christos # and the howto, mapping, and apply routines in bfd/elf32-mep.c.  You
     30          1.1  christos # can then regenerate bfd-in2.h and check everything in.
     31          1.1  christos 
     32          1.1  christos # FIXME: After the relocation list is finalized, change this to
     33          1.1  christos # *verify* the reloc list, rather than resequence it.
     34          1.1  christos 
     35          1.1  christos while (! -f "include/elf/mep.h" && ! -f "bfd/reloc.c") {
     36          1.1  christos     chdir "..";
     37          1.1  christos     $pwd = `pwd`;
     38          1.1  christos     if ($pwd !~ m@/.*/@) {
     39          1.1  christos 	print STDERR "Cannot find include/elf/mep.h or bfd/reloc.h\n";
     40          1.1  christos 	exit 1;
     41          1.1  christos     }
     42          1.1  christos }
     43          1.1  christos $pwd = `pwd`;
     44          1.1  christos print "srctop is $pwd";
     45          1.1  christos 
     46          1.1  christos printf "Reading include/elf/mep.h ...\n";
     47          1.1  christos open(MEPH, "include/elf/mep.h");
     48          1.1  christos open(MEPHO, "> include/elf/mep.h.new") || die("mep.h.new create: $!");
     49          1.1  christos $val = 0;
     50          1.1  christos while (<MEPH>) {
     51          1.1  christos     if (($pre,$rel,$rest) = /(.*RELOC_NUMBER \()([^,]+), *\d+(.*)/) {
     52          1.1  christos 	$rest =~ s/[\r\n]+$//;
     53          1.1  christos 	print (MEPHO "$pre$rel, $val$rest\n") || die("mep.h.new write: $!");
     54          1.1  christos 	$val ++;
     55          1.1  christos 	$rel =~ s/R_MEP_//;
     56          1.1  christos 	push(@relocs, $rel);
     57          1.1  christos 
     58          1.1  christos 	$rest =~ s@.*/\* @@;
     59          1.1  christos 	($pattern, $sign, $attrs) = $rest =~ m@(.*) ([US]) (.*)\*/@;
     60          1.1  christos 	$pattern =~ s/ //g;
     61          1.1  christos 	push(@pattern, $pattern);
     62          1.1  christos 	push(@sign, $sign);
     63          1.1  christos 	push(@attrs, $attrs);
     64          1.1  christos 
     65          1.1  christos 	printf "%4d $rel p=`$pattern' s=`$sign' a=`$attrs'\n", $#pattern;
     66          1.1  christos 
     67          1.1  christos     } else {
     68          1.1  christos 	print(MEPHO) || die("mep.h.new write: $!");
     69          1.1  christos     }
     70          1.1  christos }
     71          1.1  christos close(MEPH);
     72          1.1  christos close(MEPHO) || die("mep.h.new close: $!");
     73          1.1  christos 
     74          1.1  christos &swapfile("include/elf/mep.h");
     75          1.1  christos 
     76          1.1  christos redo_file ("bfd/reloc.c",
     77          1.1  christos 	   "",
     78          1.1  christos 	   "ENUMDOC\n  Toshiba Media Processor Relocations.\n\nCOMMENT\n",
     79          1.1  christos 	   "ENUM\n  BFD_RELOC_MEP_%s\n",
     80          1.1  christos 	   "");
     81          1.1  christos 
     82          1.1  christos $autogen = "    /* This section generated from bfd/mep-relocs.pl from include/elf/mep.h.  */\n";
     83          1.1  christos 
     84          1.1  christos redo_file ("bfd/elf32-mep.c",
     85          1.1  christos 	   "MEPRELOC:HOWTO",
     86          1.1  christos 	   $autogen,
     87          1.1  christos 	   "MEPRELOC:END",
     88          1.1  christos 	   "",
     89          1.1  christos 	   "&emit_howto();",
     90          1.1  christos 	   "MEPRELOC:MAP",
     91          1.1  christos 	   $autogen,
     92          1.1  christos 	   "MEPRELOC:END",
     93          1.1  christos 	   "",
     94          1.1  christos 	   "    MAP(%s);\n",
     95          1.1  christos 	   "MEPRELOC:APPLY",
     96          1.1  christos 	   $autogen,
     97          1.1  christos 	   "MEPRELOC:END",
     98          1.1  christos 	   "",
     99          1.1  christos 	   "&emit_apply();",
    100          1.1  christos 	   );
    101          1.1  christos 
    102          1.1  christos sub mask2shifts {
    103          1.1  christos     my ($mask) = @_;
    104          1.1  christos     my ($bits, $left, $right, $ci, $c, $cv);
    105          1.1  christos     $bits = 0;
    106          1.1  christos     $left = 0;
    107          1.1  christos     $right = 32;
    108          1.1  christos     for ($ci=0; $ci<length($mask); $ci++) {
    109          1.1  christos 	$c = substr($mask, $ci, 1);
    110          1.1  christos 	$left++;
    111          1.1  christos 	next if $c eq '-';
    112          1.1  christos 	$left = 0;
    113          1.1  christos 	$cv = ord($c) - ord('0');
    114          1.1  christos 	$cv -= ord('a') - ord('9') - 1 if $cv > 9;
    115          1.1  christos 	$right = $cv unless $right < $cv;
    116          1.1  christos 	$bits = $cv+1 unless $bits > $cv+1;
    117          1.1  christos     }
    118          1.1  christos     $mask =~ tr/-/1/c;
    119          1.1  christos     $mask =~ tr/-/0/;
    120          1.1  christos     ($rmask = $mask) =~ tr/01/10/;
    121          1.1  christos     $mask = unpack("H*", pack("B*", $mask));
    122          1.1  christos     $rmask = unpack("H*", pack("B*", $rmask));
    123          1.1  christos     return ($bits, $left, $right, $mask, $rmask);
    124          1.1  christos }
    125          1.1  christos 
    126          1.1  christos sub emit_howto {
    127          1.1  christos     for ($i=2; $i<=$#relocs; $i++) {
    128          1.1  christos 	$mask = $pattern[$i];
    129          1.1  christos 
    130          1.1  christos 	if (length($mask) == 8)     { $bytesize = 0; }
    131          1.1  christos 	elsif (length($mask) == 16) { $bytesize = 1; }
    132          1.1  christos 	elsif (length($mask) == 32) { $bytesize = 2; }
    133          1.1  christos 
    134          1.1  christos 	($bits, $left, $right, $mask) = mask2shifts ($mask);
    135          1.1  christos 	$bits[$i] = $bits;
    136          1.1  christos 	$pcrel = 0;
    137          1.1  christos 	$pcrel = 1 if $attrs[$i] =~ /pc-rel/i;
    138          1.1  christos 	$overflow = $sign[$i];
    139          1.1  christos 	$overflow = 'N' if $attrs[$i] =~ /no-overflow/;
    140          1.1  christos 
    141          1.1  christos 	$c = "$relocs[$i],";
    142          1.1  christos 	printf(NEW "  MEPREL (R_MEP_%-10s%d,%3d,%2d,%2d,%2d,%2s, 0x%s),\n",
    143          1.1  christos 	       $c, $bytesize, $bits, $left, $right, $pcrel, $overflow, $mask);
    144          1.1  christos     }
    145          1.1  christos }
    146          1.1  christos 
    147          1.1  christos sub emit_apply {
    148          1.1  christos     for ($i=2; $i<=$#relocs; $i++) {
    149          1.1  christos 	$v = "u";
    150          1.1  christos 	$v = "s" if $sign[$i] =~ /S/;
    151          1.1  christos 	if (length($pattern[$i]) == 8) {
    152          1.1  christos 	    $e = ''; # no endian swap for bytes
    153          1.1  christos 	} elsif ($pattern[$i] =~ /-/ || length($pattern[$i]) == 16) {
    154          1.1  christos 	    $e = '^e2'; # endian swap - 2byte words only
    155          1.1  christos 	} else {
    156          1.1  christos 	    $e = '^e4' # endian swap for data
    157          1.1  christos 	}
    158          1.1  christos 	print NEW "    case R_MEP_$relocs[$i]: /* $pattern[$i] */\n";
    159      1.1.1.6  christos 	if ($relocs[$i] =~ /HI16S/) {
    160      1.1.1.6  christos 	    print NEW "      u += 0x8000;\n"
    161      1.1.1.6  christos 	}
    162          1.1  christos 	if ($attrs[$i] =~ /tp-rel/i) {
    163      1.1.1.6  christos 	    print NEW "      u -= mep_tpoff_base(rel->r_offset);\n";
    164          1.1  christos 	}
    165          1.1  christos 	if ($attrs[$i] =~ /gp-rel/i) {
    166      1.1.1.6  christos 	    print NEW "      u -= mep_sdaoff_base(rel->r_offset);\n";
    167          1.1  christos 	}
    168          1.1  christos 	if ($attrs[$i] !~ /no-overflow/ && $bits[$i] < 32) {
    169          1.1  christos 	    if ($v eq "u") {
    170          1.1  christos 		$max = (1 << $bits[$i]) - 1;
    171          1.1  christos 		print NEW "      if (u > $max) r = bfd_reloc_overflow;\n";
    172          1.1  christos 	    } else {
    173      1.1.1.6  christos 		$min = (1 << ($bits[$i]-1));
    174      1.1.1.6  christos 		$max = (1 << ($bits[$i])) - 1;
    175      1.1.1.6  christos 		print NEW "      if (u + $min > $max) r = bfd_reloc_overflow;\n";
    176          1.1  christos 	    }
    177          1.1  christos 	}
    178          1.1  christos 	for ($b=0; $b<length($pattern[$i]); $b += 8) {
    179          1.1  christos 	    $mask = substr($pattern[$i], $b, 8);
    180          1.1  christos 	    ($bits, $left, $right, $mask, $rmask) = mask2shifts ($mask);
    181          1.1  christos 	    if ($left > $right) { $left -= $right; $right = 0; }
    182          1.1  christos 	    else { $right -= $left; $left = 0; }
    183          1.1  christos 
    184          1.1  christos 	    if ($mask ne "00") {
    185          1.1  christos 		$bb = $b / 8;
    186          1.1  christos 		print NEW "      byte[$bb$e] = ";
    187          1.1  christos 		print NEW "(byte[$bb$e] & 0x$rmask) | " if $rmask ne "00";
    188          1.1  christos 		if ($left) {
    189      1.1.1.6  christos 		    print NEW "((u << $left) & 0x$mask)";
    190          1.1  christos 		} elsif ($right) {
    191      1.1.1.6  christos 		    print NEW "((u >> $right) & 0x$mask)";
    192          1.1  christos 		} else {
    193      1.1.1.6  christos 		    print NEW "(u & 0x$mask)";
    194          1.1  christos 		}
    195          1.1  christos 		print NEW ";\n";
    196          1.1  christos 	    }
    197          1.1  christos 	}
    198          1.1  christos 	print NEW "      break;\n";
    199          1.1  christos     }
    200          1.1  christos }
    201          1.1  christos 
    202          1.1  christos 
    203          1.1  christos #-----------------------------------------------------------------------------
    204          1.1  christos 
    205          1.1  christos sub redo_file {
    206          1.1  christos     my ($file, @control) = @_;
    207          1.1  christos     open(OLD, $file);
    208          1.1  christos     open(NEW, "> $file.new") || die("$file.new create: $!");
    209          1.1  christos 
    210          1.1  christos     print "Scanning file $file ...\n";
    211          1.1  christos 
    212          1.1  christos     while (1) {
    213          1.1  christos 	$start = shift @control;
    214          1.1  christos 	$prefix = shift @control;
    215          1.1  christos 	$end = shift @control;
    216          1.1  christos 	$suffix = shift @control;
    217          1.1  christos 	$pattern = shift @control;
    218          1.1  christos 
    219          1.1  christos 	if (!$start) {
    220          1.1  christos 	    print NEW while <OLD>;
    221          1.1  christos 	    last;
    222          1.1  christos 	}
    223          1.1  christos 
    224          1.1  christos 	print "  looking for $start\n";
    225          1.1  christos 	while (<OLD>) {
    226          1.1  christos 	    print NEW;
    227          1.1  christos 	    last if /\Q$start\E/;
    228          1.1  christos 	}
    229          1.1  christos 	print "can't find $start\n" unless $_;
    230          1.1  christos 	last unless $_;
    231          1.1  christos 
    232          1.1  christos 	print NEW $prefix;
    233          1.1  christos 	if ($pattern =~ /^\&/) {
    234          1.1  christos 	    eval $pattern;
    235          1.1  christos 	    die("$pattern: $@") if $@;
    236          1.1  christos 	} else {
    237          1.1  christos 	    for $i (2..$#relocs) {
    238          1.1  christos 		printf (NEW "$pattern", $relocs[$i]) || die("$file.new write: $!");
    239          1.1  christos 		$pattern =~ s/^ENUM\n/ENUMX\n/;
    240          1.1  christos 	    }
    241          1.1  christos 	}
    242          1.1  christos 	print NEW $suffix;
    243          1.1  christos 	while (<OLD>) {
    244          1.1  christos 	    last if /\Q$end\E/;
    245          1.1  christos 	}
    246          1.1  christos 	print NEW;
    247          1.1  christos     }
    248          1.1  christos 
    249          1.1  christos     close(OLD);
    250          1.1  christos     close(NEW) || die("$file.new close: $!");
    251          1.1  christos     &swapfile($file);
    252          1.1  christos }
    253          1.1  christos 
    254          1.1  christos #-----------------------------------------------------------------------------
    255          1.1  christos 
    256          1.1  christos sub swapfile {
    257          1.1  christos     my ($f) = @_;
    258          1.1  christos     if ( ! -f "$f.save") {
    259          1.1  christos 	system "cp $f $f.save";
    260          1.1  christos     }
    261          1.1  christos     open(ORIG, $f);
    262          1.1  christos     open(NEW, "$f.new");
    263          1.1  christos     while (<ORIG>) {
    264          1.1  christos 	$n = <NEW>;
    265          1.1  christos 	if ($n ne $_) {
    266          1.1  christos 	    close(ORIG);
    267          1.1  christos 	    close(NEW);
    268          1.1  christos 	    print "  Updating $f\n";
    269          1.1  christos 	    rename "$f", "$f.old";
    270          1.1  christos 	    rename "$f.new", "$f";
    271          1.1  christos 	    return;
    272          1.1  christos 	}
    273          1.1  christos     }
    274          1.1  christos     close(ORIG);
    275          1.1  christos     close(NEW);
    276          1.1  christos     print "  No change to $f\n";
    277          1.1  christos     unlink "$f.new";
    278          1.1  christos }
    279