diff options
Diffstat (limited to 'ld/testsuite/ld-empic/empic.exp')
-rw-r--r-- | ld/testsuite/ld-empic/empic.exp | 263 |
1 files changed, 263 insertions, 0 deletions
diff --git a/ld/testsuite/ld-empic/empic.exp b/ld/testsuite/ld-empic/empic.exp new file mode 100644 index 0000000..2d528be --- /dev/null +++ b/ld/testsuite/ld-empic/empic.exp @@ -0,0 +1,263 @@ +# Expect script for ld-empic tests +# Copyright (C) 1994,1995, 1996, 1997 Free Software Foundation +# +# This file is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +# +# Written by Ian Lance Taylor (ian@cygnus.com) +# + +# Test the handling of MIPS embedded PIC code. This test essentially +# tests the compiler and assembler as well as the linker, since MIPS +# embedded PIC is a GNU enhancement to standard MIPS tools. + +# Embedded PIC is only supported for MIPS ECOFF targets. +if ![istarget mips*-*-ecoff*] { + return +} + +set testname relax + +if { [which $CC] == 0 } { + untested $testname + return +} + +# Test that relaxation works correctly. This testsuite was composed +# (by experimentation) to force the linker to relax twice--that is, +# the first relaxation pass will force another call to be out of +# range, requiring a second relaxation pass. +if { ![ld_compile "$CC $CFLAGS -membedded-pic" $srcdir/$subdir/relax1.c tmpdir/relax1.o] + || ![ld_compile "$CC $CFLAGS -membedded-pic" $srcdir/$subdir/relax2.c tmpdir/relax2.o] + || ![ld_compile "$CC $CFLAGS -membedded-pic" $srcdir/$subdir/relax3.c tmpdir/relax3.o] + || ![ld_compile "$CC $CFLAGS -membedded-pic" $srcdir/$subdir/relax4.c tmpdir/relax4.o] } { + unresolved $testname + return +} + +if ![ld_simple_link $ld tmpdir/relax "--relax -T $srcdir/$subdir/relax.t tmpdir/relax1.o tmpdir/relax2.o tmpdir/relax3.o tmpdir/relax4.o"] { + fail $testname +} else { + # Check that the relaxation produced the correct result. Check + # each bal instruction. Some will go directly to the start of a + # function, which is OK. Some will form part of the five + # instruction expanded call sequence, in which case we compute the + # real destination and make sure it is the start of a function. + # Some bal instructions are used to locate the start of the + # function in order to do position independent addressing into the + # text section, in which case we just check that it correctly + # computes the start of the function. + + # Get the symbol table. + if ![ld_nm $nm tmpdir/relax] { + unresolved $testname + return + } + + # Get a disassembly. + send_log "$objdump -d tmpdir/relax >tmpdir/relax.dis\n" + verbose "$objdump -d tmpdir/relax >tmpdir/relax.dis" + catch "exec $objdump -d tmpdir/relax >tmpdir/relax.dis" exec_output + if ![string match "" $exec_output] { + send_log "$exec_output\n" + verbose $exec_output + unresolved $testname + return + } + + set balcnt 0 + set file [open tmpdir/relax.dis r] + while { [gets $file line] != -1 } { + verbose "$line" 2 + + if ![string match "*bal*" $line] { + continue + } + + verbose "$line" + + incr balcnt + + if ![regexp "^(\[0-9a-fA-F\]+) (<\[a-z+0-9A-Z.\]+>)? bal (\[0-9a-fA-F\]+)" $line whole addr label dest] { + perror "unrecognized format for $line" + unresolved $testname + return + } + + if "0x$addr + 8 != 0x$dest" { + # This is a straight function call. All function calls in + # this example are to either foo or bar. + if "0x$dest != $nm_output(foo) && 0x$dest != $nm_output(bar)" { + send_log "fail 1\n" + send_log "$line\n" + fail $testname + return + } + } else { + # Pick up the next line. If it is sll, this is a switch + # prologue, and there is not much we can do to test it. + # Otherwise, it should be lui, and the next instruction + # should be an addiu, followed by an addu to $31. + if { [gets $file l] == -1 } { + send_log "fail 2\n" + send_log "$line\n" + fail $testname + return + } + verbose $l + + if [string match "*sll*" $l] { + continue + } + if ![regexp "lui (\[\$a-z0-9\]+),(\[0-9a-fA-Fx\]+)" $l whole reg upper] { + send_log "fail 3\n" + send_log "$line\n" + send_log "$l\n" + fail $testname + return + } + + if { [gets $file l] == -1 } { + send_log "fail 4\n" + send_log "$line\n" + fail $testname + return + } + verbose "$l" + if ![regexp "addiu \\$reg,\\$reg,(\[-0-9\]+)" $l whole lower] { + send_log "fail 5\n" + send_log "$line\n" + send_log "$l\n" + send_log "addiu \\$reg,\\$reg,(\[-0-9\]+)\n" + fail $testname + return + } + + if { [gets $file l] == -1 } { + send_log "fail 6\n" + send_log "$line\n" + fail $testname + return + } + verbose "$l" + if ![regexp "addu \\$reg,\\$reg,\\\$ra" $l] { + send_log "fail 7\n" + send_log "$line\n" + send_log "$l\n" + fail $testname + return + } + + # The next line will be jalr in the case of an expanded + # call. Otherwise, the code is getting the start of the + # function, and the next line can be anything. + + if { [gets $file l] == -1 } { + send_log "fail 8\n" + send_log "$line\n" + fail $testname + return + } + verbose "$l" + if [string match "*jalr*" $l] { + set dest [expr 0x$addr + 8 + ($upper << 16) + $lower] + if { $dest != $nm_output(foo) && $dest != $nm_output(bar) } { + send_log "fail 9\n" + send_log "$line\n" + fail $testname + return + } + } else { + set dest [expr ($upper << 16) + $lower] + if ![regexp "<(\[.a-z\]+)\\+(\[0-9a-fA-F\]+)>" $label whole base offset] { + send_log "fail 10\n" + send_log "$line\n" + fail $testname + return + } + set offset 0x$offset + if { $base == ".foo" } { + set offset [expr $offset - ($nm_output(foo) - 0x30)] + } + if { $offset + 8 != - $dest } { + send_log "fail 11\n" + send_log "$line\n" + fail $testname + return + } + } + } + } + + close $file + + if {$balcnt < 10} { + send_log "fail 12\n" + fail $testname + } else { + verbose "$balcnt bal instructions" + pass $testname + } +} + +# We now test actually running embedded MIPS PIC code. This can only +# be done on a MIPS host with the same endianness as our target. +if [istarget mipsel-*-*] { + if ![ishost mips*-*-ultrix*] { + return + } +} else { + if ![ishost mips*-*-irix*] { + return + } +} + +set testname "run embedded PIC code" + +# Compile the program which will run the test. This code must be +# compiled for the host, not the target. +send_log "$CC_FOR_HOST $CFLAGS_FOR_HOST -o tmpdir/run $srcdir/$subdir/run.c\n" +verbose "$CC_FOR_HOST $CFLAGS_FOR_HOST -o tmpdir/run $srcdir/$subdir/run.c" +catch "exec $CC_FOR_HOST $CFLAGS_FOR_HOST -o tmpdir/run $srcdir/$subdir/run.c" exec_output +if ![string match "" $exec_output] { + send_log "$exec_output\n" + verbose "$exec_output" + unresolved $testname + return +} + +# Compile and link the test. +if { ![ld_compile "$CC $CFLAGS -membedded-pic" $srcdir/$subdir/runtesti.s tmpdir/runtesti.o] + || ![ld_compile "$CC $CFLAGS -membedded-pic" $srcdir/$subdir/runtest1.c tmpdir/runtest1.o] + || ![ld_compile "$CC $CFLAGS -membedded-pic" $srcdir/$subdir/runtest2.c tmpdir/runtest2.o] } { + unresolved $testname + return +} +if ![ld_simple_link $ld tmpdir/runtest "--embedded-relocs tmpdir/runtesti.o tmpdir/runtest1.o tmpdir/runtest2.o"] { + fail $testname +} else { + # Now run the test. + send_log "tmpdir/run tmpdir/runtest\n" + verbose "tmpdir/run tmpdir/runtest" + catch "exec tmpdir/run tmpdir/runtest" exec_output + if [string match "*ran and returned 0*" $exec_output] { + send_log "$exec_output\n" + verbose "$exec_output" + pass $testname + } else { + send_log "$exec_output\n" + verbose "$exec_output" + fail $testname + } +} |