1999-05-03 07:29:11 +00:00
|
|
|
# Expect script for ld-empic tests
|
2001-03-13 06:14:29 +00:00
|
|
|
# Copyright 1994, 1995, 1996 Free Software Foundation, Inc.
|
1999-05-03 07:29:11 +00:00
|
|
|
#
|
|
|
|
# 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
|
|
|
|
}
|
|
|
|
}
|