aboutsummaryrefslogtreecommitdiff
path: root/tests
diff options
context:
space:
mode:
authorPeter Maydell <peter.maydell@linaro.org>2019-05-28 17:38:32 +0100
committerPeter Maydell <peter.maydell@linaro.org>2019-05-28 17:38:32 +0100
commit8c1ecb590497b0349c550607db923972b37f6963 (patch)
treeb7f45cd1b4275664cb311170acef9904cc8c24ab /tests
parent4a1d38c44089f4e7bbbc924a830f30ca0119a7dd (diff)
parent70ff5b07fcdd378180ad2d5cc0b0d5e67e7ef325 (diff)
Merge remote-tracking branch 'remotes/stsquad/tags/pull-testing-next-280519-2' into staging
Various testing updates - semihosting re-factor (used in system tests) - aarch64 and alpha system tests - editorconfig tweak for .S - some docker image updates - iotests clean-up (without make check inclusion) # gpg: Signature made Tue 28 May 2019 17:26:34 BST # gpg: using RSA key 6685AE99E75167BCAFC8DF35FBD0DB095A9E2A44 # gpg: Good signature from "Alex Bennée (Master Work Key) <alex.bennee@linaro.org>" [full] # Primary key fingerprint: 6685 AE99 E751 67BC AFC8 DF35 FBD0 DB09 5A9E 2A44 * remotes/stsquad/tags/pull-testing-next-280519-2: (27 commits) tests/qemu-iotests: re-format output to for make check-block tests/qemu-iotests/group: Re-use the "auto" group for tests that can always run Makefile.target: support per-target coverage reports Makefile: include per-target build directories in coverage report Makefile: fix coverage-report reference to BUILD_DIR .travis.yml: enable aarch64-softmmu and alpha-softmmu tcg tests tests/tcg/alpha: add system boot.S tests/tcg/multiarch: expand system memory test to cover more tests/tcg/minilib: support %c format char tests/tcg/multiarch: move the system memory test tests/tcg/aarch64: add system boot.S editorconfig: add settings for .s/.S files tests/tcg/multiarch: add hello world system test tests/tcg/multiarch: add support for multiarch system tests tests/docker: Test more components on the Fedora default image tests/docker: add ubuntu 18.04 MAINTAINERS: update for semihostings new home target/mips: convert UHI_plog to use common semihosting code target/mips: only build mips-semi for softmmu target/arm: correct return values for WRITE/READ in arm-semi ... Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Diffstat (limited to 'tests')
-rw-r--r--tests/docker/dockerfiles/fedora.docker7
-rw-r--r--tests/docker/dockerfiles/ubuntu1804.docker57
-rwxr-xr-xtests/qemu-iotests/check177
-rw-r--r--tests/qemu-iotests/group177
-rw-r--r--tests/tcg/Makefile1
-rw-r--r--tests/tcg/aarch64/Makefile.softmmu-target34
-rw-r--r--tests/tcg/aarch64/system/boot.S239
-rw-r--r--tests/tcg/aarch64/system/kernel.ld24
-rw-r--r--tests/tcg/alpha/Makefile.softmmu-target34
-rw-r--r--tests/tcg/alpha/system/boot.S511
-rw-r--r--tests/tcg/alpha/system/kernel.ld30
-rw-r--r--tests/tcg/i386/Makefile.softmmu-target4
-rw-r--r--tests/tcg/i386/system/memory.c243
-rw-r--r--tests/tcg/minilib/printf.c3
-rw-r--r--tests/tcg/multiarch/system/Makefile.softmmu-target14
-rw-r--r--tests/tcg/multiarch/system/hello.c (renamed from tests/tcg/i386/system/hello.c)0
-rw-r--r--tests/tcg/multiarch/system/memory.c449
17 files changed, 1618 insertions, 386 deletions
diff --git a/tests/docker/dockerfiles/fedora.docker b/tests/docker/dockerfiles/fedora.docker
index 69d4a7f5d7..afbba29ada 100644
--- a/tests/docker/dockerfiles/fedora.docker
+++ b/tests/docker/dockerfiles/fedora.docker
@@ -8,6 +8,7 @@ ENV PACKAGES \
bzip2-devel \
ccache \
clang \
+ cyrus-sasl-devel \
device-mapper-multipath-devel \
findutils \
flex \
@@ -23,13 +24,17 @@ ENV PACKAGES \
libaio-devel \
libasan \
libattr-devel \
+ libblockdev-mpath-devel \
libcap-devel \
libcap-ng-devel \
libcurl-devel \
libfdt-devel \
+ libiscsi-devel \
libjpeg-devel \
+ libpmem-devel \
libpng-devel \
librbd-devel \
+ libseccomp-devel \
libssh2-devel \
libubsan \
libusbx-devel \
@@ -74,10 +79,12 @@ ENV PACKAGES \
pixman-devel \
python3 \
PyYAML \
+ rdma-core-devel \
SDL2-devel \
snappy-devel \
sparse \
spice-server-devel \
+ systemd-devel \
systemtap-sdt-devel \
tar \
usbredir-devel \
diff --git a/tests/docker/dockerfiles/ubuntu1804.docker b/tests/docker/dockerfiles/ubuntu1804.docker
new file mode 100644
index 0000000000..2e2900150b
--- /dev/null
+++ b/tests/docker/dockerfiles/ubuntu1804.docker
@@ -0,0 +1,57 @@
+FROM ubuntu:18.04
+ENV PACKAGES flex bison \
+ ccache \
+ clang \
+ gcc \
+ gettext \
+ git \
+ glusterfs-common \
+ libaio-dev \
+ libattr1-dev \
+ libbluetooth-dev \
+ libbrlapi-dev \
+ libbz2-dev \
+ libcacard-dev \
+ libcap-dev \
+ libcap-ng-dev \
+ libcurl4-gnutls-dev \
+ libdrm-dev \
+ libepoxy-dev \
+ libfdt-dev \
+ libgbm-dev \
+ libgtk-3-dev \
+ libibverbs-dev \
+ libiscsi-dev \
+ libjemalloc-dev \
+ libjpeg-turbo8-dev \
+ liblzo2-dev \
+ libncurses5-dev \
+ libncursesw5-dev \
+ libnfs-dev \
+ libnss3-dev \
+ libnuma-dev \
+ libpixman-1-dev \
+ librados-dev \
+ librbd-dev \
+ librdmacm-dev \
+ libsasl2-dev \
+ libsdl2-dev \
+ libseccomp-dev \
+ libsnappy-dev \
+ libspice-protocol-dev \
+ libspice-server-dev \
+ libssh2-1-dev \
+ libusb-1.0-0-dev \
+ libusbredirhost-dev \
+ libvdeplug-dev \
+ libvte-2.91-dev \
+ libxen-dev \
+ make \
+ python-yaml \
+ sparse \
+ texinfo \
+ xfslibs-dev
+RUN apt-get update && \
+ apt-get -y install $PACKAGES
+RUN dpkg -l $PACKAGES | sort > /packages.txt
+ENV FEATURES clang pyyaml sdl2
diff --git a/tests/qemu-iotests/check b/tests/qemu-iotests/check
index 922c5d1d3d..95162c6cf9 100755
--- a/tests/qemu-iotests/check
+++ b/tests/qemu-iotests/check
@@ -27,9 +27,7 @@ bad=""
notrun=""
casenotrun=""
interrupt=true
-
-# by default don't output timestamps
-timestamp=${TIMESTAMP:=false}
+makecheck=false
_init_error()
{
@@ -88,6 +86,22 @@ _full_platform_details()
echo "$os/$platform $host $kernel"
}
+_full_env_details()
+{
+ cat <<EOF
+QEMU -- "$QEMU_PROG" $QEMU_OPTIONS
+QEMU_IMG -- "$QEMU_IMG_PROG" $QEMU_IMG_OPTIONS
+QEMU_IO -- "$QEMU_IO_PROG" $QEMU_IO_OPTIONS
+QEMU_NBD -- "$QEMU_NBD_PROG" $QEMU_NBD_OPTIONS
+IMGFMT -- $FULL_IMGFMT_DETAILS
+IMGPROTO -- $IMGPROTO
+PLATFORM -- $FULL_HOST_DETAILS
+TEST_DIR -- $TEST_DIR
+SOCKET_SCM_HELPER -- $SOCKET_SCM_HELPER
+
+EOF
+}
+
# $1 = prog to look for
set_prog_path()
{
@@ -254,8 +268,8 @@ other options
-misalign misalign memory allocations
-n show me, do not run tests
-o options -o options to pass to qemu-img create/convert
- -T output timestamps
-c mode cache mode
+ -makecheck pretty print output for make check
testlist options
-g group[,group...] include tests from these groups
@@ -403,7 +417,10 @@ testlist options
command -v xxdiff >/dev/null 2>&1 && diff=xxdiff
fi
;;
-
+ -makecheck) # makecheck friendly output
+ makecheck=true
+ xpand=false
+ ;;
-n) # show me, don't do it
showme=true
xpand=false
@@ -416,8 +433,7 @@ testlist options
cachemode=true
xpand=false
;;
- -T) # turn on timestamp output
- timestamp=true
+ -T) # deprecated timestamp option
xpand=false
;;
@@ -633,12 +649,6 @@ _wallclock()
date "+%H %M %S" | awk '{ print $1*3600 + $2*60 + $3 }'
}
-_timestamp()
-{
- now=$(date "+%T")
- printf %s " [$now]"
-}
-
_wrapup()
{
if $showme
@@ -704,23 +714,54 @@ END { if (NR > 0) {
trap "_wrapup; exit \$status" 0 1 2 3 15
+# Report the test start and results. For makecheck we want to pretty
+# print the whole report at the end of the execution.
+# args: $seq, $starttime, $lasttime
+_report_test_start()
+{
+ if ! $makecheck; then
+ if [ -n "$3" ]; then
+ local lasttime=" (last: $3s)"
+ fi
+ printf "%-8s %-10s [%s] %4s%-14s\r" "$1" "..." "$2" "..." "$lasttime"
+ fi
+}
+# args:$seq $status $starttime $lasttime $thistime $details
+_report_test_result()
+{
+ local status lasttime thistime
+ if $makecheck; then
+ if [ -n "$2" ] && [ "$2" != "pass" ]; then
+ status=" [$2]"
+ fi
+ printf " TEST iotest-$IMGFMT: %s%s\n" "$1" "$status"
+ return
+ fi
+
+ if [ -n "$4" ]; then
+ lasttime=" (last: $4s)"
+ fi
+ if [ -n "$5" ]; then
+ thistime=" $5s"
+ fi
+ case "$2" in
+ "pass") status=$(printf "\e[32m%-10s\e[0m" "$2") ;;
+ "fail") status=$(printf "\e[1m\e[31m%-10s\e[0m" "$2") ;;
+ "not run") status=$(printf "\e[33m%-10s\e[0m" "$2") ;;
+ *) status=$(printf "%-10s" "$2") ;;
+ esac
+
+ printf "%-8s %s [%s] [%s] %4s%-14s %s\n" "$1" "$status" "$3" "$(date '+%T')" "$thistime" "$lasttime" "$6"
+}
+
[ -f $TIMESTAMP_FILE ] || touch $TIMESTAMP_FILE
FULL_IMGFMT_DETAILS=$(_full_imgfmt_details)
FULL_HOST_DETAILS=$(_full_platform_details)
-cat <<EOF
-QEMU -- "$QEMU_PROG" $QEMU_OPTIONS
-QEMU_IMG -- "$QEMU_IMG_PROG" $QEMU_IMG_OPTIONS
-QEMU_IO -- "$QEMU_IO_PROG" $QEMU_IO_OPTIONS
-QEMU_NBD -- "$QEMU_NBD_PROG" $QEMU_NBD_OPTIONS
-IMGFMT -- $FULL_IMGFMT_DETAILS
-IMGPROTO -- $IMGPROTO
-PLATFORM -- $FULL_HOST_DETAILS
-TEST_DIR -- $TEST_DIR
-SOCKET_SCM_HELPER -- $SOCKET_SCM_HELPER
-
-EOF
+if ! $makecheck; then
+ _full_env_details
+fi
seq="check"
@@ -728,42 +769,43 @@ seq="check"
for seq in $list
do
- err=false
- printf %s "$seq"
+ err=false # error flag
+ printdiff=false # show diff to reference output?
+ status="" # test result summary
+ results="" # test result details
+
if [ -n "$TESTS_REMAINING_LOG" ] ; then
sed -e "s/$seq//" -e 's/ / /' -e 's/^ *//' $TESTS_REMAINING_LOG > $TESTS_REMAINING_LOG.tmp
mv $TESTS_REMAINING_LOG.tmp $TESTS_REMAINING_LOG
sync
fi
+ lasttime=$(sed -n -e "/^$seq /s/.* //p" <$TIMESTAMP_FILE)
+ starttime=$(date "+%T")
+ _report_test_start $seq $starttime $lasttime
+
if $showme
then
- echo
- continue
+ status="not run"
elif [ -f expunged ] && $expunge && egrep "^$seq([ ]|\$)" expunged >/dev/null
then
- echo " - expunged"
+ status="not run"
+ results="expunged"
rm -f $seq.out.bad
echo "/^$seq\$/d" >>$tmp.expunged
elif [ ! -f "$source_iotests/$seq" ]
then
- echo " - no such test?"
+ status="not run"
+ results="no such test?"
echo "/^$seq\$/d" >>$tmp.expunged
else
# really going to try and run this one
#
rm -f $seq.out.bad
- lasttime=$(sed -n -e "/^$seq /s/.* //p" <$TIMESTAMP_FILE)
- if [ "X$lasttime" != X ]; then
- printf %s " ${lasttime}s ..."
- else
- printf " " # prettier output with timestamps.
- fi
rm -f core $seq.notrun
rm -f $seq.casenotrun
start=$(_wallclock)
- $timestamp && printf %s " [$(date "+%T")]"
if [ "$(head -n 1 "$source_iotests/$seq")" == "#!/usr/bin/env python" ]; then
run_command="$PYTHON $seq"
@@ -781,26 +823,26 @@ do
$run_command >$tmp.out 2>&1)
fi
sts=$?
- $timestamp && _timestamp
stop=$(_wallclock)
if [ -f core ]
then
- printf " [dumped core]"
mv core $seq.core
+ status="fail"
+ results="[dumped core] $seq.core"
err=true
fi
if [ -f $seq.notrun ]
then
- $timestamp || printf " [not run] "
- $timestamp && echo " [not run]" && printf %s " $seq -- "
- cat $seq.notrun
- notrun="$notrun $seq"
+ # overwrites timestamp output
+ status="not run"
+ results="$(cat $seq.notrun)"
else
if [ $sts -ne 0 ]
then
- printf %s " [failed, exit status $sts]"
+ status="fail"
+ results=$(printf %s "[failed, exit status $sts]")
err=true
fi
@@ -821,22 +863,23 @@ do
if [ ! -f "$reference" ]
then
- echo " - no qualified output"
+ status="fail"
+ reason="no qualified output"
err=true
else
if diff -w "$reference" $tmp.out >/dev/null 2>&1
then
- echo ""
- if $err
- then
- :
- else
- echo "$seq $(expr $stop - $start)" >>$tmp.time
+ if ! $err; then
+ status="pass"
+ thistime=$(expr $stop - $start)
+ echo "$seq $thistime" >>$tmp.time
fi
else
- echo " - output mismatch (see $seq.out.bad)"
mv $tmp.out $seq.out.bad
$diff -w "$reference" "$PWD"/$seq.out.bad
+ status="fail"
+ results="output mismatch (see $seq.out.bad)"
+ printdiff=true
err=true
fi
fi
@@ -850,13 +893,27 @@ do
# come here for each test, except when $showme is true
#
- if $err
- then
- bad="$bad $seq"
- n_bad=$(expr $n_bad + 1)
- quick=false
- fi
- [ -f $seq.notrun ] || try=$(expr $try + 1)
+ _report_test_result $seq "$status" "$starttime" "$lasttime" "$thistime" "$results"
+ case "$status" in
+ "pass")
+ try=$(expr $try + 1)
+ ;;
+ "fail")
+ try=$(expr $try + 1)
+ if $makecheck; then
+ _full_env_details
+ fi
+ if $printdiff; then
+ $diff -w "$reference" "$PWD"/$seq.out.bad
+ fi
+ bad="$bad $seq"
+ n_bad=$(expr $n_bad + 1)
+ quick=false
+ ;;
+ "not run")
+ notrun="$notrun $seq"
+ ;;
+ esac
seq="after_$seq"
done
diff --git a/tests/qemu-iotests/group b/tests/qemu-iotests/group
index 52b7c16e15..2c74deec00 100644
--- a/tests/qemu-iotests/group
+++ b/tests/qemu-iotests/group
@@ -1,8 +1,21 @@
#
# QA groups control file
# Defines test groups
+#
+# Some notes about the groups:
+#
# - do not start group names with a digit
#
+# - quick : Tests in this group should finish within some few seconds.
+#
+# - img : Tests in this group can be used to excercise the qemu-img tool.
+#
+# - auto : Tests in this group are used during "make check" and should be
+# runnable in any case. That means they should run with every QEMU binary
+# (also non-x86), with every QEMU configuration (i.e. must not fail if
+# an optional feature is not compiled in - but reporting a "skip" is ok),
+# and work all kind of host filesystems and users (e.g. "nobody" or "root").
+#
#
# test-group association ... one line per test
@@ -32,11 +45,11 @@
023 rw auto
024 rw backing auto quick
025 rw auto quick
-026 rw blkdbg auto
+026 rw blkdbg
027 rw auto quick
-028 rw backing auto quick
+028 rw backing quick
029 rw auto quick
-030 rw auto backing
+030 rw backing
031 rw auto quick
032 rw auto quick
033 rw auto quick
@@ -46,35 +59,35 @@
037 rw auto backing quick
038 rw auto backing quick
039 rw auto quick
-040 rw auto
-041 rw auto backing
+040 rw
+041 rw backing
042 rw auto quick
043 rw auto backing
-044 rw auto
-045 rw auto quick
+044 rw
+045 rw quick
046 rw auto aio quick
047 rw auto quick
048 img auto quick
049 rw auto
050 rw auto backing quick
-051 rw auto
+051 rw
052 rw auto backing quick
053 rw auto quick
054 rw auto quick
-055 rw auto
-056 rw auto backing
-057 rw auto
-058 rw auto quick
+055 rw
+056 rw backing
+057 rw
+058 rw quick
059 rw auto quick
060 rw auto quick
061 rw auto
062 rw auto quick
063 rw auto quick
064 rw auto quick
-065 rw auto quick
+065 rw quick
066 rw auto quick
-067 rw auto quick
-068 rw auto quick
+067 rw quick
+068 rw quick
069 rw auto quick
070 rw auto quick
071 rw auto quick
@@ -91,18 +104,18 @@
082 rw auto quick
083 rw auto
084 img auto quick
-085 rw auto
+085 rw
086 rw auto quick
-087 rw auto quick
+087 rw quick
088 rw auto quick
089 rw auto quick
090 rw auto quick
091 rw auto migration
092 rw auto quick
-093 auto
+093 throttle
094 rw auto quick
-095 rw auto quick
-096 rw auto quick
+095 rw quick
+096 rw quick
097 rw auto backing
098 rw auto backing quick
099 rw auto quick
@@ -118,60 +131,60 @@
109 rw auto
110 rw auto backing quick
111 rw auto quick
-112 rw auto
+112 rw
113 rw auto quick
114 rw auto quick
-115 rw auto
+115 rw
116 rw auto quick
117 rw auto
-118 rw auto
+118 rw
119 rw auto quick
120 rw auto quick
-121 rw auto
+121 rw
122 rw auto
123 rw auto quick
-124 rw auto backing
-125 rw auto
+124 rw backing
+125 rw
126 rw auto backing
-127 rw auto backing quick
+127 rw backing quick
128 rw auto quick
-129 rw auto quick
+129 rw quick
130 rw auto quick
131 rw auto quick
-132 rw auto quick
+132 rw quick
133 auto quick
134 rw auto quick
135 rw auto
-136 rw auto
+136 rw
137 rw auto
138 rw auto quick
-139 rw auto quick
+139 rw quick
140 rw auto quick
141 rw auto quick
142 auto
143 auto quick
-144 rw auto quick
-145 auto quick
+144 rw quick
+145 quick
146 auto quick
-147 auto
-148 rw auto quick
-149 rw auto sudo
+147 img
+148 rw quick
+149 rw sudo
150 rw auto quick
-151 rw auto
-152 rw auto quick
-153 rw auto quick
+151 rw
+152 rw quick
+153 rw quick
154 rw auto backing quick
-155 rw auto
+155 rw
156 rw auto quick
-157 auto
+157 quick
158 rw auto quick
159 rw auto quick
160 rw auto quick
161 rw auto quick
-162 auto quick
-163 rw auto
-165 rw auto quick
-169 rw auto quick migration
+162 quick
+163 rw
+165 rw quick
+169 rw quick migration
170 rw auto quick
171 rw auto quick
172 auto
@@ -180,74 +193,74 @@
175 auto quick
176 rw auto backing
177 rw auto quick
-178 auto
+178 img
179 rw auto quick
181 rw auto migration
-182 rw auto quick
-183 rw auto migration
+182 rw quick
+183 rw migration
184 rw auto quick
-185 rw auto
+185 rw
186 rw auto
187 rw auto
-188 rw auto quick
-189 rw auto
+188 rw quick
+189 rw
190 rw auto quick
191 rw auto
192 rw auto quick
-194 rw auto migration quick
+194 rw migration quick
195 rw auto quick
-196 rw auto quick migration
+196 rw quick migration
197 rw auto quick
-198 rw auto
-199 rw auto migration
-200 rw auto
+198 rw
+199 rw migration
+200 rw
201 rw auto migration
-202 rw auto quick
-203 rw auto migration
-204 rw auto quick
-205 rw auto quick
-206 rw auto
+202 rw quick
+203 rw migration
+204 rw quick
+205 rw quick
+206 rw
207 rw auto
-208 rw auto quick
-209 rw auto quick
+208 rw quick
+209 rw quick
210 rw auto
211 rw auto quick
212 rw auto quick
213 rw auto quick
214 rw auto
215 rw auto quick
-216 rw auto quick
+216 rw quick
217 rw auto quick
-218 rw auto quick
-219 rw auto
+218 rw quick
+219 rw
220 rw auto
221 rw auto quick
-222 rw auto quick
-223 rw auto quick
-224 rw auto quick
+222 rw quick
+223 rw quick
+224 rw quick
225 rw auto quick
226 auto quick
-227 auto quick
-228 rw auto quick
+227 quick
+228 rw quick
229 auto quick
231 auto quick
-232 auto quick
+232 quick
233 auto quick
-234 auto quick migration
-235 auto quick
-236 auto quick
+234 quick migration
+235 quick
+236 quick
237 rw auto quick
-238 auto quick
+238 quick
239 rw auto quick
-240 auto quick
+240 quick
241 rw auto quick
-242 rw auto quick
+242 rw quick
243 rw auto quick
244 rw auto quick
-245 rw auto
-246 rw auto quick
-247 rw auto quick
-248 rw auto quick
+245 rw
+246 rw quick
+247 rw quick
+248 rw quick
249 rw auto quick
252 rw auto backing quick
253 rw auto quick
diff --git a/tests/tcg/Makefile b/tests/tcg/Makefile
index 1cdd628e96..6fa63cc8d5 100644
--- a/tests/tcg/Makefile
+++ b/tests/tcg/Makefile
@@ -96,6 +96,7 @@ else
# build options for bare programs are usually pretty different. They
# are expected to provide their own build recipes.
-include $(SRC_PATH)/tests/tcg/minilib/Makefile.target
+-include $(SRC_PATH)/tests/tcg/multiarch/system/Makefile.softmmu-target
-include $(SRC_PATH)/tests/tcg/$(TARGET_BASE_ARCH)/Makefile.softmmu-target
ifneq ($(TARGET_BASE_ARCH),$(TARGET_NAME))
-include $(SRC_PATH)/tests/tcg/$(TARGET_NAME)/Makefile.softmmu-target
diff --git a/tests/tcg/aarch64/Makefile.softmmu-target b/tests/tcg/aarch64/Makefile.softmmu-target
new file mode 100644
index 0000000000..2e560e4d08
--- /dev/null
+++ b/tests/tcg/aarch64/Makefile.softmmu-target
@@ -0,0 +1,34 @@
+#
+# Aarch64 system tests
+#
+
+AARCH64_SYSTEM_SRC=$(SRC_PATH)/tests/tcg/aarch64/system
+VPATH+=$(AARCH64_SYSTEM_SRC)
+
+# These objects provide the basic boot code and helper functions for all tests
+CRT_OBJS=boot.o
+
+AARCH64_TEST_SRCS=$(wildcard $(AARCH64_SYSTEM_SRC)/*.c)
+AARCH64_TESTS = $(patsubst $(AARCH64_SYSTEM_SRC)/%.c, %, $(AARCH64_TEST_SRCS))
+
+CRT_PATH=$(AARCH64_SYSTEM_SRC)
+LINK_SCRIPT=$(AARCH64_SYSTEM_SRC)/kernel.ld
+LDFLAGS=-Wl,-T$(LINK_SCRIPT)
+TESTS+=$(AARCH64_TESTS) $(MULTIARCH_TESTS)
+CFLAGS+=-nostdlib -ggdb -O0 $(MINILIB_INC)
+LDFLAGS+=-static -nostdlib $(CRT_OBJS) $(MINILIB_OBJS) -lgcc
+
+# building head blobs
+.PRECIOUS: $(CRT_OBJS)
+
+%.o: $(CRT_PATH)/%.S
+ $(CC) $(CFLAGS) -x assembler-with-cpp -c $< -o $@
+
+# Build and link the tests
+%: %.c $(LINK_SCRIPT) $(CRT_OBJS) $(MINILIB_OBJS)
+ $(CC) $(CFLAGS) $< -o $@ $(LDFLAGS)
+
+memory: CFLAGS+=-DCHECK_UNALIGNED=1
+
+# Running
+QEMU_OPTS+=-M virt -cpu max -display none -semihosting-config enable=on,target=native,chardev=output -kernel
diff --git a/tests/tcg/aarch64/system/boot.S b/tests/tcg/aarch64/system/boot.S
new file mode 100644
index 0000000000..b14e94f332
--- /dev/null
+++ b/tests/tcg/aarch64/system/boot.S
@@ -0,0 +1,239 @@
+/*
+ * Minimal AArch64 system boot code.
+ *
+ * Copyright Linaro Ltd 2019
+ *
+ * Loosely based on the newlib/libgloss setup stubs. Using semihosting
+ * for serial output and exit functions.
+ */
+
+/*
+ * Semihosting interface on ARM AArch64
+ * See "Semihosting for AArch32 and AArch64 Relase 2.0" by ARM
+ * w0 - semihosting call number
+ * x1 - semihosting parameter
+ */
+#define semihosting_call hlt 0xf000
+#define SYS_WRITEC 0x03 /* character to debug channel */
+#define SYS_WRITE0 0x04 /* string to debug channel */
+#define SYS_EXIT 0x18
+
+ .align 12
+
+ .macro ventry label
+ .align 7
+ b \label
+ .endm
+
+vector_table:
+ /* Current EL with SP0. */
+ ventry curr_sp0_sync /* Synchronous */
+ ventry curr_sp0_irq /* Irq/vIRQ */
+ ventry curr_sp0_fiq /* Fiq/vFIQ */
+ ventry curr_sp0_serror /* SError/VSError */
+
+ /* Current EL with SPx. */
+ ventry curr_spx_sync /* Synchronous */
+ ventry curr_spx_irq /* IRQ/vIRQ */
+ ventry curr_spx_fiq /* FIQ/vFIQ */
+ ventry curr_spx_serror /* SError/VSError */
+
+ /* Lower EL using AArch64. */
+ ventry lower_a64_sync /* Synchronous */
+ ventry lower_a64_irq /* IRQ/vIRQ */
+ ventry lower_a64_fiq /* FIQ/vFIQ */
+ ventry lower_a64_serror /* SError/VSError */
+
+ /* Lower EL using AArch32. */
+ ventry lower_a32_sync /* Synchronous */
+ ventry lower_a32_irq /* IRQ/vIRQ */
+ ventry lower_a32_fiq /* FIQ/vFIQ */
+ ventry lower_a32_serror /* SError/VSError */
+
+ .text
+ .align 4
+
+ /* Common vector handling for now */
+curr_sp0_sync:
+curr_sp0_irq:
+curr_sp0_fiq:
+curr_sp0_serror:
+curr_spx_sync:
+curr_spx_irq:
+curr_spx_fiq:
+curr_spx_serror:
+lower_a64_sync:
+lower_a64_irq:
+lower_a64_fiq:
+lower_a64_serror:
+lower_a32_sync:
+lower_a32_irq:
+lower_a32_fiq:
+lower_a32_serror:
+ mov x0, SYS_WRITE0
+ adr x1, .error
+ semihosting_call
+ mov x0, SYS_EXIT
+ mov x1, 1
+ semihosting_call
+ /* never returns */
+
+ .section .rodata
+.error:
+ .string "Terminated by exception.\n"
+
+ .text
+ .align 4
+ .global __start
+__start:
+ /* Installs a table of exception vectors to catch and handle all
+ exceptions by terminating the process with a diagnostic. */
+ adr x0, vector_table
+ msr vbar_el1, x0
+
+ /* Page table setup (identity mapping). */
+ adrp x0, ttb
+ add x0, x0, :lo12:ttb
+ msr ttbr0_el1, x0
+
+ /*
+ * Setup a flat address mapping page-tables. Stage one simply
+ * maps RAM to the first Gb. The stage2 tables have two 2mb
+ * translation block entries covering a series of adjacent
+ * 4k pages.
+ */
+
+ /* Stage 1 entry: indexed by IA[38:30] */
+ adr x1, . /* phys address */
+ bic x1, x1, #(1 << 30) - 1 /* 1GB alignment*/
+ add x2, x0, x1, lsr #(30 - 3) /* offset in l1 page table */
+
+ /* point to stage 2 table [47:12] */
+ adrp x0, ttb_stage2
+ orr x1, x0, #3 /* ptr to stage 2 */
+ str x1, [x2]
+
+ /* Stage 2 entries: indexed by IA[29:21] */
+ ldr x5, =(((1 << 9) - 1) << 21)
+
+ /* First block: .text/RO/execute enabled */
+ adr x1, . /* phys address */
+ bic x1, x1, #(1 << 21) - 1 /* 2mb block alignment */
+ and x4, x1, x5 /* IA[29:21] */
+ add x2, x0, x4, lsr #(21 - 3) /* offset in l2 page table */
+ ldr x3, =0x401 /* attr(AF, block) */
+ orr x1, x1, x3
+ str x1, [x2] /* 1st 2mb (.text & rodata) */
+
+ /* Second block: .data/RW/no execute */
+ adrp x1, .data
+ add x1, x1, :lo12:.data
+ bic x1, x1, #(1 << 21) - 1 /* 2mb block alignment */
+ and x4, x1, x5 /* IA[29:21] */
+ add x2, x0, x4, lsr #(21 - 3) /* offset in l2 page table */
+ ldr x3, =(3 << 53) | 0x401 /* attr(AF, NX, block) */
+ orr x1, x1, x3
+ str x1, [x2] /* 2nd 2mb (.data & .bss)*/
+
+ /* Setup/enable the MMU. */
+
+ /*
+ * TCR_EL1 - Translation Control Registers
+ *
+ * IPS[34:32] = 40-bit PA, 1TB
+ * TG0[14:15] = b00 => 4kb granuale
+ * ORGN0[11:10] = Outer: Normal, WB Read-Alloc No Write-Alloc Cacheable
+ * IRGN0[9:8] = Inner: Normal, WB Read-Alloc No Write-Alloc Cacheable
+ * T0SZ[5:0] = 2^(64 - 25)
+ *
+ * The size of T0SZ controls what the initial lookup level. It
+ * would be nice to start at level 2 but unfortunatly for a
+ * flat-mapping on the virt machine we need to handle IA's
+ * with at least 1gb range to see RAM. So we start with a
+ * level 1 lookup.
+ */
+ ldr x0, = (2 << 32) | 25 | (3 << 10) | (3 << 8)
+ msr tcr_el1, x0
+
+ mov x0, #0xee /* Inner/outer cacheable WB */
+ msr mair_el1, x0
+ isb
+
+ /*
+ * SCTLR_EL1 - System Control Register
+ *
+ * WXN[19] = 0 = no effect, Write does not imply XN (execute never)
+ * I[12] = Instruction cachability control
+ * SA[3] = SP alignment check
+ * C[2] = Data cachability control
+ * M[0] = 1, enable stage 1 address translation for EL0/1
+ */
+ mrs x0, sctlr_el1
+ ldr x1, =0x100d /* bits I(12) SA(3) C(2) M(0) */
+ bic x0, x0, #(1 << 1) /* clear bit A(1) */
+ bic x0, x0, #(1 << 19) /* clear WXN */
+ orr x0, x0, x1 /* set bits */
+
+ dsb sy
+ msr sctlr_el1, x0
+ isb
+
+ /*
+ * Enable FP registers. The standard C pre-amble will be
+ * saving these and A-profile compilers will use AdvSIMD
+ * registers unless we tell it not to.
+ */
+ mrs x0, cpacr_el1
+ orr x0, x0, #(3 << 20)
+ msr cpacr_el1, x0
+
+ /* Setup some stack space and enter the test code.
+ * Assume everthing except the return value is garbage when we
+ * return, we won't need it.
+ */
+ adrp x0, stack_end
+ add x0, x0, :lo12:stack_end
+ mov sp, x0
+ bl main
+
+ /* pass return value to sys exit */
+ mov x1, x0
+ ldr x0, =0x20026 /* ADP_Stopped_ApplicationExit */
+ stp x0, x1, [sp, #-16]!
+ mov x1, sp
+ mov x0, SYS_EXIT
+ semihosting_call
+ /* never returns */
+
+ /*
+ * Helper Functions
+ */
+
+ /* Output a single character to serial port */
+ .global __sys_outc
+__sys_outc:
+ stp x0, x1, [sp, #-16]!
+ /* pass address of c on stack */
+ mov x1, sp
+ mov x0, SYS_WRITEC
+ semihosting_call
+ ldp x0, x1, [sp], #16
+ ret
+
+ .data
+ .align 12
+
+ /* Translation table
+ * @4k granuale: 9 bit lookup, 512 entries
+ */
+ttb:
+ .space 4096, 0
+
+ .align 12
+ttb_stage2:
+ .space 4096, 0
+
+ .align 12
+stack:
+ .space 65536, 0
+stack_end:
diff --git a/tests/tcg/aarch64/system/kernel.ld b/tests/tcg/aarch64/system/kernel.ld
new file mode 100644
index 0000000000..7b3a76dcbf
--- /dev/null
+++ b/tests/tcg/aarch64/system/kernel.ld
@@ -0,0 +1,24 @@
+ENTRY(__start)
+
+SECTIONS
+{
+ /* virt machine, RAM starts at 1gb */
+ . = (1 << 30);
+ .text : {
+ *(.text)
+ }
+ .rodata : {
+ *(.rodata)
+ }
+ /* align r/w section to next 2mb */
+ . = ALIGN(1 << 21);
+ .data : {
+ *(.data)
+ }
+ .bss : {
+ *(.bss)
+ }
+ /DISCARD/ : {
+ *(.ARM.attributes)
+ }
+}
diff --git a/tests/tcg/alpha/Makefile.softmmu-target b/tests/tcg/alpha/Makefile.softmmu-target
new file mode 100644
index 0000000000..3c0f34cc69
--- /dev/null
+++ b/tests/tcg/alpha/Makefile.softmmu-target
@@ -0,0 +1,34 @@
+#
+# Alpha system tests
+#
+
+ALPHA_SYSTEM_SRC=$(SRC_PATH)/tests/tcg/alpha/system
+VPATH+=$(ALPHA_SYSTEM_SRC)
+
+# These objects provide the basic boot code and helper functions for all tests
+CRT_OBJS=boot.o
+
+ALPHA_TEST_SRCS=$(wildcard $(ALPHA_SYSTEM_SRC)/*.c)
+ALPHA_TESTS = $(patsubst $(ALPHA_SYSTEM_SRC)/%.c, %, $(ALPHA_TEST_SRCS))
+
+CRT_PATH=$(ALPHA_SYSTEM_SRC)
+LINK_SCRIPT=$(ALPHA_SYSTEM_SRC)/kernel.ld
+LDFLAGS=-Wl,-T$(LINK_SCRIPT)
+TESTS+=$(ALPHA_TESTS) $(MULTIARCH_TESTS)
+CFLAGS+=-nostdlib -g -O1 -mcpu=ev6 $(MINILIB_INC)
+LDFLAGS+=-static -nostdlib $(CRT_OBJS) $(MINILIB_OBJS) -lgcc
+
+# building head blobs
+.PRECIOUS: $(CRT_OBJS)
+
+%.o: $(CRT_PATH)/%.S
+ $(CC) $(CFLAGS) -x assembler-with-cpp -c $< -o $@
+
+# Build and link the tests
+%: %.c $(LINK_SCRIPT) $(CRT_OBJS) $(MINILIB_OBJS)
+ $(CC) $(CFLAGS) $< -o $@ $(LDFLAGS)
+
+memory: CFLAGS+=-DCHECK_UNALIGNED=0
+
+# Running
+QEMU_OPTS+=-serial chardev:output -kernel
diff --git a/tests/tcg/alpha/system/boot.S b/tests/tcg/alpha/system/boot.S
new file mode 100644
index 0000000000..9791b1ef7c
--- /dev/null
+++ b/tests/tcg/alpha/system/boot.S
@@ -0,0 +1,511 @@
+/*
+ * Minimal Alpha system boot code.
+ *
+ * Copyright Linaro Ltd 2019
+ */
+
+ .set noat
+ .set nomacro
+ .arch ev6
+ .text
+
+.macro load_pci_io reg
+ /* For typhoon, this is
+ * 0xfffffc0000000000 -- kseg identity map
+ * + 0x10000000000 -- typhoon pio base
+ * + 0x1fc000000 -- typhoon pchip0 pci base
+ * = 0xfffffd01fc000000
+ */
+ ldah \reg, -3 /* ff..fd0000 */
+ lda \reg, 0x1fc(\reg) /* ff..fd01fc */
+ sll \reg, 24, \reg
+.endm
+
+#define com1Rbr 0x3f8
+#define com1Thr 0x3f8
+#define com1Ier 0x3f9
+#define com1Iir 0x3fa
+#define com1Lcr 0x3fb
+#define com1Mcr 0x3fc
+#define com1Lsr 0x3fd
+#define com1Msr 0x3fe
+#define com1Scr 0x3ff
+#define com1Dll 0x3f8
+#define com1Dlm 0x3f9
+
+#define PAL_halt 0
+#define PAL_wrent 52
+#define PAL_wrkgp 55
+
+ .text
+ .p2align 4
+ .globl _start
+ .ent _start
+_start:
+ br $gp, .+4
+ ldah $gp, 0($gp) !gpdisp!1
+ lda $gp, 0($gp) !gpdisp!1
+
+ ldah $sp, $stack_end($gp) !gprelhigh
+ lda $sp, $stack_end($sp) !gprellow
+
+ /* Install kernel gp for exception handlers. */
+ mov $gp, $16
+ call_pal PAL_wrkgp
+
+ /* Install exception handlers. */
+ ldah $16, entInt($gp) !gprelhigh
+ lda $16, entInt($16) !gprellow
+ lda $17, 0
+ call_pal PAL_wrent
+
+ ldah $16, entArith($gp) !gprelhigh
+ lda $16, entArith($16) !gprellow
+ lda $17, 1
+ call_pal PAL_wrent
+
+ ldah $16, entMM($gp) !gprelhigh
+ lda $16, entMM($16) !gprellow
+ lda $17, 2
+ call_pal PAL_wrent
+
+ ldah $16, entIF($gp) !gprelhigh
+ lda $16, entIF($16) !gprellow
+ lda $17, 3
+ call_pal PAL_wrent
+
+ ldah $16, entUna($gp) !gprelhigh
+ lda $16, entUna($16) !gprellow
+ lda $17, 4
+ call_pal PAL_wrent
+
+ ldah $16, entSys($gp) !gprelhigh
+ lda $16, entSys($16) !gprellow
+ lda $17, 5
+ call_pal PAL_wrent
+
+ /*
+ * Initialize COM1.
+ */
+ load_pci_io $1
+ lda $2, 0x87 /* outb(0x87, com1Lcr); */
+ stb $2, com1Lcr($1)
+ stb $31, com1Dlm($1) /* outb(0, com1Dlm); */
+ lda $2, 3 /* baudconst 3 => 56000 */
+ stb $2, com1Dll($1) /* outb(baudconst, com1Dll); */
+ lda $2, 0x07
+ stb $2, com1Lcr($1) /* outb(0x07, com1Lcr) */
+ lda $2, 0x0f
+ stb $2, com1Mcr($1) /* outb(0x0f, com1Mcr) */
+
+ bsr $26, main !samegp
+
+ /* fall through to _exit */
+ .end _start
+
+ .globl _exit
+ .ent _exit
+_exit:
+ .frame $sp, 0, $26, 0
+ .prologue 0
+
+ /* We cannot return an error code. */
+ call_pal PAL_halt
+ .end _exit
+
+/*
+ * We have received an exception that we don't handle. Log and exit.
+ */
+ .ent log_exit
+log_exit:
+entInt:
+entArith:
+entMM:
+entIF:
+entUna:
+entSys:
+ ldah $16, $errormsg($gp) !gprelhigh
+ lda $16, $errormsg($16) !gprellow
+ bsr $26, __sys_outs !samegp
+ bsr $26, _exit !samegp
+ .end log_exit
+
+ .section .rodata
+$errormsg:
+ .string "Terminated by exception.\n"
+ .previous
+
+ /*
+ * Helper Functions
+ */
+
+ /* Output a single character to serial port */
+ .global __sys_outc
+ .ent __sys_outc
+__sys_outc:
+ .frame $sp, 0, $26, 0
+ .prologue 0
+
+ load_pci_io $1
+
+ /*
+ * while ((inb(com1Lsr) & 0x20) == 0)
+ * continue;
+ */
+1: ldbu $0, com1Lsr($1)
+ and $0, 0x20, $0
+ beq $0, 1b
+
+ /* outb(c, com1Thr); */
+ stb $16, com1Thr($1)
+ ret
+ .end __sys_outc
+
+ /* Output a nul-terminated string to serial port */
+ .global __sys_outs
+ .ent __sys_outs
+__sys_outs:
+ .frame $sp, 0, $26, 0
+ .prologue 0
+
+ load_pci_io $1
+
+ ldbu $2, 0($16)
+ beq $2, 9f
+
+ /*
+ * while ((inb(com1Lsr) & 0x20) == 0)
+ * continue;
+ */
+1: ldbu $0, com1Lsr($1)
+ and $0, 0x20, $0
+ beq $0, 1b
+
+ /* outb(c, com1Thr); */
+ stb $2, com1Thr($1)
+
+ addq $16, 1, $16
+ ldbu $2, 0($16)
+ bne $2, 1b
+
+9: ret
+ .end __sys_outs
+
+/*
+ * Division routines that are normally in libc.
+ *
+ * These do not follow the C calling convention. Arguments are in $24+$25,
+ * the result is in $27. Register $28 may be clobbered; everything else
+ * must be saved.
+ *
+ * We store the remainder in $28, so that we can share code.
+ *
+ * We do not signal divide by zero.
+ */
+
+/*
+ * Unsigned 64-bit division.
+ */
+
+ .globl __divqu
+ .ent __divqu
+__divqu:
+ .frame $sp, 48, $23
+ subq $sp, 48, $sp
+ stq $0, 0($sp)
+ stq $1, 8($sp)
+ stq $2, 16($sp)
+ stq $3, 24($sp)
+ stq $4, 32($sp)
+ .prologue 0
+
+#define mask $0
+#define divisor $1
+#define compare $2
+#define tmp1 $3
+#define tmp2 $4
+#define quotient $27
+#define modulus $28
+
+ mov $24, modulus
+ mov $25, divisor
+ mov $31, quotient
+ mov 1, mask
+ beq $25, 9f
+
+ /* Shift left until divisor >= modulus. */
+1: cmpult divisor, modulus, compare
+ blt divisor, 2f
+ addq divisor, divisor, divisor
+ addq mask, mask, mask
+ bne compare, 1b
+
+2: addq quotient, mask, tmp2
+ srl mask, 1, mask
+ cmpule divisor, modulus, compare
+ subq modulus, divisor, tmp1
+ cmovne compare, tmp2, quotient
+ srl divisor, 1, divisor
+ cmovne compare, tmp1, modulus
+ bne mask, 2b
+
+9: ldq $0, 0($sp)
+ ldq $1, 8($sp)
+ ldq $2, 16($sp)
+ ldq $3, 24($sp)
+ ldq $4, 32($sp)
+ addq $sp, 48, $sp
+ ret $31, ($23), 1
+
+#undef mask
+#undef divisor
+#undef compare
+#undef tmp1
+#undef tmp2
+#undef quotient
+#undef modulus
+
+ .end __divqu
+
+/*
+ * Unsigned 64-bit remainder.
+ * Note that __divqu above leaves the result in $28.
+ */
+
+ .globl __remqu
+ .ent __remqu
+__remqu:
+ .frame $sp, 16, $23
+ subq $sp, 16, $sp
+ stq $23, 0($sp)
+ .prologue 0
+
+ bsr $23, __divqu
+
+ ldq $23, 0($sp)
+ mov $28, $27
+ addq $sp, 16, $sp
+ ret $31, ($23), 1
+ .end __remqu
+
+/*
+ * Signed 64-bit division.
+ */
+
+ .globl __divqs
+ .ent __divqs
+__divqs:
+ .prologue 0
+
+ /* Common case: both arguments are positive. */
+ bis $24, $25, $28
+ bge $28, __divqu
+
+ /* At least one argument is negative. */
+ subq $sp, 32, $sp
+ stq $23, 0($sp)
+ stq $24, 8($sp)
+ stq $25, 16($sp)
+
+ /* Compute absolute values. */
+ subq $31, $24, $28
+ cmovlt $24, $28, $24
+ subq $31, $25, $28
+ cmovlt $25, $28, $25
+
+ bsr $23, __divqu
+
+ ldq $24, 8($sp)
+ ldq $25, 16($sp)
+
+ /* -a / b = a / -b = -(a / b) */
+ subq $31, $27, $23
+ xor $24, $25, $28
+ cmovlt $28, $23, $27
+
+ ldq $23, 0($sp)
+ addq $sp, 32, $sp
+ ret $31, ($23), 1
+ .end __divqs
+
+/*
+ * Signed 64-bit remainder.
+ */
+
+ .globl __remqs
+ .ent __remqs
+__remqs:
+ .prologue 0
+
+ /* Common case: both arguments are positive. */
+ bis $24, $25, $28
+ bge $28, __remqu
+
+ /* At least one argument is negative. */
+ subq $sp, 32, $sp
+ stq $23, 0($sp)
+ stq $24, 8($sp)
+ stq $25, 16($sp)
+
+ /* Compute absolute values. */
+ subq $31, $24, $28
+ cmovlt $24, $28, $24
+ subq $31, $25, $28
+ cmovlt $25, $28, $25
+
+ bsr $23, __divqu
+
+ ldq $23, 0($sp)
+ ldq $24, 8($sp)
+ ldq $25, 16($sp)
+
+ /* -a % b = -(a % b); a % -b = a % b. */
+ subq $31, $28, $27
+ cmovge $24, $28, $27
+
+ addq $sp, 32, $sp
+ ret $31, ($23), 1
+ .end __remqs
+
+/*
+ * Unsigned 32-bit division.
+ */
+
+ .globl __divlu
+ .ent __divlu
+__divlu:
+ .frame $sp, 32, $23
+ subq $sp, 32, $sp
+ stq $23, 0($sp)
+ stq $24, 8($sp)
+ stq $25, 16($sp)
+ .prologue 0
+
+ /* Zero extend and use the 64-bit routine. */
+ zap $24, 0xf0, $24
+ zap $25, 0xf0, $25
+ bsr $23, __divqu
+
+ addl $27, 0, $27
+ ldq $23, 0($sp)
+ ldq $24, 8($sp)
+ ldq $25, 16($sp)
+ addq $sp, 32, $sp
+ ret $31, ($23), 1
+ .end __divlu
+
+/*
+ * Unsigned 32-bit remainder.
+ */
+
+ .globl __remlu
+ .ent __remlu
+__remlu:
+ .frame $sp, 32, $23
+ subq $sp, 32, $sp
+ stq $23, 0($sp)
+ stq $24, 8($sp)
+ stq $25, 16($sp)
+ .prologue 0
+
+ /* Zero extend and use the 64-bit routine. */
+ zap $24, 0xf0, $24
+ zap $25, 0xf0, $25
+ bsr $23, __divqu
+
+ /* Recall that the remainder is returned in $28. */
+ addl $28, 0, $27
+ ldq $23, 0($sp)
+ ldq $24, 8($sp)
+ ldq $25, 16($sp)
+ addq $sp, 32, $sp
+ ret $31, ($23), 1
+ .end __remlu
+
+/*
+ * Signed 32-bit division.
+ */
+
+ .globl __divls
+ .ent __divls
+__divls:
+ .frame $sp, 32, $23
+ subq $sp, 32, $sp
+ stq $23, 0($sp)
+ stq $24, 8($sp)
+ stq $25, 16($sp)
+ .prologue 0
+
+ /* Sign extend. */
+ addl $24, 0, $24
+ addl $25, 0, $25
+
+ /* Compute absolute values. */
+ subq $31, $24, $28
+ cmovlt $24, $28, $24
+ subq $31, $25, $28
+ cmovlt $25, $28, $25
+
+ bsr $23, __divqu
+
+ ldq $24, 8($sp)
+ ldq $25, 16($sp)
+
+ /* Negate the unsigned result, if necessary. */
+ xor $24, $25, $28
+ subl $31, $27, $23
+ addl $27, 0, $27
+ addl $28, 0, $28
+ cmovlt $28, $23, $27
+
+ ldq $23, 0($sp)
+ addq $sp, 32, $sp
+ ret $31, ($23), 1
+ .end __divls
+
+/*
+ * Signed 32-bit remainder.
+ */
+
+ .globl __remls
+ .ent __remls
+__remls:
+ .frame $sp, 32, $23
+ subq $sp, 32, $sp
+ stq $23, 0($sp)
+ stq $24, 8($sp)
+ stq $25, 16($sp)
+ .prologue 0
+
+ /* Sign extend. */
+ addl $24, 0, $24
+ addl $25, 0, $25
+
+ /* Compute absolute values. */
+ subq $31, $24, $28
+ cmovlt $24, $28, $24
+ subq $31, $25, $28
+ cmovlt $25, $28, $25
+
+ bsr $23, __divqu
+
+ ldq $23, 0($sp)
+ ldq $24, 8($sp)
+ ldq $25, 16($sp)
+
+ /* Negate the unsigned result, if necessary. */
+ subl $31, $28, $27
+ addl $28, 0, $28
+ cmovge $24, $28, $27
+
+ addq $sp, 32, $sp
+ ret $31, ($23), 1
+ .end __remls
+
+ .data
+ .p2align 4
+stack:
+ .skip 65536
+$stack_end:
+ .type stack,@object
+ .size stack, . - stack
diff --git a/tests/tcg/alpha/system/kernel.ld b/tests/tcg/alpha/system/kernel.ld
new file mode 100644
index 0000000000..d2ac6ecfeb
--- /dev/null
+++ b/tests/tcg/alpha/system/kernel.ld
@@ -0,0 +1,30 @@
+ENTRY(_start)
+
+SECTIONS
+{
+ /* Linux kernel legacy start address. */
+ . = 0xfffffc0000310000;
+ _text = .;
+ .text : {
+ *(.text)
+ }
+ .rodata : {
+ *(.rodata)
+ }
+ _etext = .;
+
+ . = ALIGN(8192);
+ _data = .;
+ .got : {
+ *(.got)
+ }
+ .data : {
+ *(.sdata)
+ *(.data)
+ }
+ _edata = .;
+ .bss : {
+ *(.bss)
+ }
+ _end = .;
+}
diff --git a/tests/tcg/i386/Makefile.softmmu-target b/tests/tcg/i386/Makefile.softmmu-target
index 53c9c5ece0..e1f98177aa 100644
--- a/tests/tcg/i386/Makefile.softmmu-target
+++ b/tests/tcg/i386/Makefile.softmmu-target
@@ -27,7 +27,7 @@ CFLAGS+=-m32
LINK_SCRIPT=$(I386_SYSTEM_SRC)/kernel.ld
LDFLAGS=-Wl,-T$(LINK_SCRIPT) -Wl,-melf_i386
# FIXME: move to common once x86_64 is bootstrapped
-TESTS+=$(X86_TESTS)
+TESTS+=$(X86_TESTS) $(MULTIARCH_TESTS)
endif
CFLAGS+=-nostdlib -ggdb -O0 $(MINILIB_INC)
LDFLAGS+=-static -nostdlib $(CRT_OBJS) $(MINILIB_OBJS) -lgcc
@@ -42,5 +42,7 @@ LDFLAGS+=-static -nostdlib $(CRT_OBJS) $(MINILIB_OBJS) -lgcc
%: %.c $(LINK_SCRIPT) $(CRT_OBJS) $(MINILIB_OBJS)
$(CC) $(CFLAGS) $< -o $@ $(LDFLAGS)
+memory: CFLAGS+=-DCHECK_UNALIGNED=1
+
# Running
QEMU_OPTS+=-device isa-debugcon,chardev=output -device isa-debug-exit,iobase=0xf4,iosize=0x4 -kernel
diff --git a/tests/tcg/i386/system/memory.c b/tests/tcg/i386/system/memory.c
deleted file mode 100644
index a7a0a8e978..0000000000
--- a/tests/tcg/i386/system/memory.c
+++ /dev/null
@@ -1,243 +0,0 @@
-/*
- * Memory Test
- *
- * This is intended to test the softmmu code and ensure we properly
- * behave across normal and unaligned accesses across several pages.
- * We are not replicating memory tests for stuck bits and other
- * hardware level failures but looking for issues with different size
- * accesses when:
-
- *
- */
-
-#include <inttypes.h>
-#include <minilib.h>
-
-#define TEST_SIZE (4096 * 4) /* 4 pages */
-
-static uint8_t test_data[TEST_SIZE];
-
-static void pdot(int count)
-{
- if (count % 128 == 0) {
- ml_printf(".");
- }
-}
-
-
-/*
- * Fill the data with ascending value bytes. As x86 is a LE machine we
- * write in ascending order and then read and high byte should either
- * be zero or higher than the lower bytes.
- */
-
-static void init_test_data_u8(void)
-{
- uint8_t count = 0, *ptr = &test_data[0];
- int i;
-
- ml_printf("Filling test area with u8:");
- for (i = 0; i < TEST_SIZE; i++) {
- *ptr++ = count++;
- pdot(i);
- }
- ml_printf("done\n");
-}
-
-static void init_test_data_u16(int offset)
-{
- uint8_t count = 0;
- uint16_t word, *ptr = (uint16_t *) &test_data[0];
- const int max = (TEST_SIZE - offset) / sizeof(word);
- int i;
-
- ml_printf("Filling test area with u16 (offset %d):", offset);
-
- /* Leading zeros */
- for (i = 0; i < offset; i++) {
- *ptr = 0;
- }
-
- ptr = (uint16_t *) &test_data[offset];
- for (i = 0; i < max; i++) {
- uint8_t high, low;
- low = count++;
- high = count++;
- word = (high << 8) | low;
- *ptr++ = word;
- pdot(i);
- }
- ml_printf("done\n");
-}
-
-static void init_test_data_u32(int offset)
-{
- uint8_t count = 0;
- uint32_t word, *ptr = (uint32_t *) &test_data[0];
- const int max = (TEST_SIZE - offset) / sizeof(word);
- int i;
-
- ml_printf("Filling test area with u32 (offset %d):", offset);
-
- /* Leading zeros */
- for (i = 0; i < offset; i++) {
- *ptr = 0;
- }
-
- ptr = (uint32_t *) &test_data[offset];
- for (i = 0; i < max; i++) {
- uint8_t b1, b2, b3, b4;
- b4 = count++;
- b3 = count++;
- b2 = count++;
- b1 = count++;
- word = (b1 << 24) | (b2 << 16) | (b3 << 8) | b4;
- *ptr++ = word;
- pdot(i);
- }
- ml_printf("done\n");
-}
-
-
-static int read_test_data_u16(int offset)
-{
- uint16_t word, *ptr = (uint16_t *)&test_data[offset];
- int i;
- const int max = (TEST_SIZE - offset) / sizeof(word);
-
- ml_printf("Reading u16 from %#lx (offset %d):", ptr, offset);
-
- for (i = 0; i < max; i++) {
- uint8_t high, low;
- word = *ptr++;
- high = (word >> 8) & 0xff;
- low = word & 0xff;
- if (high < low && high != 0) {
- ml_printf("Error %d < %d\n", high, low);
- return 1;
- } else {
- pdot(i);
- }
-
- }
- ml_printf("done\n");
- return 0;
-}
-
-static int read_test_data_u32(int offset)
-{
- uint32_t word, *ptr = (uint32_t *)&test_data[offset];
- int i;
- const int max = (TEST_SIZE - offset) / sizeof(word);
-
- ml_printf("Reading u32 from %#lx (offset %d):", ptr, offset);
-
- for (i = 0; i < max; i++) {
- uint8_t b1, b2, b3, b4;
- word = *ptr++;
-
- b1 = word >> 24 & 0xff;
- b2 = word >> 16 & 0xff;
- b3 = word >> 8 & 0xff;
- b4 = word & 0xff;
-
- if ((b1 < b2 && b1 != 0) ||
- (b2 < b3 && b2 != 0) ||
- (b3 < b4 && b3 != 0)) {
- ml_printf("Error %d, %d, %d, %d", b1, b2, b3, b4);
- return 2;
- } else {
- pdot(i);
- }
- }
- ml_printf("done\n");
- return 0;
-}
-
-static int read_test_data_u64(int offset)
-{
- uint64_t word, *ptr = (uint64_t *)&test_data[offset];
- int i;
- const int max = (TEST_SIZE - offset) / sizeof(word);
-
- ml_printf("Reading u64 from %#lx (offset %d):", ptr, offset);
-
- for (i = 0; i < max; i++) {
- uint8_t b1, b2, b3, b4, b5, b6, b7, b8;
- word = *ptr++;
-
- b1 = ((uint64_t) (word >> 56)) & 0xff;
- b2 = ((uint64_t) (word >> 48)) & 0xff;
- b3 = ((uint64_t) (word >> 40)) & 0xff;
- b4 = (word >> 32) & 0xff;
- b5 = (word >> 24) & 0xff;
- b6 = (word >> 16) & 0xff;
- b7 = (word >> 8) & 0xff;
- b8 = (word >> 0) & 0xff;
-
- if ((b1 < b2 && b1 != 0) ||
- (b2 < b3 && b2 != 0) ||
- (b3 < b4 && b3 != 0) ||
- (b4 < b5 && b4 != 0) ||
- (b5 < b6 && b5 != 0) ||
- (b6 < b7 && b6 != 0) ||
- (b7 < b8 && b7 != 0)) {
- ml_printf("Error %d, %d, %d, %d, %d, %d, %d, %d",
- b1, b2, b3, b4, b5, b6, b7, b8);
- return 2;
- } else {
- pdot(i);
- }
- }
- ml_printf("done\n");
- return 0;
-}
-
-/* Read the test data and verify at various offsets */
-int do_reads(void)
-{
- int r = 0;
- int off = 0;
-
- while (r == 0 && off < 8) {
- r = read_test_data_u16(off);
- r |= read_test_data_u32(off);
- r |= read_test_data_u64(off);
- off++;
- }
-
- return r;
-}
-
-int main(void)
-{
- int i, r = 0;
-
-
- init_test_data_u8();
- r = do_reads();
- if (r) {
- return r;
- }
-
- for (i = 0; i < 8; i++) {
- init_test_data_u16(i);
-
- r = do_reads();
- if (r) {
- return r;
- }
- }
-
- for (i = 0; i < 8; i++) {
- init_test_data_u32(i);
-
- r = do_reads();
- if (r) {
- return r;
- }
- }
-
- ml_printf("Test complete: %s\n", r == 0 ? "PASSED" : "FAILED");
- return r;
-}
diff --git a/tests/tcg/minilib/printf.c b/tests/tcg/minilib/printf.c
index 121620cb16..10472b4f58 100644
--- a/tests/tcg/minilib/printf.c
+++ b/tests/tcg/minilib/printf.c
@@ -119,6 +119,9 @@ void ml_printf(const char *fmt, ...)
str = va_arg(ap, char*);
print_str(str);
break;
+ case 'c':
+ __sys_outc(va_arg(ap, int));
+ break;
case '%':
__sys_outc(*fmt);
break;
diff --git a/tests/tcg/multiarch/system/Makefile.softmmu-target b/tests/tcg/multiarch/system/Makefile.softmmu-target
new file mode 100644
index 0000000000..db4bbeda44
--- /dev/null
+++ b/tests/tcg/multiarch/system/Makefile.softmmu-target
@@ -0,0 +1,14 @@
+# -*- Mode: makefile -*-
+#
+# Multiarch system tests
+#
+# We just collect the tests together here and rely on the actual guest
+# architecture to add to the test dependancies and deal with the
+# complications of building.
+#
+
+MULTIARCH_SYSTEM_SRC=$(SRC_PATH)/tests/tcg/multiarch/system
+VPATH+=$(MULTIARCH_SYSTEM_SRC)
+
+MULTIARCH_TEST_SRCS=$(wildcard $(MULTIARCH_SYSTEM_SRC)/*.c)
+MULTIARCH_TESTS = $(patsubst $(MULTIARCH_SYSTEM_SRC)/%.c, %, $(MULTIARCH_TEST_SRCS))
diff --git a/tests/tcg/i386/system/hello.c b/tests/tcg/multiarch/system/hello.c
index 821dc0ef09..821dc0ef09 100644
--- a/tests/tcg/i386/system/hello.c
+++ b/tests/tcg/multiarch/system/hello.c
diff --git a/tests/tcg/multiarch/system/memory.c b/tests/tcg/multiarch/system/memory.c
new file mode 100644
index 0000000000..dc1d8a98ff
--- /dev/null
+++ b/tests/tcg/multiarch/system/memory.c
@@ -0,0 +1,449 @@
+/*
+ * Memory Test
+ *
+ * This is intended to test the softmmu code and ensure we properly
+ * behave across normal and unaligned accesses across several pages.
+ * We are not replicating memory tests for stuck bits and other
+ * hardware level failures but looking for issues with different size
+ * accesses when access is:
+ *
+ * - unaligned at various sizes (if -DCHECK_UNALIGNED set)
+ * - spanning a (softmmu) page
+ * - sign extension when loading
+ */
+
+#include <inttypes.h>
+#include <stdbool.h>
+#include <minilib.h>
+
+#ifndef CHECK_UNALIGNED
+# error "Target does not specify CHECK_UNALIGNED"
+#endif
+
+#define PAGE_SIZE 4096 /* nominal 4k "pages" */
+#define TEST_SIZE (PAGE_SIZE * 4) /* 4 pages */
+
+#define ARRAY_SIZE(x) ((sizeof(x) / sizeof((x)[0])))
+
+__attribute__((aligned(PAGE_SIZE)))
+static uint8_t test_data[TEST_SIZE];
+
+typedef void (*init_ufn) (int offset);
+typedef bool (*read_ufn) (int offset);
+typedef bool (*read_sfn) (int offset, bool nf);
+
+static void pdot(int count)
+{
+ if (count % 128 == 0) {
+ ml_printf(".");
+ }
+}
+
+/*
+ * Helper macros for shift/extract so we can keep our endian handling
+ * in one place.
+ */
+#define BYTE_SHIFT(b, pos) ((uint64_t)b << (pos * 8))
+#define BYTE_EXTRACT(b, pos) ((b >> (pos * 8)) & 0xff)
+
+/*
+ * Fill the data with ascending value bytes.
+ *
+ * Currently we only support Little Endian machines so write in
+ * ascending address order. When we read higher address bytes should
+ * either be zero or higher than the lower bytes.
+ */
+
+static void init_test_data_u8(int unused_offset)
+{
+ uint8_t count = 0, *ptr = &test_data[0];
+ int i;
+ (void)(unused_offset);
+
+ ml_printf("Filling test area with u8:");
+ for (i = 0; i < TEST_SIZE; i++) {
+ *ptr++ = count++;
+ pdot(i);
+ }
+ ml_printf("done\n");
+}
+
+/*
+ * Full the data with alternating positive and negative bytes. This
+ * should mean for reads larger than a byte all subsequent reads will
+ * stay either negative or positive. We never write 0.
+ */
+
+static inline uint8_t get_byte(int index, bool neg)
+{
+ return neg ? (0xff << (index % 7)) : (0xff >> ((index % 6) + 1));
+}
+
+static void init_test_data_s8(bool neg_first)
+{
+ uint8_t top, bottom, *ptr = &test_data[0];
+ int i;
+
+ ml_printf("Filling test area with s8 pairs (%s):",
+ neg_first ? "neg first" : "pos first");
+ for (i = 0; i < TEST_SIZE / 2; i++) {
+ *ptr++ = get_byte(i, neg_first);
+ *ptr++ = get_byte(i, !neg_first);
+ pdot(i);
+ }
+ ml_printf("done\n");
+}
+
+/*
+ * Zero the first few bytes of the test data in preparation for
+ * new offset values.
+ */
+static void reset_start_data(int offset)
+{
+ uint32_t *ptr = (uint32_t *) &test_data[0];
+ int i;
+ for (i = 0; i < offset; i++) {
+ *ptr++ = 0;
+ }
+}
+
+static void init_test_data_u16(int offset)
+{
+ uint8_t count = 0;
+ uint16_t word, *ptr = (uint16_t *) &test_data[offset];
+ const int max = (TEST_SIZE - offset) / sizeof(word);
+ int i;
+
+ ml_printf("Filling test area with u16 (offset %d, %p):", offset, ptr);
+
+ reset_start_data(offset);
+
+ for (i = 0; i < max; i++) {
+ uint8_t low = count++, high = count++;
+ word = BYTE_SHIFT(high, 1) | BYTE_SHIFT(low, 0);
+ *ptr++ = word;
+ pdot(i);
+ }
+ ml_printf("done @ %p\n", ptr);
+}
+
+static void init_test_data_u32(int offset)
+{
+ uint8_t count = 0;
+ uint32_t word, *ptr = (uint32_t *) &test_data[offset];
+ const int max = (TEST_SIZE - offset) / sizeof(word);
+ int i;
+
+ ml_printf("Filling test area with u32 (offset %d, %p):", offset, ptr);
+
+ reset_start_data(offset);
+
+ for (i = 0; i < max; i++) {
+ uint8_t b4 = count++, b3 = count++;
+ uint8_t b2 = count++, b1 = count++;
+ word = BYTE_SHIFT(b1, 3) | BYTE_SHIFT(b2, 2) | BYTE_SHIFT(b3, 1) | b4;
+ *ptr++ = word;
+ pdot(i);
+ }
+ ml_printf("done @ %p\n", ptr);
+}
+
+static void init_test_data_u64(int offset)
+{
+ uint8_t count = 0;
+ uint64_t word, *ptr = (uint64_t *) &test_data[offset];
+ const int max = (TEST_SIZE - offset) / sizeof(word);
+ int i;
+
+ ml_printf("Filling test area with u64 (offset %d, %p):", offset, ptr);
+
+ reset_start_data(offset);
+
+ for (i = 0; i < max; i++) {
+ uint8_t b8 = count++, b7 = count++;
+ uint8_t b6 = count++, b5 = count++;
+ uint8_t b4 = count++, b3 = count++;
+ uint8_t b2 = count++, b1 = count++;
+ word = BYTE_SHIFT(b1, 7) | BYTE_SHIFT(b2, 6) | BYTE_SHIFT(b3, 5) |
+ BYTE_SHIFT(b4, 4) | BYTE_SHIFT(b5, 3) | BYTE_SHIFT(b6, 2) |
+ BYTE_SHIFT(b7, 1) | b8;
+ *ptr++ = word;
+ pdot(i);
+ }
+ ml_printf("done @ %p\n", ptr);
+}
+
+static bool read_test_data_u16(int offset)
+{
+ uint16_t word, *ptr = (uint16_t *)&test_data[offset];
+ int i;
+ const int max = (TEST_SIZE - offset) / sizeof(word);
+
+ ml_printf("Reading u16 from %#lx (offset %d):", ptr, offset);
+
+ for (i = 0; i < max; i++) {
+ uint8_t high, low;
+ word = *ptr++;
+ high = (word >> 8) & 0xff;
+ low = word & 0xff;
+ if (high < low && high != 0) {
+ ml_printf("Error %d < %d\n", high, low);
+ return false;
+ } else {
+ pdot(i);
+ }
+
+ }
+ ml_printf("done @ %p\n", ptr);
+ return true;
+}
+
+static bool read_test_data_u32(int offset)
+{
+ uint32_t word, *ptr = (uint32_t *)&test_data[offset];
+ int i;
+ const int max = (TEST_SIZE - offset) / sizeof(word);
+
+ ml_printf("Reading u32 from %#lx (offset %d):", ptr, offset);
+
+ for (i = 0; i < max; i++) {
+ uint8_t b1, b2, b3, b4;
+ word = *ptr++;
+
+ b1 = word >> 24 & 0xff;
+ b2 = word >> 16 & 0xff;
+ b3 = word >> 8 & 0xff;
+ b4 = word & 0xff;
+
+ if ((b1 < b2 && b1 != 0) ||
+ (b2 < b3 && b2 != 0) ||
+ (b3 < b4 && b3 != 0)) {
+ ml_printf("Error %d, %d, %d, %d", b1, b2, b3, b4);
+ return false;
+ } else {
+ pdot(i);
+ }
+ }
+ ml_printf("done @ %p\n", ptr);
+ return true;
+}
+
+static bool read_test_data_u64(int offset)
+{
+ uint64_t word, *ptr = (uint64_t *)&test_data[offset];
+ int i;
+ const int max = (TEST_SIZE - offset) / sizeof(word);
+
+ ml_printf("Reading u64 from %#lx (offset %d):", ptr, offset);
+
+ for (i = 0; i < max; i++) {
+ uint8_t b1, b2, b3, b4, b5, b6, b7, b8;
+ word = *ptr++;
+
+ b1 = ((uint64_t) (word >> 56)) & 0xff;
+ b2 = ((uint64_t) (word >> 48)) & 0xff;
+ b3 = ((uint64_t) (word >> 40)) & 0xff;
+ b4 = (word >> 32) & 0xff;
+ b5 = (word >> 24) & 0xff;
+ b6 = (word >> 16) & 0xff;
+ b7 = (word >> 8) & 0xff;
+ b8 = (word >> 0) & 0xff;
+
+ if ((b1 < b2 && b1 != 0) ||
+ (b2 < b3 && b2 != 0) ||
+ (b3 < b4 && b3 != 0) ||
+ (b4 < b5 && b4 != 0) ||
+ (b5 < b6 && b5 != 0) ||
+ (b6 < b7 && b6 != 0) ||
+ (b7 < b8 && b7 != 0)) {
+ ml_printf("Error %d, %d, %d, %d, %d, %d, %d, %d",
+ b1, b2, b3, b4, b5, b6, b7, b8);
+ return false;
+ } else {
+ pdot(i);
+ }
+ }
+ ml_printf("done @ %p\n", ptr);
+ return true;
+}
+
+/* Read the test data and verify at various offsets */
+read_ufn read_ufns[] = { read_test_data_u16,
+ read_test_data_u32,
+ read_test_data_u64 };
+
+bool do_unsigned_reads(void)
+{
+ int i;
+ bool ok = true;
+
+ for (i = 0; i < ARRAY_SIZE(read_ufns) && ok; i++) {
+#if CHECK_UNALIGNED
+ int off;
+ for (off = 0; off < 8 && ok; off++) {
+ ok = read_ufns[i](off);
+ }
+#else
+ ok = read_ufns[i](0);
+#endif
+ }
+
+ return ok;
+}
+
+static bool do_unsigned_test(init_ufn fn)
+{
+#if CHECK_UNALIGNED
+ bool ok = true;
+ int i;
+ for (i = 0; i < 8 && ok; i++) {
+ fn(i);
+ ok = do_unsigned_reads();
+ }
+#else
+ fn(0);
+ return do_unsigned_reads();
+#endif
+}
+
+/*
+ * We need to ensure signed data is read into a larger data type to
+ * ensure that sign extension is working properly.
+ */
+
+static bool read_test_data_s8(int offset, bool neg_first)
+{
+ int8_t *ptr = (int8_t *)&test_data[offset];
+ int i;
+ const int max = (TEST_SIZE - offset) / 2;
+
+ ml_printf("Reading s8 pairs from %#lx (offset %d):", ptr, offset);
+
+ for (i = 0; i < max; i++) {
+ int16_t first, second;
+ bool ok;
+ first = *ptr++;
+ second = *ptr++;
+
+ if (neg_first && first < 0 && second > 0) {
+ pdot(i);
+ } else if (!neg_first && first > 0 && second < 0) {
+ pdot(i);
+ } else {
+ ml_printf("Error %d %c %d\n", first, neg_first ? '<' : '>', second);
+ return false;
+ }
+ }
+ ml_printf("done @ %p\n", ptr);
+ return true;
+}
+
+static bool read_test_data_s16(int offset, bool neg_first)
+{
+ int16_t *ptr = (int16_t *)&test_data[offset];
+ int i;
+ const int max = (TEST_SIZE - offset) / (sizeof(*ptr));
+
+ ml_printf("Reading s16 from %#lx (offset %d, %s):", ptr,
+ offset, neg_first ? "neg" : "pos");
+
+ for (i = 0; i < max; i++) {
+ int32_t data = *ptr++;
+
+ if (neg_first && data < 0) {
+ pdot(i);
+ } else if (data > 0) {
+ pdot(i);
+ } else {
+ ml_printf("Error %d %c 0\n", data, neg_first ? '<' : '>');
+ return false;
+ }
+ }
+ ml_printf("done @ %p\n", ptr);
+ return true;
+}
+
+static bool read_test_data_s32(int offset, bool neg_first)
+{
+ int32_t *ptr = (int32_t *)&test_data[offset];
+ int i;
+ const int max = (TEST_SIZE - offset) / (sizeof(int32_t));
+
+ ml_printf("Reading s32 from %#lx (offset %d, %s):",
+ ptr, offset, neg_first ? "neg" : "pos");
+
+ for (i = 0; i < max; i++) {
+ int64_t data = *ptr++;
+
+ if (neg_first && data < 0) {
+ pdot(i);
+ } else if (data > 0) {
+ pdot(i);
+ } else {
+ ml_printf("Error %d %c 0\n", data, neg_first ? '<' : '>');
+ return false;
+ }
+ }
+ ml_printf("done @ %p\n", ptr);
+ return true;
+}
+
+/*
+ * Read the test data and verify at various offsets
+ *
+ * For everything except bytes all our reads should be either positive
+ * or negative depending on what offset we are reading from. Currently
+ * we only handle LE systems.
+ */
+read_sfn read_sfns[] = { read_test_data_s8,
+ read_test_data_s16,
+ read_test_data_s32 };
+
+bool do_signed_reads(bool neg_first)
+{
+ int i;
+ bool ok = true;
+
+ for (i = 0; i < ARRAY_SIZE(read_sfns) && ok; i++) {
+#if CHECK_UNALIGNED
+ int off;
+ for (off = 0; off < 8 && ok; off++) {
+ bool nf = i == 0 ? neg_first ^ (off & 1) : !(neg_first ^ (off & 1));
+ ok = read_sfns[i](off, nf);
+ }
+#else
+ ok = read_sfns[i](0, i == 0 ? neg_first : !neg_first);
+#endif
+ }
+
+ return ok;
+}
+
+init_ufn init_ufns[] = { init_test_data_u8,
+ init_test_data_u16,
+ init_test_data_u32,
+ init_test_data_u64 };
+
+int main(void)
+{
+ int i;
+ bool ok = true;
+
+ /* Run through the unsigned tests first */
+ for (i = 0; i < ARRAY_SIZE(init_ufns) && ok; i++) {
+ ok = do_unsigned_test(init_ufns[i]);
+ }
+
+ if (ok) {
+ init_test_data_s8(false);
+ ok = do_signed_reads(false);
+ }
+
+ if (ok) {
+ init_test_data_s8(true);
+ ok = do_signed_reads(true);
+ }
+
+ ml_printf("Test complete: %s\n", ok ? "PASSED" : "FAILED");
+ return ok ? 0 : -1;
+}