diff options
628 files changed, 28888 insertions, 4083 deletions
diff --git a/.editorconfig b/.editorconfig index 1582883393..df6db65531 100644 --- a/.editorconfig +++ b/.editorconfig @@ -26,6 +26,11 @@ file_type_emacs = makefile indent_style = space indent_size = 4 +[*.{s,S}] +indent_style = tab +indent_size = 8 +file_type_emacs = asm + [*.{vert,frag}] file_type_emacs = glsl diff --git a/.patchew.yml b/.patchew.yml new file mode 100644 index 0000000000..988c29261f --- /dev/null +++ b/.patchew.yml @@ -0,0 +1,302 @@ +--- +# Note: this file is still unused. It serves as a documentation for the +# Patchew configuration in case patchew.org disappears or has to be +# reinstalled. +# +# Patchew configuration is available to project administrators at +# https://patchew.org/api/v1/projects/1/config/ and can be configured +# to YAML using the following Python script: +# +# import json +# import sys +# import ruamel.yaml +# +# json_str = sys.stdin.read() +# yaml = ruamel.yaml.YAML() +# yaml.explicit_start = True +# data = json.loads(json_str, object_pairs_hook=ruamel.yaml.comments.CommentedMap) +# ruamel.yaml.scalarstring.walk_tree(data) +# yaml.dump(data, sys.stdout) + +email: + notifications: + timeouts: + event: TestingReport + enabled: true + to_user: false + reply_subject: true + set_reply_to: true + in_reply_to: true + reply_to_all: false + subject_template: none + to: fam@euphon.net + cc: '' + body_template: | + {% if not is_timeout %} {{ cancel }} {% endif %} + + Test '{{ test }}' timeout, log: + + {{ log }} + ENOSPC: + event: TestingReport + enabled: true + to_user: false + reply_subject: false + set_reply_to: false + in_reply_to: true + reply_to_all: false + subject_template: Out of space error + to: fam@euphon.net + cc: '' + body_template: | + {% if passed %} + {{ cancel }} + {% endif %} + + {% if 'No space left on device' in log %} + Tester {{ tester }} out of space when running {{ test }} + + {{ log }} + {% else %} + {{ cancel }} + {% endif %} + FailureShort: + event: TestingReport + enabled: true + to_user: false + reply_subject: true + set_reply_to: true + in_reply_to: true + reply_to_all: true + subject_template: Testing failed + to: '' + cc: '' + body_template: | + {% if passed or not obj.message_id or is_timeout %} + {{ cancel }} + {% endif %} + {% if 'No space left on device' in log %} + {{ cancel }} + {% endif %} + Patchew URL: https://patchew.org/QEMU/{{ obj.message_id }}/ + + {% ansi2text log as logtext %} + {% if test == "checkpatch" %} + Hi, + + This series seems to have some coding style problems. See output below for + more information: + + {{ logtext }} + {% elif test == "docker-mingw@fedora" or test == "docker-quick@centos7" or test == "asan" %} + Hi, + + This series failed the {{ test }} build test. Please find the testing commands and + their output below. If you have Docker installed, you can probably reproduce it + locally. + + {% lines_between logtext start="^=== TEST SCRIPT BEGIN ===$" stop="^=== TEST SCRIPT END ===$" %} + {% lines_between logtext start="^=== OUTPUT BEGIN ===$" stop="=== OUTPUT END ===$" as output %} + {% grep_C output regex="\b(FAIL|XPASS|ERROR|WARN|error:|warning:)" n=3 %} + {% elif test == "s390x" or test == "FreeBSD" or test == "ppcle" or test == "ppcbe" %} + Hi, + + This series failed build test on {{test}} host. Please find the details below. + + {% lines_between logtext start="^=== TEST SCRIPT BEGIN ===$" stop="^=== TEST SCRIPT END ===$" %} + {% lines_between logtext start="^=== OUTPUT BEGIN ===$" stop="=== OUTPUT END ===$" as output %} + {% grep_C output regex="\b(FAIL|XPASS|ERROR|WARN|error:|warning:)" n=3 %} + {% else %} + {{ cancel }} + {% endif %} + + The full log is available at + {{ log_url }}. + --- + Email generated automatically by Patchew [https://patchew.org/]. + Please send your feedback to patchew-devel@redhat.com +testing: + tests: + asan: + enabled: true + requirements: docker + timeout: 3600 + script: | + #!/bin/bash + time make docker-test-debug@fedora TARGET_LIST=x86_64-softmmu J=14 NETWORK=1 + docker-quick@centos7: + enabled: false + requirements: docker,x86_64 + timeout: 3600 + script: | + #!/bin/bash + time make docker-test-quick@centos7 SHOW_ENV=1 J=14 NETWORK=1 + checkpatch: + enabled: true + requirements: '' + timeout: 600 + script: | + #!/bin/bash + git rev-parse base > /dev/null || exit 0 + git config --local diff.renamelimit 0 + git config --local diff.renames True + git config --local diff.algorithm histogram + ./scripts/checkpatch.pl --mailback base.. + docker-mingw@fedora: + enabled: true + requirements: docker,x86_64 + timeout: 3600 + script: | + #! /bin/bash + test "$(uname -m)" = "x86_64" + ppcle: + enabled: false + requirements: ppcle + timeout: 3600 + script: | + #!/bin/bash + # Testing script will be invoked under the git checkout with + # HEAD pointing to a commit that has the patches applied on top of "base" + # branch + set -e + CC=$HOME/bin/cc + INSTALL=$PWD/install + BUILD=$PWD/build + mkdir -p $BUILD $INSTALL + SRC=$PWD + cd $BUILD + $SRC/configure --cc=$CC --prefix=$INSTALL + make -j4 + # XXX: we need reliable clean up + # make check -j4 V=1 + make install + + echo + echo "=== ENV ===" + env + + echo + echo "=== PACKAGES ===" + rpm -qa + ppcbe: + enabled: false + requirements: ppcbe + timeout: 3600 + script: | + #!/bin/bash + # Testing script will be invoked under the git checkout with + # HEAD pointing to a commit that has the patches applied on top of "base" + # branch + set -e + CC=$HOME/bin/cc + INSTALL=$PWD/install + BUILD=$PWD/build + mkdir -p $BUILD $INSTALL + SRC=$PWD + cd $BUILD + $SRC/configure --cc=$CC --prefix=$INSTALL + make -j4 + # XXX: we need reliable clean up + # make check -j4 V=1 + make install + + echo + echo "=== ENV ===" + env + + echo + echo "=== PACKAGES ===" + rpm -qa + FreeBSD: + enabled: true + requirements: qemu-x86,x86_64,git + timeout: 3600 + script: | + #!/bin/bash + # Testing script will be invoked under the git checkout with + # HEAD pointing to a commit that has the patches applied on top of "base" + # branch + if qemu-system-x86_64 --help >/dev/null 2>&1; then + QEMU=qemu-system-x86_64 + elif /usr/libexec/qemu-kvm --help >/dev/null 2>&1; then + QEMU=/usr/libexec/qemu-kvm + else + exit 1 + fi + make vm-build-freebsd J=21 QEMU=$QEMU + exit 0 + docker-clang@ubuntu: + enabled: true + requirements: docker,x86_64 + timeout: 3600 + script: | + #!/bin/bash + time make docker-test-clang@ubuntu SHOW_ENV=1 J=14 NETWORK=1 + s390x: + enabled: true + requirements: s390x + timeout: 3600 + script: | + #!/bin/bash + # Testing script will be invoked under the git checkout with + # HEAD pointing to a commit that has the patches applied on top of "base" + # branch + set -e + CC=$HOME/bin/cc + INSTALL=$PWD/install + BUILD=$PWD/build + mkdir -p $BUILD $INSTALL + SRC=$PWD + cd $BUILD + $SRC/configure --cc=$CC --prefix=$INSTALL + make -j4 + # XXX: we need reliable clean up + # make check -j4 V=1 + make install + + echo + echo "=== ENV ===" + env + + echo + echo "=== PACKAGES ===" + rpm -qa + requirements: + x86_64: + script: | + #! /bin/bash + test "$(uname -m)" = "x86_64" + qemu-x86: + script: | + #!/bin/bash + if qemu-system-x86_64 --help >/dev/null 2>&1; then + : + elif /usr/libexec/qemu-kvm --help >/dev/null 2>&1; then + : + else + exit 1 + fi + ppcle: + script: | + #!/bin/bash + test "$(uname -m)" = "ppc64le" + ppcbe: + script: | + #!/bin/bash + test "$(uname -m)" = "ppc64" + git: + script: | + #! /bin/bash + git config user.name > /dev/null 2>&1 + docker: + script: | + #!/bin/bash + docker ps || sudo -n docker ps + s390x: + script: | + #!/bin/bash + test "$(uname -m)" = "s390x" +git: + push_to: git@github.com:patchew-project/qemu + public_repo: https://github.com/patchew-project/qemu + url_template: https://github.com/patchew-project/qemu/tree/%t diff --git a/.travis.yml b/.travis.yml index 6fd89b3d91..b053a836a3 100644 --- a/.travis.yml +++ b/.travis.yml @@ -284,5 +284,5 @@ matrix: # Run check-tcg against softmmu targets - env: - - CONFIG="--target-list=xtensa-softmmu,arm-softmmu" + - CONFIG="--target-list=xtensa-softmmu,arm-softmmu,aarch64-softmmu,alpha-softmmu" - TEST_CMD="make -j3 check-tcg V=1" diff --git a/MAINTAINERS b/MAINTAINERS index 3cacd751bf..7be1225415 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -102,6 +102,7 @@ F: pc-bios/s390-ccw/ F: pc-bios/s390-ccw.img F: target/s390x/ F: docs/vfio-ap.txt +F: tests/migration/s390x/ K: ^Subject:.*(?i)s390x? T: git https://github.com/cohuck/qemu.git s390-next L: qemu-s390x@nongnu.org @@ -470,6 +471,7 @@ M: Richard Henderson <rth@twiddle.net> S: Maintained F: hw/alpha/ F: hw/isa/smc37c669-superio.c +F: tests/tcg/alpha/system/ ARM Machines ------------ @@ -934,6 +936,7 @@ M: Aurelien Jarno <aurelien@aurel32.net> R: Aleksandar Rikalo <arikalo@wavecomp.com> S: Maintained F: hw/mips/mips_malta.c +F: tests/acceptance/linux_ssh_mips_malta.py Mipssim M: Aleksandar Markovic <amarkovic@wavecomp.com> @@ -1673,9 +1676,17 @@ virtio-gpu M: Gerd Hoffmann <kraxel@redhat.com> S: Maintained F: hw/display/virtio-gpu* -F: hw/display/virtio-vga.c +F: hw/display/virtio-vga.* F: include/hw/virtio/virtio-gpu.h +vhost-user-gpu +M: Marc-André Lureau <marcandre.lureau@redhat.com> +M: Gerd Hoffmann <kraxel@redhat.com> +S: Maintained +F: docs/interop/vhost-user-gpu.rst +F: contrib/vhost-user-gpu +F: hw/display/vhost-user-* + Cirrus VGA M: Gerd Hoffmann <kraxel@redhat.com> S: Odd Fixes @@ -1710,6 +1721,7 @@ L: qemu-ppc@nongnu.org S: Supported F: hw/*/*xive* F: include/hw/*/*xive* +F: docs/*/*xive* Subsystems ---------- @@ -2562,6 +2574,13 @@ F: docs/pvrdma.txt F: contrib/rdmacm-mux/* F: qapi/rdma.json +Semihosting +M: Alex Bennée <alex.bennee@linaro.org> +L: qemu-devel@nongnu.org +S: Maintained +F: hw/semihosting/ +F: include/hw/semihosting/ + Build and test automation ------------------------- Build and test automation @@ -314,8 +314,20 @@ $(call set-vpath, $(SRC_PATH)) LIBS+=-lz $(LIBS_TOOLS) +vhost-user-json-y = +HELPERS-y = + HELPERS-$(call land,$(CONFIG_SOFTMMU),$(CONFIG_LINUX)) = qemu-bridge-helper$(EXESUF) +ifdef CONFIG_LINUX +ifdef CONFIG_VIRGL +ifdef CONFIG_GBM +HELPERS-y += vhost-user-gpu$(EXESUF) +vhost-user-json-y += contrib/vhost-user-gpu/50-qemu-gpu.json +endif +endif +endif + ifdef BUILD_DOCS DOCS=qemu-doc.html qemu-doc.txt qemu.1 qemu-img.1 qemu-nbd.8 qemu-ga.8 DOCS+=docs/interop/qemu-qmp-ref.html docs/interop/qemu-qmp-ref.txt docs/interop/qemu-qmp-ref.7 @@ -409,6 +421,7 @@ dummy := $(call unnest-vars,, \ vhost-user-scsi-obj-y \ vhost-user-blk-obj-y \ vhost-user-input-obj-y \ + vhost-user-gpu-obj-y \ qga-vss-dll-obj-y \ block-obj-y \ block-obj-m \ @@ -426,7 +439,7 @@ dummy := $(call unnest-vars,, \ include $(SRC_PATH)/tests/Makefile.include -all: $(DOCS) $(if $(BUILD_DOCS),sphinxdocs) $(TOOLS) $(HELPERS-y) recurse-all modules +all: $(DOCS) $(if $(BUILD_DOCS),sphinxdocs) $(TOOLS) $(HELPERS-y) recurse-all modules $(vhost-user-json-y) qemu-version.h: FORCE $(call quiet-command, \ @@ -619,6 +632,9 @@ rdmacm-mux$(EXESUF): LIBS += "-libumad" rdmacm-mux$(EXESUF): $(rdmacm-mux-obj-y) $(COMMON_LDADDS) $(call LINK, $^) +vhost-user-gpu$(EXESUF): $(vhost-user-gpu-obj-y) $(libvhost-user-obj-y) libqemuutil.a libqemustub.a + $(call LINK, $^) + ifdef CONFIG_VHOST_USER_INPUT ifdef CONFIG_LINUX vhost-user-input$(EXESUF): $(vhost-user-input-obj-y) libvhost-user.a libqemuutil.a @@ -827,6 +843,12 @@ endif ifneq ($(HELPERS-y),) $(call install-prog,$(HELPERS-y),$(DESTDIR)$(libexecdir)) endif +ifneq ($(vhost-user-json-y),) + $(INSTALL_DIR) "$(DESTDIR)$(qemu_datadir)/vhost-user/" + for x in $(vhost-user-json-y); do \ + $(INSTALL_DATA) $$x "$(DESTDIR)$(qemu_datadir)/vhost-user/"; \ + done +endif ifdef CONFIG_TRACE_SYSTEMTAP $(INSTALL_PROG) "scripts/qemu-trace-stap" $(DESTDIR)$(bindir) endif @@ -1009,7 +1031,9 @@ $(filter %.1 %.7 %.8,$(DOCS)): scripts/texi2pod.pl %/coverage-report.html: @mkdir -p $* $(call quiet-command,\ - gcovr -r $(SRC_PATH) --object-directory $(BUILD_PATH) \ + gcovr -r $(SRC_PATH) \ + $(foreach t, $(TARGET_DIRS), --object-directory $(BUILD_DIR)/$(t)) \ + --object-directory $(BUILD_DIR) \ -p --html --html-details -o $@, \ "GEN", "coverage-report.html") diff --git a/Makefile.objs b/Makefile.objs index d7491413c1..c8337fa34b 100644 --- a/Makefile.objs +++ b/Makefile.objs @@ -123,6 +123,7 @@ vhost-user-scsi-obj-y = contrib/vhost-user-scsi/ vhost-user-blk-obj-y = contrib/vhost-user-blk/ rdmacm-mux-obj-y = contrib/rdmacm-mux/ vhost-user-input-obj-y = contrib/vhost-user-input/ +vhost-user-gpu-obj-y = contrib/vhost-user-gpu/ ###################################################################### trace-events-subdirs = @@ -182,6 +183,7 @@ trace-events-subdirs += hw/virtio trace-events-subdirs += hw/watchdog trace-events-subdirs += hw/xen trace-events-subdirs += hw/gpio +trace-events-subdirs += hw/riscv trace-events-subdirs += migration trace-events-subdirs += net trace-events-subdirs += ui diff --git a/Makefile.target b/Makefile.target index 4ef4ce5996..ecd856e3a3 100644 --- a/Makefile.target +++ b/Makefile.target @@ -238,3 +238,19 @@ endif generated-files-y += config-target.h Makefile: $(generated-files-y) + +# Reports/Analysis +# +# The target specific coverage report only cares about target specific +# blobs and not the shared code. +# + +%/coverage-report.html: + @mkdir -p $* + $(call quiet-command,\ + gcovr -r $(SRC_PATH) --object-directory $(CURDIR) \ + -p --html --html-details -o $@, \ + "GEN", "coverage-report.html") + +.PHONY: coverage-report +coverage-report: $(CURDIR)/reports/coverage/coverage-report.html @@ -2235,6 +2235,10 @@ static void bdrv_replace_child(BdrvChild *child, BlockDriverState *new_bs) bdrv_get_cumulative_perm(old_bs, &perm, &shared_perm); bdrv_check_perm(old_bs, NULL, perm, shared_perm, NULL, &error_abort); bdrv_set_perm(old_bs, perm, shared_perm); + + /* When the parent requiring a non-default AioContext is removed, the + * node moves back to the main AioContext */ + bdrv_try_set_aio_context(old_bs, qemu_get_aio_context(), NULL); } if (new_bs) { @@ -2243,18 +2247,31 @@ static void bdrv_replace_child(BdrvChild *child, BlockDriverState *new_bs) } } +/* + * This function steals the reference to child_bs from the caller. + * That reference is later dropped by bdrv_root_unref_child(). + * + * On failure NULL is returned, errp is set and the reference to + * child_bs is also dropped. + * + * The caller must hold the AioContext lock @child_bs, but not that of @ctx + * (unless @child_bs is already in @ctx). + */ BdrvChild *bdrv_root_attach_child(BlockDriverState *child_bs, const char *child_name, const BdrvChildRole *child_role, + AioContext *ctx, uint64_t perm, uint64_t shared_perm, void *opaque, Error **errp) { BdrvChild *child; + Error *local_err = NULL; int ret; ret = bdrv_check_update_perm(child_bs, NULL, perm, shared_perm, NULL, errp); if (ret < 0) { bdrv_abort_perm_update(child_bs); + bdrv_unref(child_bs); return NULL; } @@ -2268,12 +2285,48 @@ BdrvChild *bdrv_root_attach_child(BlockDriverState *child_bs, .opaque = opaque, }; + /* If the AioContexts don't match, first try to move the subtree of + * child_bs into the AioContext of the new parent. If this doesn't work, + * try moving the parent into the AioContext of child_bs instead. */ + if (bdrv_get_aio_context(child_bs) != ctx) { + ret = bdrv_try_set_aio_context(child_bs, ctx, &local_err); + if (ret < 0 && child_role->can_set_aio_ctx) { + GSList *ignore = g_slist_prepend(NULL, child);; + ctx = bdrv_get_aio_context(child_bs); + if (child_role->can_set_aio_ctx(child, ctx, &ignore, NULL)) { + error_free(local_err); + ret = 0; + g_slist_free(ignore); + ignore = g_slist_prepend(NULL, child);; + child_role->set_aio_ctx(child, ctx, &ignore); + } + g_slist_free(ignore); + } + if (ret < 0) { + error_propagate(errp, local_err); + g_free(child); + bdrv_abort_perm_update(child_bs); + return NULL; + } + } + /* This performs the matching bdrv_set_perm() for the above check. */ bdrv_replace_child(child, child_bs); return child; } +/* + * This function transfers the reference to child_bs from the caller + * to parent_bs. That reference is later dropped by parent_bs on + * bdrv_close() or if someone calls bdrv_unref_child(). + * + * On failure NULL is returned, errp is set and the reference to + * child_bs is also dropped. + * + * If @parent_bs and @child_bs are in different AioContexts, the caller must + * hold the AioContext lock for @child_bs, but not for @parent_bs. + */ BdrvChild *bdrv_attach_child(BlockDriverState *parent_bs, BlockDriverState *child_bs, const char *child_name, @@ -2286,11 +2339,11 @@ BdrvChild *bdrv_attach_child(BlockDriverState *parent_bs, bdrv_get_cumulative_perm(parent_bs, &perm, &shared_perm); assert(parent_bs->drv); - assert(bdrv_get_aio_context(parent_bs) == bdrv_get_aio_context(child_bs)); bdrv_child_perm(parent_bs, child_bs, NULL, child_role, NULL, perm, shared_perm, &perm, &shared_perm); child = bdrv_root_attach_child(child_bs, child_name, child_role, + bdrv_get_aio_context(parent_bs), perm, shared_perm, parent_bs, errp); if (child == NULL) { return NULL; @@ -2401,12 +2454,9 @@ void bdrv_set_backing_hd(BlockDriverState *bs, BlockDriverState *backing_hd, /* If backing_hd was already part of bs's backing chain, and * inherits_from pointed recursively to bs then let's update it to * point directly to bs (else it will become NULL). */ - if (update_inherits_from) { + if (bs->backing && update_inherits_from) { backing_hd->inherits_from = bs; } - if (!bs->backing) { - bdrv_unref(backing_hd); - } out: bdrv_refresh_limits(bs, NULL); @@ -2504,7 +2554,6 @@ int bdrv_open_backing_file(BlockDriverState *bs, QDict *parent_options, ret = -EINVAL; goto free_exit; } - bdrv_set_aio_context(backing_hd, bdrv_get_aio_context(bs)); if (implicit_backing) { bdrv_refresh_filename(backing_hd); @@ -2594,7 +2643,6 @@ BdrvChild *bdrv_open_child(const char *filename, const BdrvChildRole *child_role, bool allow_none, Error **errp) { - BdrvChild *c; BlockDriverState *bs; bs = bdrv_open_child_bs(filename, options, bdref_key, parent, child_role, @@ -2603,13 +2651,7 @@ BdrvChild *bdrv_open_child(const char *filename, return NULL; } - c = bdrv_attach_child(parent, bs, bdref_key, child_role, errp); - if (!c) { - bdrv_unref(bs); - return NULL; - } - - return c; + return bdrv_attach_child(parent, bs, bdref_key, child_role, errp); } /* TODO Future callers may need to specify parent/child_role in order for @@ -2878,7 +2920,7 @@ static BlockDriverState *bdrv_open_inherit(const char *filename, /* Not requesting BLK_PERM_CONSISTENT_READ because we're only * looking at the header to guess the image format. This works even * in cases where a guest would not see a consistent state. */ - file = blk_new(0, BLK_PERM_ALL); + file = blk_new(bdrv_get_aio_context(file_bs), 0, BLK_PERM_ALL); blk_insert_bs(file, file_bs, &local_err); bdrv_unref(file_bs); if (local_err) { @@ -3877,22 +3919,12 @@ static void bdrv_close(BlockDriverState *bs) bs->drv = NULL; } - bdrv_set_backing_hd(bs, NULL, &error_abort); - - if (bs->file != NULL) { - bdrv_unref_child(bs, bs->file); - bs->file = NULL; - } - QLIST_FOREACH_SAFE(child, &bs->children, next, next) { - /* TODO Remove bdrv_unref() from drivers' close function and use - * bdrv_unref_child() here */ - if (child->bs->inherits_from == bs) { - child->bs->inherits_from = NULL; - } - bdrv_detach_child(child); + bdrv_unref_child(bs, child); } + bs->backing = NULL; + bs->file = NULL; g_free(bs->opaque); bs->opaque = NULL; atomic_set(&bs->copy_on_read, 0); @@ -4021,13 +4053,13 @@ void bdrv_replace_node(BlockDriverState *from, BlockDriverState *to, uint64_t perm = 0, shared = BLK_PERM_ALL; int ret; - assert(!atomic_read(&from->in_flight)); - assert(!atomic_read(&to->in_flight)); - /* Make sure that @from doesn't go away until we have successfully attached * all of its parents to @to. */ bdrv_ref(from); + assert(qemu_get_current_aio_context() == qemu_get_aio_context()); + bdrv_drained_begin(from); + /* Put all parents into @list and calculate their cumulative permissions */ QLIST_FOREACH_SAFE(c, &from->parents, next_parent, next) { assert(c->bs == from); @@ -4068,6 +4100,7 @@ void bdrv_replace_node(BlockDriverState *from, BlockDriverState *to, out: g_slist_free(list); + bdrv_drained_end(from); bdrv_unref(from); } @@ -5756,8 +5789,17 @@ static void bdrv_attach_aio_context(BlockDriverState *bs, bs->walking_aio_notifiers = false; } -/* @ignore will accumulate all visited BdrvChild object. The caller is - * responsible for freeing the list afterwards. */ +/* + * Changes the AioContext used for fd handlers, timers, and BHs by this + * BlockDriverState and all its children and parents. + * + * The caller must own the AioContext lock for the old AioContext of bs, but it + * must not own the AioContext lock for new_context (unless new_context is the + * same as the current context of bs). + * + * @ignore will accumulate all visited BdrvChild object. The caller is + * responsible for freeing the list afterwards. + */ void bdrv_set_aio_context_ignore(BlockDriverState *bs, AioContext *new_context, GSList **ignore) { @@ -5780,10 +5822,9 @@ void bdrv_set_aio_context_ignore(BlockDriverState *bs, if (g_slist_find(*ignore, child)) { continue; } - if (child->role->set_aio_ctx) { - *ignore = g_slist_prepend(*ignore, child); - child->role->set_aio_ctx(child, new_context, ignore); - } + assert(child->role->set_aio_ctx); + *ignore = g_slist_prepend(*ignore, child); + child->role->set_aio_ctx(child, new_context, ignore); } bdrv_detach_aio_context(bs); @@ -5797,16 +5838,6 @@ void bdrv_set_aio_context_ignore(BlockDriverState *bs, aio_context_release(new_context); } -/* The caller must own the AioContext lock for the old AioContext of bs, but it - * must not own the AioContext lock for new_context (unless new_context is - * the same as the current context of bs). */ -void bdrv_set_aio_context(BlockDriverState *bs, AioContext *new_context) -{ - GSList *ignore_list = NULL; - bdrv_set_aio_context_ignore(bs, new_context, &ignore_list); - g_slist_free(ignore_list); -} - static bool bdrv_parent_can_set_aio_context(BdrvChild *c, AioContext *ctx, GSList **ignore, Error **errp) { diff --git a/block/Makefile.objs b/block/Makefile.objs index 7a81892a52..ae11605c9f 100644 --- a/block/Makefile.objs +++ b/block/Makefile.objs @@ -6,7 +6,7 @@ block-obj-$(CONFIG_BOCHS) += bochs.o block-obj-$(CONFIG_VVFAT) += vvfat.o block-obj-$(CONFIG_DMG) += dmg.o -block-obj-y += qcow2.o qcow2-refcount.o qcow2-cluster.o qcow2-snapshot.o qcow2-cache.o qcow2-bitmap.o +block-obj-y += qcow2.o qcow2-refcount.o qcow2-cluster.o qcow2-snapshot.o qcow2-cache.o qcow2-bitmap.o qcow2-threads.o block-obj-$(CONFIG_QED) += qed.o qed-l2-cache.o qed-table.o qed-cluster.o block-obj-$(CONFIG_QED) += qed-check.o block-obj-y += vhdx.o vhdx-endian.o vhdx-log.o diff --git a/block/backup.c b/block/backup.c index 916817d8b1..715e1d3be8 100644 --- a/block/backup.c +++ b/block/backup.c @@ -112,7 +112,8 @@ static int coroutine_fn backup_cow_with_bounce_buffer(BackupBlockJob *job, int read_flags = is_write_notifier ? BDRV_REQ_NO_SERIALISING : 0; int write_flags = job->serialize_target_writes ? BDRV_REQ_SERIALISING : 0; - hbitmap_reset(job->copy_bitmap, start / job->cluster_size, 1); + assert(QEMU_IS_ALIGNED(start, job->cluster_size)); + hbitmap_reset(job->copy_bitmap, start, job->cluster_size); nbytes = MIN(job->cluster_size, job->len - start); if (!*bounce_buffer) { *bounce_buffer = blk_blockalign(blk, job->cluster_size); @@ -145,7 +146,7 @@ static int coroutine_fn backup_cow_with_bounce_buffer(BackupBlockJob *job, return nbytes; fail: - hbitmap_set(job->copy_bitmap, start / job->cluster_size, 1); + hbitmap_set(job->copy_bitmap, start, job->cluster_size); return ret; } @@ -165,16 +166,15 @@ static int coroutine_fn backup_cow_with_offload(BackupBlockJob *job, int write_flags = job->serialize_target_writes ? BDRV_REQ_SERIALISING : 0; assert(QEMU_IS_ALIGNED(job->copy_range_size, job->cluster_size)); + assert(QEMU_IS_ALIGNED(start, job->cluster_size)); nbytes = MIN(job->copy_range_size, end - start); nr_clusters = DIV_ROUND_UP(nbytes, job->cluster_size); - hbitmap_reset(job->copy_bitmap, start / job->cluster_size, - nr_clusters); + hbitmap_reset(job->copy_bitmap, start, job->cluster_size * nr_clusters); ret = blk_co_copy_range(blk, start, job->target, start, nbytes, read_flags, write_flags); if (ret < 0) { trace_backup_do_cow_copy_range_fail(job, start, ret); - hbitmap_set(job->copy_bitmap, start / job->cluster_size, - nr_clusters); + hbitmap_set(job->copy_bitmap, start, job->cluster_size * nr_clusters); return ret; } @@ -202,7 +202,7 @@ static int coroutine_fn backup_do_cow(BackupBlockJob *job, cow_request_begin(&cow_request, job, start, end); while (start < end) { - if (!hbitmap_get(job->copy_bitmap, start / job->cluster_size)) { + if (!hbitmap_get(job->copy_bitmap, start)) { trace_backup_do_cow_skip(job, start); start += job->cluster_size; continue; /* already copied */ @@ -298,12 +298,16 @@ static void backup_clean(Job *job) assert(s->target); blk_unref(s->target); s->target = NULL; + + if (s->copy_bitmap) { + hbitmap_free(s->copy_bitmap); + s->copy_bitmap = NULL; + } } void backup_do_checkpoint(BlockJob *job, Error **errp) { BackupBlockJob *backup_job = container_of(job, BackupBlockJob, common); - int64_t len; assert(block_job_driver(job) == &backup_job_driver); @@ -313,8 +317,7 @@ void backup_do_checkpoint(BlockJob *job, Error **errp) return; } - len = DIV_ROUND_UP(backup_job->len, backup_job->cluster_size); - hbitmap_set(backup_job->copy_bitmap, 0, len); + hbitmap_set(backup_job->copy_bitmap, 0, backup_job->len); } static void backup_drain(BlockJob *job) @@ -365,20 +368,44 @@ static bool coroutine_fn yield_and_check(BackupBlockJob *job) return false; } -static int coroutine_fn backup_run_incremental(BackupBlockJob *job) +static bool bdrv_is_unallocated_range(BlockDriverState *bs, + int64_t offset, int64_t bytes) +{ + int64_t end = offset + bytes; + + while (offset < end && !bdrv_is_allocated(bs, offset, bytes, &bytes)) { + if (bytes == 0) { + return true; + } + offset += bytes; + bytes = end - offset; + } + + return offset >= end; +} + +static int coroutine_fn backup_loop(BackupBlockJob *job) { int ret; bool error_is_read; - int64_t cluster; + int64_t offset; HBitmapIter hbi; + BlockDriverState *bs = blk_bs(job->common.blk); hbitmap_iter_init(&hbi, job->copy_bitmap, 0); - while ((cluster = hbitmap_iter_next(&hbi)) != -1) { + while ((offset = hbitmap_iter_next(&hbi)) != -1) { + if (job->sync_mode == MIRROR_SYNC_MODE_TOP && + bdrv_is_unallocated_range(bs, offset, job->cluster_size)) + { + hbitmap_reset(job->copy_bitmap, offset, job->cluster_size); + continue; + } + do { if (yield_and_check(job)) { return 0; } - ret = backup_do_cow(job, cluster * job->cluster_size, + ret = backup_do_cow(job, offset, job->cluster_size, &error_is_read, false); if (ret < 0 && backup_error_action(job, error_is_read, -ret) == BLOCK_ERROR_ACTION_REPORT) @@ -394,66 +421,43 @@ static int coroutine_fn backup_run_incremental(BackupBlockJob *job) /* init copy_bitmap from sync_bitmap */ static void backup_incremental_init_copy_bitmap(BackupBlockJob *job) { - BdrvDirtyBitmapIter *dbi; - int64_t offset; - int64_t end = DIV_ROUND_UP(bdrv_dirty_bitmap_size(job->sync_bitmap), - job->cluster_size); + uint64_t offset = 0; + uint64_t bytes = job->len; - dbi = bdrv_dirty_iter_new(job->sync_bitmap); - while ((offset = bdrv_dirty_iter_next(dbi)) != -1) { - int64_t cluster = offset / job->cluster_size; - int64_t next_cluster; - - offset += bdrv_dirty_bitmap_granularity(job->sync_bitmap); - if (offset >= bdrv_dirty_bitmap_size(job->sync_bitmap)) { - hbitmap_set(job->copy_bitmap, cluster, end - cluster); - break; - } + while (bdrv_dirty_bitmap_next_dirty_area(job->sync_bitmap, + &offset, &bytes)) + { + hbitmap_set(job->copy_bitmap, offset, bytes); - offset = bdrv_dirty_bitmap_next_zero(job->sync_bitmap, offset, - UINT64_MAX); - if (offset == -1) { - hbitmap_set(job->copy_bitmap, cluster, end - cluster); + offset += bytes; + if (offset >= job->len) { break; } - - next_cluster = DIV_ROUND_UP(offset, job->cluster_size); - hbitmap_set(job->copy_bitmap, cluster, next_cluster - cluster); - if (next_cluster >= end) { - break; - } - - bdrv_set_dirty_iter(dbi, next_cluster * job->cluster_size); + bytes = job->len - offset; } /* TODO job_progress_set_remaining() would make more sense */ job_progress_update(&job->common.job, - job->len - hbitmap_count(job->copy_bitmap) * job->cluster_size); - - bdrv_dirty_iter_free(dbi); + job->len - hbitmap_count(job->copy_bitmap)); } static int coroutine_fn backup_run(Job *job, Error **errp) { BackupBlockJob *s = container_of(job, BackupBlockJob, common.job); BlockDriverState *bs = blk_bs(s->common.blk); - int64_t offset, nb_clusters; int ret = 0; QLIST_INIT(&s->inflight_reqs); qemu_co_rwlock_init(&s->flush_rwlock); - nb_clusters = DIV_ROUND_UP(s->len, s->cluster_size); job_progress_set_remaining(job, s->len); - s->copy_bitmap = hbitmap_alloc(nb_clusters, 0); if (s->sync_mode == MIRROR_SYNC_MODE_INCREMENTAL) { backup_incremental_init_copy_bitmap(s); } else { - hbitmap_set(s->copy_bitmap, 0, nb_clusters); + hbitmap_set(s->copy_bitmap, 0, s->len); } - s->before_write.notify = backup_before_write_notify; bdrv_add_before_write_notifier(bs, &s->before_write); @@ -465,68 +469,8 @@ static int coroutine_fn backup_run(Job *job, Error **errp) * notify callback service CoW requests. */ job_yield(job); } - } else if (s->sync_mode == MIRROR_SYNC_MODE_INCREMENTAL) { - ret = backup_run_incremental(s); } else { - /* Both FULL and TOP SYNC_MODE's require copying.. */ - for (offset = 0; offset < s->len; - offset += s->cluster_size) { - bool error_is_read; - int alloced = 0; - - if (yield_and_check(s)) { - break; - } - - if (s->sync_mode == MIRROR_SYNC_MODE_TOP) { - int i; - int64_t n; - - /* Check to see if these blocks are already in the - * backing file. */ - - for (i = 0; i < s->cluster_size;) { - /* bdrv_is_allocated() only returns true/false based - * on the first set of sectors it comes across that - * are are all in the same state. - * For that reason we must verify each sector in the - * backup cluster length. We end up copying more than - * needed but at some point that is always the case. */ - alloced = - bdrv_is_allocated(bs, offset + i, - s->cluster_size - i, &n); - i += n; - - if (alloced || n == 0) { - break; - } - } - - /* If the above loop never found any sectors that are in - * the topmost image, skip this backup. */ - if (alloced == 0) { - continue; - } - } - /* FULL sync mode we copy the whole drive. */ - if (alloced < 0) { - ret = alloced; - } else { - ret = backup_do_cow(s, offset, s->cluster_size, - &error_is_read, false); - } - if (ret < 0) { - /* Depending on error action, fail now or retry cluster */ - BlockErrorAction action = - backup_error_action(s, error_is_read, -ret); - if (action == BLOCK_ERROR_ACTION_REPORT) { - break; - } else { - offset -= s->cluster_size; - continue; - } - } - } + ret = backup_loop(s); } notifier_with_return_remove(&s->before_write); @@ -534,7 +478,6 @@ static int coroutine_fn backup_run(Job *job, Error **errp) /* wait until pending backup_do_cow() calls have completed */ qemu_co_rwlock_wrlock(&s->flush_rwlock); qemu_co_rwlock_unlock(&s->flush_rwlock); - hbitmap_free(s->copy_bitmap); return ret; } @@ -554,6 +497,42 @@ static const BlockJobDriver backup_job_driver = { .drain = backup_drain, }; +static int64_t backup_calculate_cluster_size(BlockDriverState *target, + Error **errp) +{ + int ret; + BlockDriverInfo bdi; + + /* + * If there is no backing file on the target, we cannot rely on COW if our + * backup cluster size is smaller than the target cluster size. Even for + * targets with a backing file, try to avoid COW if possible. + */ + ret = bdrv_get_info(target, &bdi); + if (ret == -ENOTSUP && !target->backing) { + /* Cluster size is not defined */ + warn_report("The target block device doesn't provide " + "information about the block size and it doesn't have a " + "backing file. The default block size of %u bytes is " + "used. If the actual block size of the target exceeds " + "this default, the backup may be unusable", + BACKUP_CLUSTER_SIZE_DEFAULT); + return BACKUP_CLUSTER_SIZE_DEFAULT; + } else if (ret < 0 && !target->backing) { + error_setg_errno(errp, -ret, + "Couldn't determine the cluster size of the target image, " + "which has no backing file"); + error_append_hint(errp, + "Aborting, since this may create an unusable destination image\n"); + return ret; + } else if (ret < 0 && target->backing) { + /* Not fatal; just trudge on ahead. */ + return BACKUP_CLUSTER_SIZE_DEFAULT; + } + + return MAX(BACKUP_CLUSTER_SIZE_DEFAULT, bdi.cluster_size); +} + BlockJob *backup_job_create(const char *job_id, BlockDriverState *bs, BlockDriverState *target, int64_t speed, MirrorSyncMode sync_mode, BdrvDirtyBitmap *sync_bitmap, @@ -565,9 +544,10 @@ BlockJob *backup_job_create(const char *job_id, BlockDriverState *bs, JobTxn *txn, Error **errp) { int64_t len; - BlockDriverInfo bdi; BackupBlockJob *job = NULL; int ret; + int64_t cluster_size; + HBitmap *copy_bitmap = NULL; assert(bs); assert(target); @@ -629,6 +609,13 @@ BlockJob *backup_job_create(const char *job_id, BlockDriverState *bs, goto error; } + cluster_size = backup_calculate_cluster_size(target, errp); + if (cluster_size < 0) { + goto error; + } + + copy_bitmap = hbitmap_alloc(len, ctz32(cluster_size)); + /* job->len is fixed, so we can't allow resize */ job = block_job_create(job_id, &backup_job_driver, txn, bs, BLK_PERM_CONSISTENT_READ, @@ -640,7 +627,8 @@ BlockJob *backup_job_create(const char *job_id, BlockDriverState *bs, } /* The target must match the source in size, so no resize here either */ - job->target = blk_new(BLK_PERM_WRITE, + job->target = blk_new(job->common.job.aio_context, + BLK_PERM_WRITE, BLK_PERM_CONSISTENT_READ | BLK_PERM_WRITE | BLK_PERM_WRITE_UNCHANGED | BLK_PERM_GRAPH_MOD); ret = blk_insert_bs(job->target, target, errp); @@ -657,33 +645,9 @@ BlockJob *backup_job_create(const char *job_id, BlockDriverState *bs, /* Detect image-fleecing (and similar) schemes */ job->serialize_target_writes = bdrv_chain_contains(target, bs); - - /* If there is no backing file on the target, we cannot rely on COW if our - * backup cluster size is smaller than the target cluster size. Even for - * targets with a backing file, try to avoid COW if possible. */ - ret = bdrv_get_info(target, &bdi); - if (ret == -ENOTSUP && !target->backing) { - /* Cluster size is not defined */ - warn_report("The target block device doesn't provide " - "information about the block size and it doesn't have a " - "backing file. The default block size of %u bytes is " - "used. If the actual block size of the target exceeds " - "this default, the backup may be unusable", - BACKUP_CLUSTER_SIZE_DEFAULT); - job->cluster_size = BACKUP_CLUSTER_SIZE_DEFAULT; - } else if (ret < 0 && !target->backing) { - error_setg_errno(errp, -ret, - "Couldn't determine the cluster size of the target image, " - "which has no backing file"); - error_append_hint(errp, - "Aborting, since this may create an unusable destination image\n"); - goto error; - } else if (ret < 0 && target->backing) { - /* Not fatal; just trudge on ahead. */ - job->cluster_size = BACKUP_CLUSTER_SIZE_DEFAULT; - } else { - job->cluster_size = MAX(BACKUP_CLUSTER_SIZE_DEFAULT, bdi.cluster_size); - } + job->cluster_size = cluster_size; + job->copy_bitmap = copy_bitmap; + copy_bitmap = NULL; job->use_copy_range = true; job->copy_range_size = MIN_NON_ZERO(blk_get_max_transfer(job->common.blk), blk_get_max_transfer(job->target)); @@ -699,6 +663,10 @@ BlockJob *backup_job_create(const char *job_id, BlockDriverState *bs, return &job->common; error: + if (copy_bitmap) { + assert(!job || !job->copy_bitmap); + hbitmap_free(copy_bitmap); + } if (sync_bitmap) { bdrv_reclaim_dirty_bitmap(bs, sync_bitmap, NULL); } diff --git a/block/block-backend.c b/block/block-backend.c index 4c0a8ef88d..f5d9407d20 100644 --- a/block/block-backend.c +++ b/block/block-backend.c @@ -42,6 +42,7 @@ struct BlockBackend { char *name; int refcnt; BdrvChild *root; + AioContext *ctx; DriveInfo *legacy_dinfo; /* null unless created by drive_new() */ QTAILQ_ENTRY(BlockBackend) link; /* for block_backends */ QTAILQ_ENTRY(BlockBackend) monitor_link; /* for monitor_block_backends */ @@ -322,12 +323,13 @@ static const BdrvChildRole child_root = { * * Return the new BlockBackend on success, null on failure. */ -BlockBackend *blk_new(uint64_t perm, uint64_t shared_perm) +BlockBackend *blk_new(AioContext *ctx, uint64_t perm, uint64_t shared_perm) { BlockBackend *blk; blk = g_new0(BlockBackend, 1); blk->refcnt = 1; + blk->ctx = ctx; blk->perm = perm; blk->shared_perm = shared_perm; blk_set_enable_write_cache(blk, true); @@ -347,6 +349,7 @@ BlockBackend *blk_new(uint64_t perm, uint64_t shared_perm) /* * Creates a new BlockBackend, opens a new BlockDriverState, and connects both. + * The new BlockBackend is in the main AioContext. * * Just as with bdrv_open(), after having called this function the reference to * @options belongs to the block layer (even on failure). @@ -382,17 +385,16 @@ BlockBackend *blk_new_open(const char *filename, const char *reference, perm |= BLK_PERM_RESIZE; } - blk = blk_new(perm, BLK_PERM_ALL); + blk = blk_new(qemu_get_aio_context(), perm, BLK_PERM_ALL); bs = bdrv_open(filename, reference, options, flags, errp); if (!bs) { blk_unref(blk); return NULL; } - blk->root = bdrv_root_attach_child(bs, "root", &child_root, + blk->root = bdrv_root_attach_child(bs, "root", &child_root, blk->ctx, perm, BLK_PERM_ALL, blk, errp); if (!blk->root) { - bdrv_unref(bs); blk_unref(blk); return NULL; } @@ -800,12 +802,12 @@ void blk_remove_bs(BlockBackend *blk) int blk_insert_bs(BlockBackend *blk, BlockDriverState *bs, Error **errp) { ThrottleGroupMember *tgm = &blk->public.throttle_group_member; - blk->root = bdrv_root_attach_child(bs, "root", &child_root, + bdrv_ref(bs); + blk->root = bdrv_root_attach_child(bs, "root", &child_root, blk->ctx, blk->perm, blk->shared_perm, blk, errp); if (blk->root == NULL) { return -EPERM; } - bdrv_ref(bs); notifier_list_notify(&blk->insert_bs_notifiers, blk); if (tgm->throttle_state) { @@ -1857,7 +1859,14 @@ void blk_op_unblock_all(BlockBackend *blk, Error *reason) AioContext *blk_get_aio_context(BlockBackend *blk) { - return bdrv_get_aio_context(blk_bs(blk)); + BlockDriverState *bs = blk_bs(blk); + + if (bs) { + AioContext *ctx = bdrv_get_aio_context(blk_bs(blk)); + assert(ctx == blk->ctx); + } + + return blk->ctx; } static AioContext *blk_aiocb_get_aio_context(BlockAIOCB *acb) @@ -1866,30 +1875,37 @@ static AioContext *blk_aiocb_get_aio_context(BlockAIOCB *acb) return blk_get_aio_context(blk_acb->blk); } -static void blk_do_set_aio_context(BlockBackend *blk, AioContext *new_context, - bool update_root_node) +static int blk_do_set_aio_context(BlockBackend *blk, AioContext *new_context, + bool update_root_node, Error **errp) { BlockDriverState *bs = blk_bs(blk); ThrottleGroupMember *tgm = &blk->public.throttle_group_member; + int ret; if (bs) { + if (update_root_node) { + ret = bdrv_child_try_set_aio_context(bs, new_context, blk->root, + errp); + if (ret < 0) { + return ret; + } + } if (tgm->throttle_state) { bdrv_drained_begin(bs); throttle_group_detach_aio_context(tgm); throttle_group_attach_aio_context(tgm, new_context); bdrv_drained_end(bs); } - if (update_root_node) { - GSList *ignore = g_slist_prepend(NULL, blk->root); - bdrv_set_aio_context_ignore(bs, new_context, &ignore); - g_slist_free(ignore); - } } + + blk->ctx = new_context; + return 0; } -void blk_set_aio_context(BlockBackend *blk, AioContext *new_context) +int blk_set_aio_context(BlockBackend *blk, AioContext *new_context, + Error **errp) { - blk_do_set_aio_context(blk, new_context, true); + return blk_do_set_aio_context(blk, new_context, true, errp); } static bool blk_root_can_set_aio_ctx(BdrvChild *child, AioContext *ctx, @@ -1916,7 +1932,7 @@ static void blk_root_set_aio_ctx(BdrvChild *child, AioContext *ctx, GSList **ignore) { BlockBackend *blk = child->opaque; - blk_do_set_aio_context(blk, ctx, false); + blk_do_set_aio_context(blk, ctx, false, &error_abort); } void blk_add_aio_context_notifier(BlockBackend *blk, diff --git a/block/commit.c b/block/commit.c index 14e5bb394c..c815def89a 100644 --- a/block/commit.c +++ b/block/commit.c @@ -301,7 +301,6 @@ void commit_start(const char *job_id, BlockDriverState *bs, commit_top_bs->implicit = true; } commit_top_bs->total_sectors = top->total_sectors; - bdrv_set_aio_context(commit_top_bs, bdrv_get_aio_context(top)); bdrv_append(commit_top_bs, top, &local_err); if (local_err) { @@ -338,7 +337,8 @@ void commit_start(const char *job_id, BlockDriverState *bs, goto fail; } - s->base = blk_new(BLK_PERM_CONSISTENT_READ + s->base = blk_new(s->common.job.aio_context, + BLK_PERM_CONSISTENT_READ | BLK_PERM_WRITE | BLK_PERM_RESIZE, BLK_PERM_CONSISTENT_READ @@ -351,7 +351,7 @@ void commit_start(const char *job_id, BlockDriverState *bs, s->base_bs = base; /* Required permissions are already taken with block_job_add_bdrv() */ - s->top = blk_new(0, BLK_PERM_ALL); + s->top = blk_new(s->common.job.aio_context, 0, BLK_PERM_ALL); ret = blk_insert_bs(s->top, top, errp); if (ret < 0) { goto fail; @@ -395,6 +395,7 @@ int bdrv_commit(BlockDriverState *bs) BlockDriverState *backing_file_bs = NULL; BlockDriverState *commit_top_bs = NULL; BlockDriver *drv = bs->drv; + AioContext *ctx; int64_t offset, length, backing_length; int ro; int64_t n; @@ -422,8 +423,9 @@ int bdrv_commit(BlockDriverState *bs) } } - src = blk_new(BLK_PERM_CONSISTENT_READ, BLK_PERM_ALL); - backing = blk_new(BLK_PERM_WRITE | BLK_PERM_RESIZE, BLK_PERM_ALL); + ctx = bdrv_get_aio_context(bs); + src = blk_new(ctx, BLK_PERM_CONSISTENT_READ, BLK_PERM_ALL); + backing = blk_new(ctx, BLK_PERM_WRITE | BLK_PERM_RESIZE, BLK_PERM_ALL); ret = blk_insert_bs(src, bs, &local_err); if (ret < 0) { @@ -440,7 +442,6 @@ int bdrv_commit(BlockDriverState *bs) error_report_err(local_err); goto ro_cleanup; } - bdrv_set_aio_context(commit_top_bs, bdrv_get_aio_context(backing_file_bs)); bdrv_set_backing_hd(commit_top_bs, backing_file_bs, &error_abort); bdrv_set_backing_hd(bs, commit_top_bs, &error_abort); diff --git a/block/crypto.c b/block/crypto.c index 3af46b805f..7351fd479d 100644 --- a/block/crypto.c +++ b/block/crypto.c @@ -257,7 +257,8 @@ static int block_crypto_co_create_generic(BlockDriverState *bs, QCryptoBlock *crypto = NULL; struct BlockCryptoCreateData data; - blk = blk_new(BLK_PERM_WRITE | BLK_PERM_RESIZE, BLK_PERM_ALL); + blk = blk_new(bdrv_get_aio_context(bs), + BLK_PERM_WRITE | BLK_PERM_RESIZE, BLK_PERM_ALL); ret = blk_insert_bs(blk, bs, errp); if (ret < 0) { diff --git a/block/dirty-bitmap.c b/block/dirty-bitmap.c index 59e6ebb861..49646a30e6 100644 --- a/block/dirty-bitmap.c +++ b/block/dirty-bitmap.c @@ -816,10 +816,10 @@ void bdrv_merge_dirty_bitmap(BdrvDirtyBitmap *dest, const BdrvDirtyBitmap *src, { bool ret; - /* only bitmaps from one bds are supported */ - assert(dest->mutex == src->mutex); - qemu_mutex_lock(dest->mutex); + if (src->mutex != dest->mutex) { + qemu_mutex_lock(src->mutex); + } if (bdrv_dirty_bitmap_check(dest, BDRV_BITMAP_DEFAULT, errp)) { goto out; @@ -845,4 +845,7 @@ void bdrv_merge_dirty_bitmap(BdrvDirtyBitmap *dest, const BdrvDirtyBitmap *src, out: qemu_mutex_unlock(dest->mutex); + if (src->mutex != dest->mutex) { + qemu_mutex_unlock(src->mutex); + } } diff --git a/block/io.c b/block/io.c index 3134a60a48..9ba1bada36 100644 --- a/block/io.c +++ b/block/io.c @@ -422,11 +422,12 @@ static void bdrv_do_drained_end(BlockDriverState *bs, bool recursive, return; } assert(bs->quiesce_counter > 0); - old_quiesce_counter = atomic_fetch_dec(&bs->quiesce_counter); /* Re-enable things in child-to-parent order */ bdrv_drain_invoke(bs, false); bdrv_parent_drained_end(bs, parent, ignore_bds_parents); + + old_quiesce_counter = atomic_fetch_dec(&bs->quiesce_counter); if (old_quiesce_counter == 1) { aio_enable_external(bdrv_get_aio_context(bs)); } @@ -2092,6 +2093,12 @@ static int coroutine_fn bdrv_co_block_status(BlockDriverState *bs, */ assert(*pnum && QEMU_IS_ALIGNED(*pnum, align) && align > offset - aligned_offset); + if (ret & BDRV_BLOCK_RECURSE) { + assert(ret & BDRV_BLOCK_DATA); + assert(ret & BDRV_BLOCK_OFFSET_VALID); + assert(!(ret & BDRV_BLOCK_ZERO)); + } + *pnum -= offset - aligned_offset; if (*pnum > bytes) { *pnum = bytes; @@ -2122,7 +2129,8 @@ static int coroutine_fn bdrv_co_block_status(BlockDriverState *bs, } } - if (want_zero && local_file && local_file != bs && + if (want_zero && ret & BDRV_BLOCK_RECURSE && + local_file && local_file != bs && (ret & BDRV_BLOCK_DATA) && !(ret & BDRV_BLOCK_ZERO) && (ret & BDRV_BLOCK_OFFSET_VALID)) { int64_t file_pnum; @@ -2624,7 +2632,7 @@ int bdrv_flush(BlockDriverState *bs) typedef struct DiscardCo { BdrvChild *child; int64_t offset; - int bytes; + int64_t bytes; int ret; } DiscardCo; static void coroutine_fn bdrv_pdiscard_co_entry(void *opaque) @@ -2635,14 +2643,15 @@ static void coroutine_fn bdrv_pdiscard_co_entry(void *opaque) aio_wait_kick(); } -int coroutine_fn bdrv_co_pdiscard(BdrvChild *child, int64_t offset, int bytes) +int coroutine_fn bdrv_co_pdiscard(BdrvChild *child, int64_t offset, + int64_t bytes) { BdrvTrackedRequest req; int max_pdiscard, ret; int head, tail, align; BlockDriverState *bs = child->bs; - if (!bs || !bs->drv) { + if (!bs || !bs->drv || !bdrv_is_inserted(bs)) { return -ENOMEDIUM; } @@ -2650,9 +2659,8 @@ int coroutine_fn bdrv_co_pdiscard(BdrvChild *child, int64_t offset, int bytes) return -EPERM; } - ret = bdrv_check_byte_request(bs, offset, bytes); - if (ret < 0) { - return ret; + if (offset < 0 || bytes < 0 || bytes > INT64_MAX - offset) { + return -EIO; } /* Do nothing if disabled. */ @@ -2687,7 +2695,7 @@ int coroutine_fn bdrv_co_pdiscard(BdrvChild *child, int64_t offset, int bytes) assert(max_pdiscard >= bs->bl.request_alignment); while (bytes > 0) { - int num = bytes; + int64_t num = bytes; if (head) { /* Make small requests to get to alignment boundaries. */ @@ -2749,7 +2757,7 @@ out: return ret; } -int bdrv_pdiscard(BdrvChild *child, int64_t offset, int bytes) +int bdrv_pdiscard(BdrvChild *child, int64_t offset, int64_t bytes) { Coroutine *co; DiscardCo rwco = { diff --git a/block/linux-aio.c b/block/linux-aio.c index d4b61fb251..27100c2fd1 100644 --- a/block/linux-aio.c +++ b/block/linux-aio.c @@ -30,7 +30,6 @@ #define MAX_EVENTS 128 struct qemu_laiocb { - BlockAIOCB common; Coroutine *co; LinuxAioState *ctx; struct iocb iocb; @@ -72,7 +71,7 @@ static inline ssize_t io_event_ret(struct io_event *ev) } /* - * Completes an AIO request (calls the callback and frees the ACB). + * Completes an AIO request. */ static void qemu_laio_process_completion(struct qemu_laiocb *laiocb) { @@ -94,18 +93,15 @@ static void qemu_laio_process_completion(struct qemu_laiocb *laiocb) } laiocb->ret = ret; - if (laiocb->co) { - /* If the coroutine is already entered it must be in ioq_submit() and - * will notice laio->ret has been filled in when it eventually runs - * later. Coroutines cannot be entered recursively so avoid doing - * that! - */ - if (!qemu_coroutine_entered(laiocb->co)) { - aio_co_wake(laiocb->co); - } - } else { - laiocb->common.cb(laiocb->common.opaque, ret); - qemu_aio_unref(laiocb); + + /* + * If the coroutine is already entered it must be in ioq_submit() and + * will notice laio->ret has been filled in when it eventually runs + * later. Coroutines cannot be entered recursively so avoid doing + * that! + */ + if (!qemu_coroutine_entered(laiocb->co)) { + aio_co_wake(laiocb->co); } } @@ -273,30 +269,6 @@ static bool qemu_laio_poll_cb(void *opaque) return true; } -static void laio_cancel(BlockAIOCB *blockacb) -{ - struct qemu_laiocb *laiocb = (struct qemu_laiocb *)blockacb; - struct io_event event; - int ret; - - if (laiocb->ret != -EINPROGRESS) { - return; - } - ret = io_cancel(laiocb->ctx->ctx, &laiocb->iocb, &event); - laiocb->ret = -ECANCELED; - if (ret != 0) { - /* iocb is not cancelled, cb will be called by the event loop later */ - return; - } - - laiocb->common.cb(laiocb->common.opaque, laiocb->ret); -} - -static const AIOCBInfo laio_aiocb_info = { - .aiocb_size = sizeof(struct qemu_laiocb), - .cancel_async = laio_cancel, -}; - static void ioq_init(LaioQueue *io_q) { QSIMPLEQ_INIT(&io_q->pending); @@ -431,30 +403,6 @@ int coroutine_fn laio_co_submit(BlockDriverState *bs, LinuxAioState *s, int fd, return laiocb.ret; } -BlockAIOCB *laio_submit(BlockDriverState *bs, LinuxAioState *s, int fd, - int64_t sector_num, QEMUIOVector *qiov, int nb_sectors, - BlockCompletionFunc *cb, void *opaque, int type) -{ - struct qemu_laiocb *laiocb; - off_t offset = sector_num * BDRV_SECTOR_SIZE; - int ret; - - laiocb = qemu_aio_get(&laio_aiocb_info, bs, cb, opaque); - laiocb->nbytes = nb_sectors * BDRV_SECTOR_SIZE; - laiocb->ctx = s; - laiocb->ret = -EINPROGRESS; - laiocb->is_read = (type == QEMU_AIO_READ); - laiocb->qiov = qiov; - - ret = laio_do_submit(fd, laiocb, offset, type); - if (ret < 0) { - qemu_aio_unref(laiocb); - return NULL; - } - - return &laiocb->common; -} - void laio_detach_aio_context(LinuxAioState *s, AioContext *old_context) { aio_set_event_notifier(old_context, &s->e, false, NULL, NULL); diff --git a/block/mirror.c b/block/mirror.c index ec4bd9f404..f8bdb5b21b 100644 --- a/block/mirror.c +++ b/block/mirror.c @@ -1543,7 +1543,6 @@ static void mirror_start_job(const char *job_id, BlockDriverState *bs, BDRV_REQ_NO_FALLBACK; bs_opaque = g_new0(MirrorBDSOpaque, 1); mirror_top_bs->opaque = bs_opaque; - bdrv_set_aio_context(mirror_top_bs, bdrv_get_aio_context(bs)); /* bdrv_append takes ownership of the mirror_top_bs reference, need to keep * it alive until block_job_create() succeeds even if bs has no parent. */ @@ -1584,7 +1583,8 @@ static void mirror_start_job(const char *job_id, BlockDriverState *bs, * We can allow anything except resize there.*/ target_is_backing = bdrv_chain_contains(bs, target); target_graph_mod = (backing_mode != MIRROR_LEAVE_BACKING_CHAIN); - s->target = blk_new(BLK_PERM_WRITE | BLK_PERM_RESIZE | + s->target = blk_new(s->common.job.aio_context, + BLK_PERM_WRITE | BLK_PERM_RESIZE | (target_graph_mod ? BLK_PERM_GRAPH_MOD : 0), BLK_PERM_WRITE_UNCHANGED | (target_is_backing ? BLK_PERM_CONSISTENT_READ | diff --git a/block/parallels.c b/block/parallels.c index 2747400577..00fae125d1 100644 --- a/block/parallels.c +++ b/block/parallels.c @@ -554,7 +554,8 @@ static int coroutine_fn parallels_co_create(BlockdevCreateOptions* opts, return -EIO; } - blk = blk_new(BLK_PERM_WRITE | BLK_PERM_RESIZE, BLK_PERM_ALL); + blk = blk_new(bdrv_get_aio_context(bs), + BLK_PERM_WRITE | BLK_PERM_RESIZE, BLK_PERM_ALL); ret = blk_insert_bs(blk, bs, errp); if (ret < 0) { goto out; diff --git a/block/qcow.c b/block/qcow.c index 1bb8fd05e2..6dee5bb792 100644 --- a/block/qcow.c +++ b/block/qcow.c @@ -844,7 +844,8 @@ static int coroutine_fn qcow_co_create(BlockdevCreateOptions *opts, return -EIO; } - qcow_blk = blk_new(BLK_PERM_WRITE | BLK_PERM_RESIZE, BLK_PERM_ALL); + qcow_blk = blk_new(bdrv_get_aio_context(bs), + BLK_PERM_WRITE | BLK_PERM_RESIZE, BLK_PERM_ALL); ret = blk_insert_bs(qcow_blk, bs, errp); if (ret < 0) { goto exit; diff --git a/block/qcow2-bitmap.c b/block/qcow2-bitmap.c index 8a75366c92..b2487101ed 100644 --- a/block/qcow2-bitmap.c +++ b/block/qcow2-bitmap.c @@ -29,7 +29,6 @@ #include "qapi/error.h" #include "qemu/cutils.h" -#include "block/block_int.h" #include "qcow2.h" /* NOTICE: BME here means Bitmaps Extension and used as a namespace for @@ -754,7 +753,7 @@ static int bitmap_list_store(BlockDriverState *bs, Qcow2BitmapList *bm_list, dir_offset = *offset; } - dir = g_try_malloc(dir_size); + dir = g_try_malloc0(dir_size); if (dir == NULL) { return -ENOMEM; } diff --git a/block/qcow2-cache.c b/block/qcow2-cache.c index df02e7b20a..b33bcbc984 100644 --- a/block/qcow2-cache.c +++ b/block/qcow2-cache.c @@ -23,7 +23,6 @@ */ #include "qemu/osdep.h" -#include "block/block_int.h" #include "qemu-common.h" #include "qcow2.h" #include "trace.h" diff --git a/block/qcow2-cluster.c b/block/qcow2-cluster.c index b36f4aa84a..cf892f37a8 100644 --- a/block/qcow2-cluster.c +++ b/block/qcow2-cluster.c @@ -27,7 +27,6 @@ #include "qapi/error.h" #include "qemu-common.h" -#include "block/block_int.h" #include "qcow2.h" #include "qemu/bswap.h" #include "trace.h" @@ -472,13 +471,12 @@ static bool coroutine_fn do_perform_cow_encrypt(BlockDriverState *bs, { if (bytes && bs->encrypted) { BDRVQcow2State *s = bs->opaque; - int64_t offset = (s->crypt_physical_offset ? - (cluster_offset + offset_in_cluster) : - (src_cluster_offset + offset_in_cluster)); assert((offset_in_cluster & ~BDRV_SECTOR_MASK) == 0); assert((bytes & ~BDRV_SECTOR_MASK) == 0); assert(s->crypto); - if (qcrypto_block_encrypt(s->crypto, offset, buffer, bytes, NULL) < 0) { + if (qcow2_co_encrypt(bs, cluster_offset, + src_cluster_offset + offset_in_cluster, + buffer, bytes) < 0) { return false; } } @@ -833,7 +831,7 @@ static int perform_cow(BlockDriverState *bs, QCowL2Meta *m) assert(start->offset + start->nb_bytes <= end->offset); assert(!m->data_qiov || m->data_qiov->size == data_bytes); - if (start->nb_bytes == 0 && end->nb_bytes == 0) { + if ((start->nb_bytes == 0 && end->nb_bytes == 0) || m->skip_cow) { return 0; } diff --git a/block/qcow2-refcount.c b/block/qcow2-refcount.c index 0b09d6838b..22cadd79d5 100644 --- a/block/qcow2-refcount.c +++ b/block/qcow2-refcount.c @@ -25,11 +25,11 @@ #include "qemu/osdep.h" #include "qapi/error.h" #include "qemu-common.h" -#include "block/block_int.h" #include "qcow2.h" #include "qemu/range.h" #include "qemu/bswap.h" #include "qemu/cutils.h" +#include "trace.h" static int64_t alloc_clusters_noref(BlockDriverState *bs, uint64_t size, uint64_t max); @@ -738,7 +738,11 @@ void qcow2_process_discards(BlockDriverState *bs, int ret) /* Discard is optional, ignore the return value */ if (ret >= 0) { - bdrv_pdiscard(bs->file, d->offset, d->bytes); + int r2 = bdrv_pdiscard(bs->file, d->offset, d->bytes); + if (r2 < 0) { + trace_qcow2_process_discards_failed_region(d->offset, d->bytes, + r2); + } } g_free(d); @@ -3445,3 +3449,35 @@ int64_t qcow2_get_last_cluster(BlockDriverState *bs, int64_t size) "There are no references in the refcount table."); return -EIO; } + +int qcow2_detect_metadata_preallocation(BlockDriverState *bs) +{ + BDRVQcow2State *s = bs->opaque; + int64_t i, end_cluster, cluster_count = 0, threshold; + int64_t file_length, real_allocation, real_clusters; + + file_length = bdrv_getlength(bs->file->bs); + if (file_length < 0) { + return file_length; + } + + real_allocation = bdrv_get_allocated_file_size(bs->file->bs); + if (real_allocation < 0) { + return real_allocation; + } + + real_clusters = real_allocation / s->cluster_size; + threshold = MAX(real_clusters * 10 / 9, real_clusters + 2); + + end_cluster = size_to_clusters(s, file_length); + for (i = 0; i < end_cluster && cluster_count < threshold; i++) { + uint64_t refcount; + int ret = qcow2_get_refcount(bs, i, &refcount); + if (ret < 0) { + return ret; + } + cluster_count += !!refcount; + } + + return cluster_count >= threshold; +} diff --git a/block/qcow2-snapshot.c b/block/qcow2-snapshot.c index a6ffae89a6..d0e7fa9311 100644 --- a/block/qcow2-snapshot.c +++ b/block/qcow2-snapshot.c @@ -24,7 +24,6 @@ #include "qemu/osdep.h" #include "qapi/error.h" -#include "block/block_int.h" #include "qcow2.h" #include "qemu/bswap.h" #include "qemu/error-report.h" diff --git a/block/qcow2-threads.c b/block/qcow2-threads.c new file mode 100644 index 0000000000..3b1e63fe41 --- /dev/null +++ b/block/qcow2-threads.c @@ -0,0 +1,268 @@ +/* + * Threaded data processing for Qcow2: compression, encryption + * + * Copyright (c) 2004-2006 Fabrice Bellard + * Copyright (c) 2018 Virtuozzo International GmbH. All rights reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#include "qemu/osdep.h" + +#define ZLIB_CONST +#include <zlib.h> + +#include "qcow2.h" +#include "block/thread-pool.h" +#include "crypto.h" + +static int coroutine_fn +qcow2_co_process(BlockDriverState *bs, ThreadPoolFunc *func, void *arg) +{ + int ret; + BDRVQcow2State *s = bs->opaque; + ThreadPool *pool = aio_get_thread_pool(bdrv_get_aio_context(bs)); + + qemu_co_mutex_lock(&s->lock); + while (s->nb_threads >= QCOW2_MAX_THREADS) { + qemu_co_queue_wait(&s->thread_task_queue, &s->lock); + } + s->nb_threads++; + qemu_co_mutex_unlock(&s->lock); + + ret = thread_pool_submit_co(pool, func, arg); + + qemu_co_mutex_lock(&s->lock); + s->nb_threads--; + qemu_co_queue_next(&s->thread_task_queue); + qemu_co_mutex_unlock(&s->lock); + + return ret; +} + + +/* + * Compression + */ + +typedef ssize_t (*Qcow2CompressFunc)(void *dest, size_t dest_size, + const void *src, size_t src_size); +typedef struct Qcow2CompressData { + void *dest; + size_t dest_size; + const void *src; + size_t src_size; + ssize_t ret; + + Qcow2CompressFunc func; +} Qcow2CompressData; + +/* + * qcow2_compress() + * + * @dest - destination buffer, @dest_size bytes + * @src - source buffer, @src_size bytes + * + * Returns: compressed size on success + * -ENOMEM destination buffer is not enough to store compressed data + * -EIO on any other error + */ +static ssize_t qcow2_compress(void *dest, size_t dest_size, + const void *src, size_t src_size) +{ + ssize_t ret; + z_stream strm; + + /* best compression, small window, no zlib header */ + memset(&strm, 0, sizeof(strm)); + ret = deflateInit2(&strm, Z_DEFAULT_COMPRESSION, Z_DEFLATED, + -12, 9, Z_DEFAULT_STRATEGY); + if (ret != Z_OK) { + return -EIO; + } + + /* + * strm.next_in is not const in old zlib versions, such as those used on + * OpenBSD/NetBSD, so cast the const away + */ + strm.avail_in = src_size; + strm.next_in = (void *) src; + strm.avail_out = dest_size; + strm.next_out = dest; + + ret = deflate(&strm, Z_FINISH); + if (ret == Z_STREAM_END) { + ret = dest_size - strm.avail_out; + } else { + ret = (ret == Z_OK ? -ENOMEM : -EIO); + } + + deflateEnd(&strm); + + return ret; +} + +/* + * qcow2_decompress() + * + * Decompress some data (not more than @src_size bytes) to produce exactly + * @dest_size bytes. + * + * @dest - destination buffer, @dest_size bytes + * @src - source buffer, @src_size bytes + * + * Returns: 0 on success + * -1 on fail + */ +static ssize_t qcow2_decompress(void *dest, size_t dest_size, + const void *src, size_t src_size) +{ + int ret = 0; + z_stream strm; + + memset(&strm, 0, sizeof(strm)); + strm.avail_in = src_size; + strm.next_in = (void *) src; + strm.avail_out = dest_size; + strm.next_out = dest; + + ret = inflateInit2(&strm, -12); + if (ret != Z_OK) { + return -1; + } + + ret = inflate(&strm, Z_FINISH); + if ((ret != Z_STREAM_END && ret != Z_BUF_ERROR) || strm.avail_out != 0) { + /* + * We approve Z_BUF_ERROR because we need @dest buffer to be filled, but + * @src buffer may be processed partly (because in qcow2 we know size of + * compressed data with precision of one sector) + */ + ret = -1; + } + + inflateEnd(&strm); + + return ret; +} + +static int qcow2_compress_pool_func(void *opaque) +{ + Qcow2CompressData *data = opaque; + + data->ret = data->func(data->dest, data->dest_size, + data->src, data->src_size); + + return 0; +} + +static ssize_t coroutine_fn +qcow2_co_do_compress(BlockDriverState *bs, void *dest, size_t dest_size, + const void *src, size_t src_size, Qcow2CompressFunc func) +{ + Qcow2CompressData arg = { + .dest = dest, + .dest_size = dest_size, + .src = src, + .src_size = src_size, + .func = func, + }; + + qcow2_co_process(bs, qcow2_compress_pool_func, &arg); + + return arg.ret; +} + +ssize_t coroutine_fn +qcow2_co_compress(BlockDriverState *bs, void *dest, size_t dest_size, + const void *src, size_t src_size) +{ + return qcow2_co_do_compress(bs, dest, dest_size, src, src_size, + qcow2_compress); +} + +ssize_t coroutine_fn +qcow2_co_decompress(BlockDriverState *bs, void *dest, size_t dest_size, + const void *src, size_t src_size) +{ + return qcow2_co_do_compress(bs, dest, dest_size, src, src_size, + qcow2_decompress); +} + + +/* + * Cryptography + */ + +/* + * Qcow2EncDecFunc: common prototype of qcrypto_block_encrypt() and + * qcrypto_block_decrypt() functions. + */ +typedef int (*Qcow2EncDecFunc)(QCryptoBlock *block, uint64_t offset, + uint8_t *buf, size_t len, Error **errp); + +typedef struct Qcow2EncDecData { + QCryptoBlock *block; + uint64_t offset; + uint8_t *buf; + size_t len; + + Qcow2EncDecFunc func; +} Qcow2EncDecData; + +static int qcow2_encdec_pool_func(void *opaque) +{ + Qcow2EncDecData *data = opaque; + + return data->func(data->block, data->offset, data->buf, data->len, NULL); +} + +static int coroutine_fn +qcow2_co_encdec(BlockDriverState *bs, uint64_t file_cluster_offset, + uint64_t offset, void *buf, size_t len, Qcow2EncDecFunc func) +{ + BDRVQcow2State *s = bs->opaque; + Qcow2EncDecData arg = { + .block = s->crypto, + .offset = s->crypt_physical_offset ? + file_cluster_offset + offset_into_cluster(s, offset) : + offset, + .buf = buf, + .len = len, + .func = func, + }; + + return qcow2_co_process(bs, qcow2_encdec_pool_func, &arg); +} + +int coroutine_fn +qcow2_co_encrypt(BlockDriverState *bs, uint64_t file_cluster_offset, + uint64_t offset, void *buf, size_t len) +{ + return qcow2_co_encdec(bs, file_cluster_offset, offset, buf, len, + qcrypto_block_encrypt); +} + +int coroutine_fn +qcow2_co_decrypt(BlockDriverState *bs, uint64_t file_cluster_offset, + uint64_t offset, void *buf, size_t len) +{ + return qcow2_co_encdec(bs, file_cluster_offset, offset, buf, len, + qcrypto_block_decrypt); +} diff --git a/block/qcow2.c b/block/qcow2.c index d39882785d..9396d490d5 100644 --- a/block/qcow2.c +++ b/block/qcow2.c @@ -24,10 +24,6 @@ #include "qemu/osdep.h" -#define ZLIB_CONST -#include <zlib.h> - -#include "block/block_int.h" #include "block/qdict.h" #include "sysemu/block-backend.h" #include "qemu/module.h" @@ -44,7 +40,6 @@ #include "qapi/qobject-input-visitor.h" #include "qapi/qapi-visit-block-core.h" #include "crypto.h" -#include "block/thread-pool.h" /* Differences with QCOW: @@ -302,7 +297,7 @@ static int qcow2_read_extensions(BlockDriverState *bs, uint64_t start_offset, } s->crypto = qcrypto_block_open(s->crypto_opts, "encrypt.", qcow2_crypto_hdr_read_func, - bs, cflags, 1, errp); + bs, cflags, QCOW2_MAX_THREADS, errp); if (!s->crypto) { return -EINVAL; } @@ -1543,7 +1538,8 @@ static int coroutine_fn qcow2_do_open(BlockDriverState *bs, QDict *options, cflags |= QCRYPTO_BLOCK_OPEN_NO_IO; } s->crypto = qcrypto_block_open(s->crypto_opts, "encrypt.", - NULL, NULL, cflags, 1, errp); + NULL, NULL, cflags, + QCOW2_MAX_THREADS, errp); if (!s->crypto) { ret = -EINVAL; goto fail; @@ -1698,7 +1694,7 @@ static int coroutine_fn qcow2_do_open(BlockDriverState *bs, QDict *options, } #endif - qemu_co_queue_init(&s->compress_wait_queue); + qemu_co_queue_init(&s->thread_task_queue); return ret; @@ -1899,6 +1895,12 @@ static int coroutine_fn qcow2_co_block_status(BlockDriverState *bs, unsigned int bytes; int status = 0; + if (!s->metadata_preallocation_checked) { + ret = qcow2_detect_metadata_preallocation(bs); + s->metadata_preallocation = (ret == 1); + s->metadata_preallocation_checked = true; + } + bytes = MIN(INT_MAX, count); qemu_co_mutex_lock(&s->lock); ret = qcow2_get_cluster_offset(bs, offset, &bytes, &cluster_offset); @@ -1921,6 +1923,11 @@ static int coroutine_fn qcow2_co_block_status(BlockDriverState *bs, } else if (ret != QCOW2_CLUSTER_UNALLOCATED) { status |= BDRV_BLOCK_DATA; } + if (s->metadata_preallocation && (status & BDRV_BLOCK_DATA) && + (status & BDRV_BLOCK_OFFSET_VALID)) + { + status |= BDRV_BLOCK_RECURSE; + } return status; } @@ -1974,8 +1981,6 @@ static coroutine_fn int qcow2_co_preadv(BlockDriverState *bs, uint64_t offset, qemu_iovec_init(&hd_qiov, qiov->niov); - qemu_co_mutex_lock(&s->lock); - while (bytes != 0) { /* prepare next request */ @@ -1985,7 +1990,9 @@ static coroutine_fn int qcow2_co_preadv(BlockDriverState *bs, uint64_t offset, QCOW_MAX_CRYPT_CLUSTERS * s->cluster_size); } + qemu_co_mutex_lock(&s->lock); ret = qcow2_get_cluster_offset(bs, offset, &cur_bytes, &cluster_offset); + qemu_co_mutex_unlock(&s->lock); if (ret < 0) { goto fail; } @@ -2000,10 +2007,8 @@ static coroutine_fn int qcow2_co_preadv(BlockDriverState *bs, uint64_t offset, if (bs->backing) { BLKDBG_EVENT(bs->file, BLKDBG_READ_BACKING_AIO); - qemu_co_mutex_unlock(&s->lock); ret = bdrv_co_preadv(bs->backing, offset, cur_bytes, &hd_qiov, 0); - qemu_co_mutex_lock(&s->lock); if (ret < 0) { goto fail; } @@ -2019,11 +2024,9 @@ static coroutine_fn int qcow2_co_preadv(BlockDriverState *bs, uint64_t offset, break; case QCOW2_CLUSTER_COMPRESSED: - qemu_co_mutex_unlock(&s->lock); ret = qcow2_co_preadv_compressed(bs, cluster_offset, offset, cur_bytes, &hd_qiov); - qemu_co_mutex_lock(&s->lock); if (ret < 0) { goto fail; } @@ -2060,11 +2063,9 @@ static coroutine_fn int qcow2_co_preadv(BlockDriverState *bs, uint64_t offset, } BLKDBG_EVENT(bs->file, BLKDBG_READ_AIO); - qemu_co_mutex_unlock(&s->lock); ret = bdrv_co_preadv(s->data_file, cluster_offset + offset_in_cluster, cur_bytes, &hd_qiov, 0); - qemu_co_mutex_lock(&s->lock); if (ret < 0) { goto fail; } @@ -2072,13 +2073,8 @@ static coroutine_fn int qcow2_co_preadv(BlockDriverState *bs, uint64_t offset, assert(s->crypto); assert((offset & (BDRV_SECTOR_SIZE - 1)) == 0); assert((cur_bytes & (BDRV_SECTOR_SIZE - 1)) == 0); - if (qcrypto_block_decrypt(s->crypto, - (s->crypt_physical_offset ? - cluster_offset + offset_in_cluster : - offset), - cluster_data, - cur_bytes, - NULL) < 0) { + if (qcow2_co_decrypt(bs, cluster_offset, offset, + cluster_data, cur_bytes) < 0) { ret = -EIO; goto fail; } @@ -2099,8 +2095,6 @@ static coroutine_fn int qcow2_co_preadv(BlockDriverState *bs, uint64_t offset, ret = 0; fail: - qemu_co_mutex_unlock(&s->lock); - qemu_iovec_destroy(&hd_qiov); qemu_vfree(cluster_data); @@ -2120,6 +2114,11 @@ static bool merge_cow(uint64_t offset, unsigned bytes, continue; } + /* If COW regions are handled already, skip this too */ + if (m->skip_cow) { + continue; + } + /* The data (middle) region must be immediately after the * start region */ if (l2meta_cow_start(m) + m->cow_start.nb_bytes != offset) { @@ -2145,6 +2144,80 @@ static bool merge_cow(uint64_t offset, unsigned bytes, return false; } +static bool is_unallocated(BlockDriverState *bs, int64_t offset, int64_t bytes) +{ + int64_t nr; + return !bytes || + (!bdrv_is_allocated_above(bs, NULL, offset, bytes, &nr) && nr == bytes); +} + +static bool is_zero_cow(BlockDriverState *bs, QCowL2Meta *m) +{ + /* + * This check is designed for optimization shortcut so it must be + * efficient. + * Instead of is_zero(), use is_unallocated() as it is faster (but not + * as accurate and can result in false negatives). + */ + return is_unallocated(bs, m->offset + m->cow_start.offset, + m->cow_start.nb_bytes) && + is_unallocated(bs, m->offset + m->cow_end.offset, + m->cow_end.nb_bytes); +} + +static int handle_alloc_space(BlockDriverState *bs, QCowL2Meta *l2meta) +{ + BDRVQcow2State *s = bs->opaque; + QCowL2Meta *m; + + if (!(s->data_file->bs->supported_zero_flags & BDRV_REQ_NO_FALLBACK)) { + return 0; + } + + if (bs->encrypted) { + return 0; + } + + for (m = l2meta; m != NULL; m = m->next) { + int ret; + + if (!m->cow_start.nb_bytes && !m->cow_end.nb_bytes) { + continue; + } + + if (!is_zero_cow(bs, m)) { + continue; + } + + /* + * instead of writing zero COW buffers, + * efficiently zero out the whole clusters + */ + + ret = qcow2_pre_write_overlap_check(bs, 0, m->alloc_offset, + m->nb_clusters * s->cluster_size, + true); + if (ret < 0) { + return ret; + } + + BLKDBG_EVENT(bs->file, BLKDBG_CLUSTER_ALLOC_SPACE); + ret = bdrv_co_pwrite_zeroes(s->data_file, m->alloc_offset, + m->nb_clusters * s->cluster_size, + BDRV_REQ_NO_FALLBACK); + if (ret < 0) { + if (ret != -ENOTSUP && ret != -EAGAIN) { + return ret; + } + continue; + } + + trace_qcow2_skip_cow(qemu_coroutine_self(), m->offset, m->nb_clusters); + m->skip_cow = true; + } + return 0; +} + static coroutine_fn int qcow2_co_pwritev(BlockDriverState *bs, uint64_t offset, uint64_t bytes, QEMUIOVector *qiov, int flags) @@ -2181,11 +2254,20 @@ static coroutine_fn int qcow2_co_pwritev(BlockDriverState *bs, uint64_t offset, ret = qcow2_alloc_cluster_offset(bs, offset, &cur_bytes, &cluster_offset, &l2meta); if (ret < 0) { - goto fail; + goto out_locked; } assert((cluster_offset & 511) == 0); + ret = qcow2_pre_write_overlap_check(bs, 0, + cluster_offset + offset_in_cluster, + cur_bytes, true); + if (ret < 0) { + goto out_locked; + } + + qemu_co_mutex_unlock(&s->lock); + qemu_iovec_reset(&hd_qiov); qemu_iovec_concat(&hd_qiov, qiov, bytes_done, cur_bytes); @@ -2197,7 +2279,7 @@ static coroutine_fn int qcow2_co_pwritev(BlockDriverState *bs, uint64_t offset, * s->cluster_size); if (cluster_data == NULL) { ret = -ENOMEM; - goto fail; + goto out_unlocked; } } @@ -2205,24 +2287,20 @@ static coroutine_fn int qcow2_co_pwritev(BlockDriverState *bs, uint64_t offset, QCOW_MAX_CRYPT_CLUSTERS * s->cluster_size); qemu_iovec_to_buf(&hd_qiov, 0, cluster_data, hd_qiov.size); - if (qcrypto_block_encrypt(s->crypto, - (s->crypt_physical_offset ? - cluster_offset + offset_in_cluster : - offset), - cluster_data, - cur_bytes, NULL) < 0) { + if (qcow2_co_encrypt(bs, cluster_offset, offset, + cluster_data, cur_bytes) < 0) { ret = -EIO; - goto fail; + goto out_unlocked; } qemu_iovec_reset(&hd_qiov); qemu_iovec_add(&hd_qiov, cluster_data, cur_bytes); } - ret = qcow2_pre_write_overlap_check(bs, 0, - cluster_offset + offset_in_cluster, cur_bytes, true); + /* Try to efficiently initialize the physical space with zeroes */ + ret = handle_alloc_space(bs, l2meta); if (ret < 0) { - goto fail; + goto out_unlocked; } /* If we need to do COW, check if it's possible to merge the @@ -2230,22 +2308,22 @@ static coroutine_fn int qcow2_co_pwritev(BlockDriverState *bs, uint64_t offset, * If it's not possible (or not necessary) then write the * guest data now. */ if (!merge_cow(offset, cur_bytes, &hd_qiov, l2meta)) { - qemu_co_mutex_unlock(&s->lock); BLKDBG_EVENT(bs->file, BLKDBG_WRITE_AIO); trace_qcow2_writev_data(qemu_coroutine_self(), cluster_offset + offset_in_cluster); ret = bdrv_co_pwritev(s->data_file, cluster_offset + offset_in_cluster, cur_bytes, &hd_qiov, 0); - qemu_co_mutex_lock(&s->lock); if (ret < 0) { - goto fail; + goto out_unlocked; } } + qemu_co_mutex_lock(&s->lock); + ret = qcow2_handle_l2meta(bs, &l2meta, true); if (ret) { - goto fail; + goto out_locked; } bytes -= cur_bytes; @@ -2254,8 +2332,12 @@ static coroutine_fn int qcow2_co_pwritev(BlockDriverState *bs, uint64_t offset, trace_qcow2_writev_done_part(qemu_coroutine_self(), cur_bytes); } ret = 0; + goto out_locked; -fail: +out_unlocked: + qemu_co_mutex_lock(&s->lock); + +out_locked: qcow2_handle_l2meta(bs, &l2meta, false); qemu_co_mutex_unlock(&s->lock); @@ -3092,7 +3174,8 @@ qcow2_co_create(BlockdevCreateOptions *create_options, Error **errp) } /* Create BlockBackend to write to the image */ - blk = blk_new(BLK_PERM_WRITE | BLK_PERM_RESIZE, BLK_PERM_ALL); + blk = blk_new(bdrv_get_aio_context(bs), + BLK_PERM_WRITE | BLK_PERM_RESIZE, BLK_PERM_ALL); ret = blk_insert_bs(blk, bs, errp); if (ret < 0) { goto out; @@ -3921,171 +4004,6 @@ fail: return ret; } -/* - * qcow2_compress() - * - * @dest - destination buffer, @dest_size bytes - * @src - source buffer, @src_size bytes - * - * Returns: compressed size on success - * -ENOMEM destination buffer is not enough to store compressed data - * -EIO on any other error - */ -static ssize_t qcow2_compress(void *dest, size_t dest_size, - const void *src, size_t src_size) -{ - ssize_t ret; - z_stream strm; - - /* best compression, small window, no zlib header */ - memset(&strm, 0, sizeof(strm)); - ret = deflateInit2(&strm, Z_DEFAULT_COMPRESSION, Z_DEFLATED, - -12, 9, Z_DEFAULT_STRATEGY); - if (ret != Z_OK) { - return -EIO; - } - - /* strm.next_in is not const in old zlib versions, such as those used on - * OpenBSD/NetBSD, so cast the const away */ - strm.avail_in = src_size; - strm.next_in = (void *) src; - strm.avail_out = dest_size; - strm.next_out = dest; - - ret = deflate(&strm, Z_FINISH); - if (ret == Z_STREAM_END) { - ret = dest_size - strm.avail_out; - } else { - ret = (ret == Z_OK ? -ENOMEM : -EIO); - } - - deflateEnd(&strm); - - return ret; -} - -/* - * qcow2_decompress() - * - * Decompress some data (not more than @src_size bytes) to produce exactly - * @dest_size bytes. - * - * @dest - destination buffer, @dest_size bytes - * @src - source buffer, @src_size bytes - * - * Returns: 0 on success - * -1 on fail - */ -static ssize_t qcow2_decompress(void *dest, size_t dest_size, - const void *src, size_t src_size) -{ - int ret = 0; - z_stream strm; - - memset(&strm, 0, sizeof(strm)); - strm.avail_in = src_size; - strm.next_in = (void *) src; - strm.avail_out = dest_size; - strm.next_out = dest; - - ret = inflateInit2(&strm, -12); - if (ret != Z_OK) { - return -1; - } - - ret = inflate(&strm, Z_FINISH); - if ((ret != Z_STREAM_END && ret != Z_BUF_ERROR) || strm.avail_out != 0) { - /* We approve Z_BUF_ERROR because we need @dest buffer to be filled, but - * @src buffer may be processed partly (because in qcow2 we know size of - * compressed data with precision of one sector) */ - ret = -1; - } - - inflateEnd(&strm); - - return ret; -} - -#define MAX_COMPRESS_THREADS 4 - -typedef ssize_t (*Qcow2CompressFunc)(void *dest, size_t dest_size, - const void *src, size_t src_size); -typedef struct Qcow2CompressData { - void *dest; - size_t dest_size; - const void *src; - size_t src_size; - ssize_t ret; - - Qcow2CompressFunc func; -} Qcow2CompressData; - -static int qcow2_compress_pool_func(void *opaque) -{ - Qcow2CompressData *data = opaque; - - data->ret = data->func(data->dest, data->dest_size, - data->src, data->src_size); - - return 0; -} - -static void qcow2_compress_complete(void *opaque, int ret) -{ - qemu_coroutine_enter(opaque); -} - -static ssize_t coroutine_fn -qcow2_co_do_compress(BlockDriverState *bs, void *dest, size_t dest_size, - const void *src, size_t src_size, Qcow2CompressFunc func) -{ - BDRVQcow2State *s = bs->opaque; - BlockAIOCB *acb; - ThreadPool *pool = aio_get_thread_pool(bdrv_get_aio_context(bs)); - Qcow2CompressData arg = { - .dest = dest, - .dest_size = dest_size, - .src = src, - .src_size = src_size, - .func = func, - }; - - while (s->nb_compress_threads >= MAX_COMPRESS_THREADS) { - qemu_co_queue_wait(&s->compress_wait_queue, NULL); - } - - s->nb_compress_threads++; - acb = thread_pool_submit_aio(pool, qcow2_compress_pool_func, &arg, - qcow2_compress_complete, - qemu_coroutine_self()); - - if (!acb) { - s->nb_compress_threads--; - return -EINVAL; - } - qemu_coroutine_yield(); - s->nb_compress_threads--; - qemu_co_queue_next(&s->compress_wait_queue); - - return arg.ret; -} - -static ssize_t coroutine_fn -qcow2_co_compress(BlockDriverState *bs, void *dest, size_t dest_size, - const void *src, size_t src_size) -{ - return qcow2_co_do_compress(bs, dest, dest_size, src, src_size, - qcow2_compress); -} - -static ssize_t coroutine_fn -qcow2_co_decompress(BlockDriverState *bs, void *dest, size_t dest_size, - const void *src, size_t src_size) -{ - return qcow2_co_do_compress(bs, dest, dest_size, src, src_size, - qcow2_decompress); -} - /* XXX: put compressed sectors first, then all the cluster aligned tables to avoid losing bytes in alignment */ static coroutine_fn int @@ -5089,7 +5007,8 @@ static int qcow2_amend_options(BlockDriverState *bs, QemuOpts *opts, } if (new_size) { - BlockBackend *blk = blk_new(BLK_PERM_RESIZE, BLK_PERM_ALL); + BlockBackend *blk = blk_new(bdrv_get_aio_context(bs), + BLK_PERM_RESIZE, BLK_PERM_ALL); ret = blk_insert_bs(blk, bs, errp); if (ret < 0) { blk_unref(blk); diff --git a/block/qcow2.h b/block/qcow2.h index 8d92ef1fee..fc1b0d3c1e 100644 --- a/block/qcow2.h +++ b/block/qcow2.h @@ -28,6 +28,7 @@ #include "crypto/block.h" #include "qemu/coroutine.h" #include "qemu/units.h" +#include "block/block_int.h" //#define DEBUG_ALLOC //#define DEBUG_ALLOC2 @@ -267,6 +268,8 @@ typedef struct Qcow2BitmapHeaderExt { uint64_t bitmap_directory_offset; } QEMU_PACKED Qcow2BitmapHeaderExt; +#define QCOW2_MAX_THREADS 4 + typedef struct BDRVQcow2State { int cluster_bits; int cluster_size; @@ -349,10 +352,13 @@ typedef struct BDRVQcow2State { char *image_backing_format; char *image_data_file; - CoQueue compress_wait_queue; - int nb_compress_threads; + CoQueue thread_task_queue; + int nb_threads; BdrvChild *data_file; + + bool metadata_preallocation_checked; + bool metadata_preallocation; } BDRVQcow2State; typedef struct Qcow2COWRegion { @@ -402,6 +408,12 @@ typedef struct QCowL2Meta */ Qcow2COWRegion cow_end; + /* + * Indicates that COW regions are already handled and do not require + * any more processing. + */ + bool skip_cow; + /** * The I/O vector with the data from the actual guest write request. * If non-NULL, this is meant to be merged together with the data @@ -646,6 +658,7 @@ int qcow2_change_refcount_order(BlockDriverState *bs, int refcount_order, void *cb_opaque, Error **errp); int qcow2_shrink_reftable(BlockDriverState *bs); int64_t qcow2_get_last_cluster(BlockDriverState *bs, int64_t size); +int qcow2_detect_metadata_preallocation(BlockDriverState *bs); /* qcow2-cluster.c functions */ int qcow2_grow_l1_table(BlockDriverState *bs, uint64_t min_size, @@ -737,4 +750,17 @@ void qcow2_remove_persistent_dirty_bitmap(BlockDriverState *bs, const char *name, Error **errp); +ssize_t coroutine_fn +qcow2_co_compress(BlockDriverState *bs, void *dest, size_t dest_size, + const void *src, size_t src_size); +ssize_t coroutine_fn +qcow2_co_decompress(BlockDriverState *bs, void *dest, size_t dest_size, + const void *src, size_t src_size); +int coroutine_fn +qcow2_co_encrypt(BlockDriverState *bs, uint64_t file_cluster_offset, + uint64_t offset, void *buf, size_t len); +int coroutine_fn +qcow2_co_decrypt(BlockDriverState *bs, uint64_t file_cluster_offset, + uint64_t offset, void *buf, size_t len); + #endif diff --git a/block/qed.c b/block/qed.c index dcdcd62b4a..bb4f5c9863 100644 --- a/block/qed.c +++ b/block/qed.c @@ -649,7 +649,8 @@ static int coroutine_fn bdrv_qed_co_create(BlockdevCreateOptions *opts, return -EIO; } - blk = blk_new(BLK_PERM_WRITE | BLK_PERM_RESIZE, BLK_PERM_ALL); + blk = blk_new(bdrv_get_aio_context(bs), + BLK_PERM_WRITE | BLK_PERM_RESIZE, BLK_PERM_ALL); ret = blk_insert_bs(blk, bs, errp); if (ret < 0) { goto out; diff --git a/block/quorum.c b/block/quorum.c index 352f729136..133ee18204 100644 --- a/block/quorum.c +++ b/block/quorum.c @@ -1019,7 +1019,6 @@ static void quorum_add_child(BlockDriverState *bs, BlockDriverState *child_bs, child = bdrv_attach_child(bs, child_bs, indexstr, &child_format, errp); if (child == NULL) { s->next_child_index--; - bdrv_unref(child_bs); goto out; } s->children = g_renew(BdrvChild *, s->children, s->num_children + 1); diff --git a/block/sheepdog.c b/block/sheepdog.c index cbdfe9ab6e..f76d6ddbbc 100644 --- a/block/sheepdog.c +++ b/block/sheepdog.c @@ -1800,7 +1800,8 @@ static int sd_prealloc(BlockDriverState *bs, int64_t old_size, int64_t new_size, void *buf = NULL; int ret; - blk = blk_new(BLK_PERM_CONSISTENT_READ | BLK_PERM_WRITE | BLK_PERM_RESIZE, + blk = blk_new(bdrv_get_aio_context(bs), + BLK_PERM_CONSISTENT_READ | BLK_PERM_WRITE | BLK_PERM_RESIZE, BLK_PERM_ALL); ret = blk_insert_bs(blk, bs, errp); diff --git a/block/trace-events b/block/trace-events index 79ccd8d824..eab51497fc 100644 --- a/block/trace-events +++ b/block/trace-events @@ -68,6 +68,7 @@ qcow2_writev_done_part(void *co, int cur_bytes) "co %p cur_bytes %d" qcow2_writev_data(void *co, uint64_t offset) "co %p offset 0x%" PRIx64 qcow2_pwrite_zeroes_start_req(void *co, int64_t offset, int count) "co %p offset 0x%" PRIx64 " count %d" qcow2_pwrite_zeroes(void *co, int64_t offset, int count) "co %p offset 0x%" PRIx64 " count %d" +qcow2_skip_cow(void *co, uint64_t offset, int nb_clusters) "co %p offset 0x%" PRIx64 " nb_clusters %d" # qcow2-cluster.c qcow2_alloc_clusters_offset(void *co, uint64_t offset, int bytes) "co %p offset 0x%" PRIx64 " bytes %d" @@ -91,6 +92,9 @@ qcow2_cache_get_done(void *co, int c, int i) "co %p is_l2_cache %d index %d" qcow2_cache_flush(void *co, int c) "co %p is_l2_cache %d" qcow2_cache_entry_flush(void *co, int c, int i) "co %p is_l2_cache %d index %d" +# qcow2-refcount.c +qcow2_process_discards_failed_region(uint64_t offset, uint64_t bytes, int ret) "offset 0x%" PRIx64 " bytes 0x%" PRIx64 " ret %d" + # qed-l2-cache.c qed_alloc_l2_cache_entry(void *l2_cache, void *entry) "l2_cache %p entry %p" qed_unref_l2_cache_entry(void *entry, int ref) "entry %p ref %d" diff --git a/block/vdi.c b/block/vdi.c index d7ef6628e7..b9845a4cbd 100644 --- a/block/vdi.c +++ b/block/vdi.c @@ -803,7 +803,8 @@ static int coroutine_fn vdi_co_do_create(BlockdevCreateOptions *create_options, goto exit; } - blk = blk_new(BLK_PERM_WRITE | BLK_PERM_RESIZE, BLK_PERM_ALL); + blk = blk_new(bdrv_get_aio_context(bs_file), + BLK_PERM_WRITE | BLK_PERM_RESIZE, BLK_PERM_ALL); ret = blk_insert_bs(blk, bs_file, errp); if (ret < 0) { goto exit; diff --git a/block/vhdx.c b/block/vhdx.c index a143a57657..d6070b6fa8 100644 --- a/block/vhdx.c +++ b/block/vhdx.c @@ -1900,7 +1900,8 @@ static int coroutine_fn vhdx_co_create(BlockdevCreateOptions *opts, return -EIO; } - blk = blk_new(BLK_PERM_WRITE | BLK_PERM_RESIZE, BLK_PERM_ALL); + blk = blk_new(bdrv_get_aio_context(bs), + BLK_PERM_WRITE | BLK_PERM_RESIZE, BLK_PERM_ALL); ret = blk_insert_bs(blk, bs, errp); if (ret < 0) { goto delete_and_exit; diff --git a/block/vmdk.c b/block/vmdk.c index de8cb859f8..51067c774f 100644 --- a/block/vmdk.c +++ b/block/vmdk.c @@ -2356,7 +2356,8 @@ static BlockBackend *vmdk_co_create_cb(int64_t size, int idx, if (!bs) { return NULL; } - blk = blk_new(BLK_PERM_CONSISTENT_READ | BLK_PERM_WRITE | BLK_PERM_RESIZE, + blk = blk_new(bdrv_get_aio_context(bs), + BLK_PERM_CONSISTENT_READ | BLK_PERM_WRITE | BLK_PERM_RESIZE, BLK_PERM_ALL); if (blk_insert_bs(blk, bs, errp)) { bdrv_unref(bs); diff --git a/block/vpc.c b/block/vpc.c index 0c279b87c8..d4776ee8a5 100644 --- a/block/vpc.c +++ b/block/vpc.c @@ -1011,7 +1011,8 @@ static int coroutine_fn vpc_co_create(BlockdevCreateOptions *opts, return -EIO; } - blk = blk_new(BLK_PERM_WRITE | BLK_PERM_RESIZE, BLK_PERM_ALL); + blk = blk_new(bdrv_get_aio_context(bs), + BLK_PERM_WRITE | BLK_PERM_RESIZE, BLK_PERM_ALL); ret = blk_insert_bs(blk, bs, errp); if (ret < 0) { goto out; diff --git a/blockdev.c b/blockdev.c index 79fbac8450..3f44b891eb 100644 --- a/blockdev.c +++ b/blockdev.c @@ -574,7 +574,7 @@ static BlockBackend *blockdev_init(const char *file, QDict *bs_opts, if ((!file || !*file) && !qdict_size(bs_opts)) { BlockBackendRootState *blk_rs; - blk = blk_new(0, BLK_PERM_ALL); + blk = blk_new(qemu_get_aio_context(), 0, BLK_PERM_ALL); blk_rs = blk_get_root_state(blk); blk_rs->open_flags = bdrv_flags; blk_rs->read_only = read_only; @@ -1535,6 +1535,7 @@ static void external_snapshot_prepare(BlkActionState *common, DO_UPCAST(ExternalSnapshotState, common, common); TransactionAction *action = common->action; AioContext *aio_context; + int ret; /* 'blockdev-snapshot' and 'blockdev-snapshot-sync' have similar * purpose but a different set of parameters */ @@ -1674,7 +1675,10 @@ static void external_snapshot_prepare(BlkActionState *common, goto out; } - bdrv_set_aio_context(state->new_bs, aio_context); + ret = bdrv_try_set_aio_context(state->new_bs, aio_context, errp); + if (ret < 0) { + goto out; + } /* This removes our old bs and adds the new bs. This is an operation that * can fail, so we need to do it in .prepare; undoing it for abort is @@ -2112,11 +2116,10 @@ static void block_dirty_bitmap_disable_abort(BlkActionState *common) } } -static BdrvDirtyBitmap *do_block_dirty_bitmap_merge(const char *node, - const char *target, - strList *bitmaps, - HBitmap **backup, - Error **errp); +static BdrvDirtyBitmap *do_block_dirty_bitmap_merge( + const char *node, const char *target, + BlockDirtyBitmapMergeSourceList *bitmaps, + HBitmap **backup, Error **errp); static void block_dirty_bitmap_merge_prepare(BlkActionState *common, Error **errp) @@ -2965,15 +2968,14 @@ void qmp_block_dirty_bitmap_disable(const char *node, const char *name, bdrv_disable_dirty_bitmap(bitmap); } -static BdrvDirtyBitmap *do_block_dirty_bitmap_merge(const char *node, - const char *target, - strList *bitmaps, - HBitmap **backup, - Error **errp) +static BdrvDirtyBitmap *do_block_dirty_bitmap_merge( + const char *node, const char *target, + BlockDirtyBitmapMergeSourceList *bitmaps, + HBitmap **backup, Error **errp) { BlockDriverState *bs; BdrvDirtyBitmap *dst, *src, *anon; - strList *lst; + BlockDirtyBitmapMergeSourceList *lst; Error *local_err = NULL; dst = block_dirty_bitmap_lookup(node, target, &bs, errp); @@ -2988,11 +2990,28 @@ static BdrvDirtyBitmap *do_block_dirty_bitmap_merge(const char *node, } for (lst = bitmaps; lst; lst = lst->next) { - src = bdrv_find_dirty_bitmap(bs, lst->value); - if (!src) { - error_setg(errp, "Dirty bitmap '%s' not found", lst->value); - dst = NULL; - goto out; + switch (lst->value->type) { + const char *name, *node; + case QTYPE_QSTRING: + name = lst->value->u.local; + src = bdrv_find_dirty_bitmap(bs, name); + if (!src) { + error_setg(errp, "Dirty bitmap '%s' not found", name); + dst = NULL; + goto out; + } + break; + case QTYPE_QDICT: + node = lst->value->u.external.node; + name = lst->value->u.external.name; + src = block_dirty_bitmap_lookup(node, name, NULL, errp); + if (!src) { + dst = NULL; + goto out; + } + break; + default: + abort(); } bdrv_merge_dirty_bitmap(anon, src, NULL, &local_err); @@ -3012,7 +3031,8 @@ static BdrvDirtyBitmap *do_block_dirty_bitmap_merge(const char *node, } void qmp_block_dirty_bitmap_merge(const char *node, const char *target, - strList *bitmaps, Error **errp) + BlockDirtyBitmapMergeSourceList *bitmaps, + Error **errp) { do_block_dirty_bitmap_merge(node, target, bitmaps, NULL, errp); } @@ -3138,7 +3158,7 @@ void qmp_block_resize(bool has_device, const char *device, goto out; } - blk = blk_new(BLK_PERM_RESIZE, BLK_PERM_ALL); + blk = blk_new(bdrv_get_aio_context(bs), BLK_PERM_RESIZE, BLK_PERM_ALL); ret = blk_insert_bs(blk, bs, errp); if (ret < 0) { goto out; @@ -3424,6 +3444,7 @@ static BlockJob *do_drive_backup(DriveBackup *backup, JobTxn *txn, int flags, job_flags = JOB_DEFAULT; int64_t size; bool set_backing_hd = false; + int ret; if (!backup->has_speed) { backup->speed = 0; @@ -3450,11 +3471,16 @@ static BlockJob *do_drive_backup(DriveBackup *backup, JobTxn *txn, backup->compress = false; } - bs = qmp_get_root_bs(backup->device, errp); + bs = bdrv_lookup_bs(backup->device, backup->device, errp); if (!bs) { return NULL; } + if (!bs->drv) { + error_setg(errp, "Device has no medium"); + return NULL; + } + aio_context = bdrv_get_aio_context(bs); aio_context_acquire(aio_context); @@ -3520,13 +3546,16 @@ static BlockJob *do_drive_backup(DriveBackup *backup, JobTxn *txn, goto out; } - bdrv_set_aio_context(target_bs, aio_context); + ret = bdrv_try_set_aio_context(target_bs, aio_context, errp); + if (ret < 0) { + bdrv_unref(target_bs); + goto out; + } if (set_backing_hd) { bdrv_set_backing_hd(target_bs, source, &local_err); if (local_err) { - bdrv_unref(target_bs); - goto out; + goto unref; } } @@ -3534,11 +3563,10 @@ static BlockJob *do_drive_backup(DriveBackup *backup, JobTxn *txn, bmap = bdrv_find_dirty_bitmap(bs, backup->bitmap); if (!bmap) { error_setg(errp, "Bitmap '%s' could not be found", backup->bitmap); - bdrv_unref(target_bs); - goto out; + goto unref; } if (bdrv_dirty_bitmap_check(bmap, BDRV_BITMAP_DEFAULT, errp)) { - goto out; + goto unref; } } if (!backup->auto_finalize) { @@ -3552,12 +3580,13 @@ static BlockJob *do_drive_backup(DriveBackup *backup, JobTxn *txn, backup->sync, bmap, backup->compress, backup->on_source_error, backup->on_target_error, job_flags, NULL, NULL, txn, &local_err); - bdrv_unref(target_bs); if (local_err != NULL) { error_propagate(errp, local_err); - goto out; + goto unref; } +unref: + bdrv_unref(target_bs); out: aio_context_release(aio_context); return job; @@ -3593,6 +3622,7 @@ BlockJob *do_blockdev_backup(BlockdevBackup *backup, JobTxn *txn, AioContext *aio_context; BlockJob *job = NULL; int job_flags = JOB_DEFAULT; + int ret; if (!backup->has_speed) { backup->speed = 0; @@ -3629,16 +3659,9 @@ BlockJob *do_blockdev_backup(BlockdevBackup *backup, JobTxn *txn, goto out; } - if (bdrv_get_aio_context(target_bs) != aio_context) { - if (!bdrv_has_blk(target_bs)) { - /* The target BDS is not attached, we can safely move it to another - * AioContext. */ - bdrv_set_aio_context(target_bs, aio_context); - } else { - error_setg(errp, "Target is attached to a different thread from " - "source."); - goto out; - } + ret = bdrv_try_set_aio_context(target_bs, aio_context, errp); + if (ret < 0) { + goto out; } if (backup->has_bitmap) { @@ -3811,6 +3834,7 @@ void qmp_drive_mirror(DriveMirror *arg, Error **errp) int flags; int64_t size; const char *format = arg->format; + int ret; bs = qmp_get_root_bs(arg->device, errp); if (!bs) { @@ -3911,7 +3935,11 @@ void qmp_drive_mirror(DriveMirror *arg, Error **errp) goto out; } - bdrv_set_aio_context(target_bs, aio_context); + ret = bdrv_try_set_aio_context(target_bs, aio_context, errp); + if (ret < 0) { + bdrv_unref(target_bs); + goto out; + } blockdev_mirror_common(arg->has_job_id ? arg->job_id : NULL, bs, target_bs, arg->has_replaces, arg->replaces, arg->sync, @@ -3955,6 +3983,7 @@ void qmp_blockdev_mirror(bool has_job_id, const char *job_id, AioContext *aio_context; BlockMirrorBackingMode backing_mode = MIRROR_LEAVE_BACKING_CHAIN; Error *local_err = NULL; + int ret; bs = qmp_get_root_bs(device, errp); if (!bs) { @@ -3969,7 +3998,10 @@ void qmp_blockdev_mirror(bool has_job_id, const char *job_id, aio_context = bdrv_get_aio_context(bs); aio_context_acquire(aio_context); - bdrv_set_aio_context(target_bs, aio_context); + ret = bdrv_try_set_aio_context(target_bs, aio_context, errp); + if (ret < 0) { + goto out; + } blockdev_mirror_common(has_job_id ? job_id : NULL, bs, target_bs, has_replaces, replaces, sync, backing_mode, @@ -3985,7 +4017,7 @@ void qmp_blockdev_mirror(bool has_job_id, const char *job_id, has_auto_dismiss, auto_dismiss, &local_err); error_propagate(errp, local_err); - +out: aio_context_release(aio_context); } @@ -4475,7 +4507,7 @@ void qmp_x_blockdev_set_iothread(const char *node_name, StrOrNull *iothread, old_context = bdrv_get_aio_context(bs); aio_context_acquire(old_context); - bdrv_set_aio_context(bs, new_context); + bdrv_try_set_aio_context(bs, new_context, errp); aio_context_release(old_context); } diff --git a/blockjob.c b/blockjob.c index 9ca942ba01..931d675c0c 100644 --- a/blockjob.c +++ b/blockjob.c @@ -204,14 +204,20 @@ int block_job_add_bdrv(BlockJob *job, const char *name, BlockDriverState *bs, { BdrvChild *c; - c = bdrv_root_attach_child(bs, name, &child_job, perm, shared_perm, - job, errp); + bdrv_ref(bs); + if (job->job.aio_context != qemu_get_aio_context()) { + aio_context_release(job->job.aio_context); + } + c = bdrv_root_attach_child(bs, name, &child_job, job->job.aio_context, + perm, shared_perm, job, errp); + if (job->job.aio_context != qemu_get_aio_context()) { + aio_context_acquire(job->job.aio_context); + } if (c == NULL) { return -EPERM; } job->nodes = g_slist_prepend(job->nodes, c); - bdrv_ref(bs); bdrv_op_block_all(bs, job->blocker); return 0; @@ -392,7 +398,7 @@ void *block_job_create(const char *job_id, const BlockJobDriver *driver, job_id = bdrv_get_device_name(bs); } - blk = blk_new(perm, shared_perm); + blk = blk_new(bdrv_get_aio_context(bs), perm, shared_perm); ret = blk_insert_bs(blk, bs, errp); if (ret < 0) { blk_unref(blk); @@ -198,7 +198,7 @@ supported_kvm_target() { i386:i386 | i386:x86_64 | i386:x32 | \ x86_64:i386 | x86_64:x86_64 | x86_64:x32 | \ mips:mips | mipsel:mips | \ - ppc:ppc | ppc64:ppc | ppc:ppc64 | ppc64:ppc64 | \ + ppc:ppc | ppc64:ppc | ppc:ppc64 | ppc64:ppc64 | ppc64:ppc64le | \ s390x:s390x) return 0 ;; @@ -502,8 +502,11 @@ cross_cc_arm="arm-linux-gnueabihf-gcc" cross_cc_cflags_armeb="-mbig-endian" cross_cc_i386="i386-pc-linux-gnu-gcc" cross_cc_cflags_i386="" -cross_cc_powerpc="powerpc-linux-gnu-gcc" -cross_cc_powerpc="powerpc-linux-gnu-gcc" +cross_cc_ppc="powerpc-linux-gnu-gcc" +cross_cc_cflags_ppc="-m32" +cross_cc_ppc64="powerpc-linux-gnu-gcc" +cross_cc_cflags_ppc64="-m64" +cross_cc_ppc64le="powerpc64le-linux-gnu-gcc" enabled_cross_compilers="" @@ -700,7 +703,11 @@ elif check_define __sparc__ ; then fi elif check_define _ARCH_PPC ; then if check_define _ARCH_PPC64 ; then - cpu="ppc64" + if check_define _LITTLE_ENDIAN ; then + cpu="ppc64le" + else + cpu="ppc64" + fi else cpu="ppc" fi @@ -731,10 +738,14 @@ ARCH= # Note that this case should only have supported host CPUs, not guests. case "$cpu" in ppc|ppc64|s390|s390x|sparc64|x32|riscv32|riscv64) - cpu="$cpu" supported_cpu="yes" eval "cross_cc_${cpu}=\$host_cc" ;; + ppc64le) + ARCH="ppc64" + supported_cpu="yes" + cross_cc_ppc64le=$host_cc + ;; i386|i486|i586|i686|i86pc|BePC) cpu="i386" supported_cpu="yes" @@ -1538,44 +1549,44 @@ case "$cpu" in ppc) CPU_CFLAGS="-m32" LDFLAGS="-m32 $LDFLAGS" - cross_cc_powerpc=$cc - cross_cc_cflags_powerpc=$CPU_CFLAGS + cross_cc_ppc=$cc + cross_cc_cflags_ppc="$CPU_CFLAGS" ;; ppc64) CPU_CFLAGS="-m64" LDFLAGS="-m64 $LDFLAGS" cross_cc_ppc64=$cc - cross_cc_cflags_ppc64=$CPU_CFLAGS + cross_cc_cflags_ppc64="$CPU_CFLAGS" ;; sparc) CPU_CFLAGS="-m32 -mv8plus -mcpu=ultrasparc" LDFLAGS="-m32 -mv8plus $LDFLAGS" cross_cc_sparc=$cc - cross_cc_cflags_sparc=$CPU_CFLAGS + cross_cc_cflags_sparc="$CPU_CFLAGS" ;; sparc64) CPU_CFLAGS="-m64 -mcpu=ultrasparc" LDFLAGS="-m64 $LDFLAGS" cross_cc_sparc64=$cc - cross_cc_cflags_sparc64=$CPU_CFLAGS + cross_cc_cflags_sparc64="$CPU_CFLAGS" ;; s390) CPU_CFLAGS="-m31" LDFLAGS="-m31 $LDFLAGS" cross_cc_s390=$cc - cross_cc_cflags_s390=$CPU_CFLAGS + cross_cc_cflags_s390="$CPU_CFLAGS" ;; s390x) CPU_CFLAGS="-m64" LDFLAGS="-m64 $LDFLAGS" cross_cc_s390x=$cc - cross_cc_cflags_s390x=$CPU_CFLAGS + cross_cc_cflags_s390x="$CPU_CFLAGS" ;; i386) CPU_CFLAGS="-m32" LDFLAGS="-m32 $LDFLAGS" cross_cc_i386=$cc - cross_cc_cflags_i386=$CPU_CFLAGS + cross_cc_cflags_i386="$CPU_CFLAGS" ;; x86_64) # ??? Only extremely old AMD cpus do not have cmpxchg16b. @@ -1584,13 +1595,13 @@ case "$cpu" in CPU_CFLAGS="-m64 -mcx16" LDFLAGS="-m64 $LDFLAGS" cross_cc_x86_64=$cc - cross_cc_cflags_x86_64=$CPU_CFLAGS + cross_cc_cflags_x86_64="$CPU_CFLAGS" ;; x32) CPU_CFLAGS="-mx32" LDFLAGS="-mx32 $LDFLAGS" cross_cc_i386=$cc - cross_cc_cflags_i386=$CPU_CFLAGS + cross_cc_cflags_i386="$CPU_CFLAGS" ;; # No special flags required for other host CPUs esac @@ -4099,6 +4110,13 @@ libs_softmmu="$libs_softmmu $fdt_libs" ########################################## # opengl probe (for sdl2, gtk, milkymist-tmu2) +gbm="no" +if $pkg_config gbm; then + gbm_cflags="$($pkg_config --cflags gbm)" + gbm_libs="$($pkg_config --libs gbm)" + gbm="yes" +fi + if test "$opengl" != "no" ; then opengl_pkgs="epoxy gbm" if $pkg_config $opengl_pkgs; then @@ -6191,7 +6209,7 @@ if { test "$cpu" = "i386" || test "$cpu" = "x86_64"; } && \ fi done fi -if test "$cpu" = "ppc64" && test "$targetos" != "Darwin" ; then +if test "$ARCH" = "ppc64" && test "$targetos" != "Darwin" ; then roms="$roms spapr-rtas" fi @@ -6434,8 +6452,6 @@ echo "gcov $gcov_tool" echo "gcov enabled $gcov" echo "TPM support $tpm" echo "libssh2 support $libssh2" -echo "TPM passthrough $tpm_passthrough" -echo "TPM emulator $tpm_emulator" echo "QOM debugging $qom_cast_debug" echo "Live block migration $live_block_migration" echo "lzo support $lzo" @@ -6964,6 +6980,13 @@ if test "$opengl" = "yes" ; then fi fi +if test "$gbm" = "yes" ; then + echo "CONFIG_GBM=y" >> $config_host_mak + echo "GBM_LIBS=$gbm_libs" >> $config_host_mak + echo "GBM_CFLAGS=$gbm_cflags" >> $config_host_mak +fi + + if test "$malloc_trim" = "yes" ; then echo "CONFIG_MALLOC_TRIM=y" >> $config_host_mak fi @@ -7133,14 +7156,6 @@ fi if test "$tpm" = "yes"; then echo 'CONFIG_TPM=$(CONFIG_SOFTMMU)' >> $config_host_mak - # TPM passthrough support? - if test "$tpm_passthrough" = "yes"; then - echo "CONFIG_TPM_PASSTHROUGH=y" >> $config_host_mak - fi - # TPM emulator support? - if test "$tpm_emulator" = "yes"; then - echo "CONFIG_TPM_EMULATOR=y" >> $config_host_mak - fi fi echo "TRACE_BACKENDS=$trace_backends" >> $config_host_mak @@ -7378,7 +7393,7 @@ if test "$linux" = "yes" ; then i386|x86_64|x32) linux_arch=x86 ;; - ppc|ppc64) + ppc|ppc64|ppc64le) linux_arch=powerpc ;; s390x) @@ -7539,7 +7554,8 @@ case "$target_name" in ;; ppc) gdb_xml_files="power-core.xml power-fpu.xml power-altivec.xml power-spe.xml" - target_compiler=$cross_cc_powerpc + target_compiler=$cross_cc_ppc + target_compiler_cflags="$cross_cc_cflags_ppc" ;; ppc64) TARGET_BASE_ARCH=ppc @@ -7547,6 +7563,7 @@ case "$target_name" in mttcg=yes gdb_xml_files="power64-core.xml power-fpu.xml power-altivec.xml power-spe.xml power-vsx.xml" target_compiler=$cross_cc_ppc64 + target_compiler_cflags="$cross_cc_cflags_ppc64" ;; ppc64le) TARGET_ARCH=ppc64 @@ -7859,6 +7876,9 @@ echo "QEMU_CFLAGS+=$cflags" >> $config_target_mak done # for target in $targets +echo "PIXMAN_CFLAGS=$pixman_cflags" >> $config_host_mak +echo "PIXMAN_LIBS=$pixman_libs" >> $config_host_mak + if test -n "$enabled_cross_compilers"; then echo echo "NOTE: cross-compilers enabled: $enabled_cross_compilers" diff --git a/contrib/libvhost-user/libvhost-user.c b/contrib/libvhost-user/libvhost-user.c index c56f2dfe44..443b7e08c3 100644 --- a/contrib/libvhost-user/libvhost-user.c +++ b/contrib/libvhost-user/libvhost-user.c @@ -130,6 +130,7 @@ vu_request_to_string(unsigned int req) REQ(VHOST_USER_POSTCOPY_END), REQ(VHOST_USER_GET_INFLIGHT_FD), REQ(VHOST_USER_SET_INFLIGHT_FD), + REQ(VHOST_USER_GPU_SET_SOCKET), REQ(VHOST_USER_MAX), }; #undef REQ diff --git a/contrib/libvhost-user/libvhost-user.h b/contrib/libvhost-user/libvhost-user.h index 78b33306e8..3b888ff0a5 100644 --- a/contrib/libvhost-user/libvhost-user.h +++ b/contrib/libvhost-user/libvhost-user.h @@ -94,6 +94,7 @@ typedef enum VhostUserRequest { VHOST_USER_POSTCOPY_END = 30, VHOST_USER_GET_INFLIGHT_FD = 31, VHOST_USER_SET_INFLIGHT_FD = 32, + VHOST_USER_GPU_SET_SOCKET = 33, VHOST_USER_MAX } VhostUserRequest; diff --git a/contrib/vhost-user-gpu/50-qemu-gpu.json.in b/contrib/vhost-user-gpu/50-qemu-gpu.json.in new file mode 100644 index 0000000000..658b545864 --- /dev/null +++ b/contrib/vhost-user-gpu/50-qemu-gpu.json.in @@ -0,0 +1,5 @@ +{ + "description": "QEMU vhost-user-gpu", + "type": "gpu", + "binary": "@libexecdir@/vhost-user-gpu", +} diff --git a/contrib/vhost-user-gpu/Makefile.objs b/contrib/vhost-user-gpu/Makefile.objs new file mode 100644 index 0000000000..6170c919e4 --- /dev/null +++ b/contrib/vhost-user-gpu/Makefile.objs @@ -0,0 +1,10 @@ +vhost-user-gpu-obj-y = main.o virgl.o vugbm.o + +main.o-cflags := $(PIXMAN_CFLAGS) $(GBM_CFLAGS) +main.o-libs := $(PIXMAN_LIBS) + +virgl.o-cflags := $(VIRGL_CFLAGS) $(GBM_CFLAGS) +virgl.o-libs := $(VIRGL_LIBS) + +vugbm.o-cflags := $(GBM_CFLAGS) +vugbm.o-libs := $(GBM_LIBS) diff --git a/contrib/vhost-user-gpu/main.c b/contrib/vhost-user-gpu/main.c new file mode 100644 index 0000000000..f9e2146b69 --- /dev/null +++ b/contrib/vhost-user-gpu/main.c @@ -0,0 +1,1185 @@ +/* + * Virtio vhost-user GPU Device + * + * Copyright Red Hat, Inc. 2013-2018 + * + * Authors: + * Dave Airlie <airlied@redhat.com> + * Gerd Hoffmann <kraxel@redhat.com> + * Marc-André Lureau <marcandre.lureau@redhat.com> + * + * This work is licensed under the terms of the GNU GPL, version 2 or later. + * See the COPYING file in the top-level directory. + */ +#include "qemu/osdep.h" +#include "qemu/drm.h" +#include "qapi/error.h" +#include "qemu/sockets.h" + +#include <pixman.h> +#include <glib-unix.h> + +#include "vugpu.h" +#include "hw/virtio/virtio-gpu-bswap.h" +#include "hw/virtio/virtio-gpu-pixman.h" +#include "virgl.h" +#include "vugbm.h" + +struct virtio_gpu_simple_resource { + uint32_t resource_id; + uint32_t width; + uint32_t height; + uint32_t format; + struct iovec *iov; + unsigned int iov_cnt; + uint32_t scanout_bitmask; + pixman_image_t *image; + struct vugbm_buffer buffer; + QTAILQ_ENTRY(virtio_gpu_simple_resource) next; +}; + +static gboolean opt_print_caps; +static int opt_fdnum = -1; +static char *opt_socket_path; +static char *opt_render_node; +static gboolean opt_virgl; + +static void vg_handle_ctrl(VuDev *dev, int qidx); + +static const char * +vg_cmd_to_string(int cmd) +{ +#define CMD(cmd) [cmd] = #cmd + static const char *vg_cmd_str[] = { + CMD(VIRTIO_GPU_UNDEFINED), + + /* 2d commands */ + CMD(VIRTIO_GPU_CMD_GET_DISPLAY_INFO), + CMD(VIRTIO_GPU_CMD_RESOURCE_CREATE_2D), + CMD(VIRTIO_GPU_CMD_RESOURCE_UNREF), + CMD(VIRTIO_GPU_CMD_SET_SCANOUT), + CMD(VIRTIO_GPU_CMD_RESOURCE_FLUSH), + CMD(VIRTIO_GPU_CMD_TRANSFER_TO_HOST_2D), + CMD(VIRTIO_GPU_CMD_RESOURCE_ATTACH_BACKING), + CMD(VIRTIO_GPU_CMD_RESOURCE_DETACH_BACKING), + CMD(VIRTIO_GPU_CMD_GET_CAPSET_INFO), + CMD(VIRTIO_GPU_CMD_GET_CAPSET), + + /* 3d commands */ + CMD(VIRTIO_GPU_CMD_CTX_CREATE), + CMD(VIRTIO_GPU_CMD_CTX_DESTROY), + CMD(VIRTIO_GPU_CMD_CTX_ATTACH_RESOURCE), + CMD(VIRTIO_GPU_CMD_CTX_DETACH_RESOURCE), + CMD(VIRTIO_GPU_CMD_RESOURCE_CREATE_3D), + CMD(VIRTIO_GPU_CMD_TRANSFER_TO_HOST_3D), + CMD(VIRTIO_GPU_CMD_TRANSFER_FROM_HOST_3D), + CMD(VIRTIO_GPU_CMD_SUBMIT_3D), + + /* cursor commands */ + CMD(VIRTIO_GPU_CMD_UPDATE_CURSOR), + CMD(VIRTIO_GPU_CMD_MOVE_CURSOR), + }; +#undef REQ + + if (cmd >= 0 && cmd < G_N_ELEMENTS(vg_cmd_str)) { + return vg_cmd_str[cmd]; + } else { + return "unknown"; + } +} + +static int +vg_sock_fd_read(int sock, void *buf, ssize_t buflen) +{ + int ret; + + do { + ret = read(sock, buf, buflen); + } while (ret < 0 && (errno == EINTR || errno == EAGAIN)); + + g_warn_if_fail(ret == buflen); + return ret; +} + +static void +vg_sock_fd_close(VuGpu *g) +{ + if (g->sock_fd >= 0) { + close(g->sock_fd); + g->sock_fd = -1; + } +} + +static gboolean +source_wait_cb(gint fd, GIOCondition condition, gpointer user_data) +{ + VuGpu *g = user_data; + + if (!vg_recv_msg(g, VHOST_USER_GPU_DMABUF_UPDATE, 0, NULL)) { + return G_SOURCE_CONTINUE; + } + + /* resume */ + g->wait_ok = 0; + vg_handle_ctrl(&g->dev.parent, 0); + + return G_SOURCE_REMOVE; +} + +void +vg_wait_ok(VuGpu *g) +{ + assert(g->wait_ok == 0); + g->wait_ok = g_unix_fd_add(g->sock_fd, G_IO_IN | G_IO_HUP, + source_wait_cb, g); +} + +static int +vg_sock_fd_write(int sock, const void *buf, ssize_t buflen, int fd) +{ + ssize_t ret; + struct msghdr msg; + struct iovec iov; + union { + struct cmsghdr cmsghdr; + char control[CMSG_SPACE(sizeof(int))]; + } cmsgu; + struct cmsghdr *cmsg; + + iov.iov_base = (void *)buf; + iov.iov_len = buflen; + + msg.msg_name = NULL; + msg.msg_namelen = 0; + msg.msg_iov = &iov; + msg.msg_iovlen = 1; + + if (fd != -1) { + msg.msg_control = cmsgu.control; + msg.msg_controllen = sizeof(cmsgu.control); + + cmsg = CMSG_FIRSTHDR(&msg); + cmsg->cmsg_len = CMSG_LEN(sizeof(int)); + cmsg->cmsg_level = SOL_SOCKET; + cmsg->cmsg_type = SCM_RIGHTS; + + *((int *)CMSG_DATA(cmsg)) = fd; + } else { + msg.msg_control = NULL; + msg.msg_controllen = 0; + } + + do { + ret = sendmsg(sock, &msg, 0); + } while (ret == -1 && (errno == EINTR || errno == EAGAIN)); + + g_warn_if_fail(ret == buflen); + return ret; +} + +void +vg_send_msg(VuGpu *vg, const VhostUserGpuMsg *msg, int fd) +{ + if (vg_sock_fd_write(vg->sock_fd, msg, + VHOST_USER_GPU_HDR_SIZE + msg->size, fd) < 0) { + vg_sock_fd_close(vg); + } +} + +bool +vg_recv_msg(VuGpu *g, uint32_t expect_req, uint32_t expect_size, + gpointer payload) +{ + uint32_t req, flags, size; + + if (vg_sock_fd_read(g->sock_fd, &req, sizeof(req)) < 0 || + vg_sock_fd_read(g->sock_fd, &flags, sizeof(flags)) < 0 || + vg_sock_fd_read(g->sock_fd, &size, sizeof(size)) < 0) { + goto err; + } + + g_return_val_if_fail(req == expect_req, false); + g_return_val_if_fail(flags & VHOST_USER_GPU_MSG_FLAG_REPLY, false); + g_return_val_if_fail(size == expect_size, false); + + if (size && vg_sock_fd_read(g->sock_fd, payload, size) != size) { + goto err; + } + + return true; + +err: + vg_sock_fd_close(g); + return false; +} + +static struct virtio_gpu_simple_resource * +virtio_gpu_find_resource(VuGpu *g, uint32_t resource_id) +{ + struct virtio_gpu_simple_resource *res; + + QTAILQ_FOREACH(res, &g->reslist, next) { + if (res->resource_id == resource_id) { + return res; + } + } + return NULL; +} + +void +vg_ctrl_response(VuGpu *g, + struct virtio_gpu_ctrl_command *cmd, + struct virtio_gpu_ctrl_hdr *resp, + size_t resp_len) +{ + size_t s; + + if (cmd->cmd_hdr.flags & VIRTIO_GPU_FLAG_FENCE) { + resp->flags |= VIRTIO_GPU_FLAG_FENCE; + resp->fence_id = cmd->cmd_hdr.fence_id; + resp->ctx_id = cmd->cmd_hdr.ctx_id; + } + virtio_gpu_ctrl_hdr_bswap(resp); + s = iov_from_buf(cmd->elem.in_sg, cmd->elem.in_num, 0, resp, resp_len); + if (s != resp_len) { + g_critical("%s: response size incorrect %zu vs %zu", + __func__, s, resp_len); + } + vu_queue_push(&g->dev.parent, cmd->vq, &cmd->elem, s); + vu_queue_notify(&g->dev.parent, cmd->vq); + cmd->finished = true; +} + +void +vg_ctrl_response_nodata(VuGpu *g, + struct virtio_gpu_ctrl_command *cmd, + enum virtio_gpu_ctrl_type type) +{ + struct virtio_gpu_ctrl_hdr resp = { + .type = type, + }; + + vg_ctrl_response(g, cmd, &resp, sizeof(resp)); +} + +void +vg_get_display_info(VuGpu *vg, struct virtio_gpu_ctrl_command *cmd) +{ + struct virtio_gpu_resp_display_info dpy_info = { {} }; + VhostUserGpuMsg msg = { + .request = VHOST_USER_GPU_GET_DISPLAY_INFO, + .size = 0, + }; + + assert(vg->wait_ok == 0); + + vg_send_msg(vg, &msg, -1); + if (!vg_recv_msg(vg, msg.request, sizeof(dpy_info), &dpy_info)) { + return; + } + + vg_ctrl_response(vg, cmd, &dpy_info.hdr, sizeof(dpy_info)); +} + +static void +vg_resource_create_2d(VuGpu *g, + struct virtio_gpu_ctrl_command *cmd) +{ + pixman_format_code_t pformat; + struct virtio_gpu_simple_resource *res; + struct virtio_gpu_resource_create_2d c2d; + + VUGPU_FILL_CMD(c2d); + virtio_gpu_bswap_32(&c2d, sizeof(c2d)); + + if (c2d.resource_id == 0) { + g_critical("%s: resource id 0 is not allowed", __func__); + cmd->error = VIRTIO_GPU_RESP_ERR_INVALID_RESOURCE_ID; + return; + } + + res = virtio_gpu_find_resource(g, c2d.resource_id); + if (res) { + g_critical("%s: resource already exists %d", __func__, c2d.resource_id); + cmd->error = VIRTIO_GPU_RESP_ERR_INVALID_RESOURCE_ID; + return; + } + + res = g_new0(struct virtio_gpu_simple_resource, 1); + res->width = c2d.width; + res->height = c2d.height; + res->format = c2d.format; + res->resource_id = c2d.resource_id; + + pformat = virtio_gpu_get_pixman_format(c2d.format); + if (!pformat) { + g_critical("%s: host couldn't handle guest format %d", + __func__, c2d.format); + g_free(res); + cmd->error = VIRTIO_GPU_RESP_ERR_INVALID_PARAMETER; + return; + } + vugbm_buffer_create(&res->buffer, &g->gdev, c2d.width, c2d.height); + res->image = pixman_image_create_bits(pformat, + c2d.width, + c2d.height, + (uint32_t *)res->buffer.mmap, + res->buffer.stride); + if (!res->image) { + g_critical("%s: resource creation failed %d %d %d", + __func__, c2d.resource_id, c2d.width, c2d.height); + g_free(res); + cmd->error = VIRTIO_GPU_RESP_ERR_OUT_OF_MEMORY; + return; + } + + QTAILQ_INSERT_HEAD(&g->reslist, res, next); +} + +static void +vg_disable_scanout(VuGpu *g, int scanout_id) +{ + struct virtio_gpu_scanout *scanout = &g->scanout[scanout_id]; + struct virtio_gpu_simple_resource *res; + + if (scanout->resource_id == 0) { + return; + } + + res = virtio_gpu_find_resource(g, scanout->resource_id); + if (res) { + res->scanout_bitmask &= ~(1 << scanout_id); + } + + scanout->width = 0; + scanout->height = 0; + + { + VhostUserGpuMsg msg = { + .request = VHOST_USER_GPU_SCANOUT, + .size = sizeof(VhostUserGpuScanout), + .payload.scanout.scanout_id = scanout_id, + }; + vg_send_msg(g, &msg, -1); + } +} + +static void +vg_resource_destroy(VuGpu *g, + struct virtio_gpu_simple_resource *res) +{ + int i; + + if (res->scanout_bitmask) { + for (i = 0; i < VIRTIO_GPU_MAX_SCANOUTS; i++) { + if (res->scanout_bitmask & (1 << i)) { + vg_disable_scanout(g, i); + } + } + } + + vugbm_buffer_destroy(&res->buffer); + pixman_image_unref(res->image); + QTAILQ_REMOVE(&g->reslist, res, next); + g_free(res); +} + +static void +vg_resource_unref(VuGpu *g, + struct virtio_gpu_ctrl_command *cmd) +{ + struct virtio_gpu_simple_resource *res; + struct virtio_gpu_resource_unref unref; + + VUGPU_FILL_CMD(unref); + virtio_gpu_bswap_32(&unref, sizeof(unref)); + + res = virtio_gpu_find_resource(g, unref.resource_id); + if (!res) { + g_critical("%s: illegal resource specified %d", + __func__, unref.resource_id); + cmd->error = VIRTIO_GPU_RESP_ERR_INVALID_RESOURCE_ID; + return; + } + vg_resource_destroy(g, res); +} + +int +vg_create_mapping_iov(VuGpu *g, + struct virtio_gpu_resource_attach_backing *ab, + struct virtio_gpu_ctrl_command *cmd, + struct iovec **iov) +{ + struct virtio_gpu_mem_entry *ents; + size_t esize, s; + int i; + + if (ab->nr_entries > 16384) { + g_critical("%s: nr_entries is too big (%d > 16384)", + __func__, ab->nr_entries); + return -1; + } + + esize = sizeof(*ents) * ab->nr_entries; + ents = g_malloc(esize); + s = iov_to_buf(cmd->elem.out_sg, cmd->elem.out_num, + sizeof(*ab), ents, esize); + if (s != esize) { + g_critical("%s: command data size incorrect %zu vs %zu", + __func__, s, esize); + g_free(ents); + return -1; + } + + *iov = g_malloc0(sizeof(struct iovec) * ab->nr_entries); + for (i = 0; i < ab->nr_entries; i++) { + uint64_t len = ents[i].length; + (*iov)[i].iov_len = ents[i].length; + (*iov)[i].iov_base = vu_gpa_to_va(&g->dev.parent, &len, ents[i].addr); + if (!(*iov)[i].iov_base || len != ents[i].length) { + g_critical("%s: resource %d element %d", + __func__, ab->resource_id, i); + g_free(*iov); + g_free(ents); + *iov = NULL; + return -1; + } + } + g_free(ents); + return 0; +} + +static void +vg_resource_attach_backing(VuGpu *g, + struct virtio_gpu_ctrl_command *cmd) +{ + struct virtio_gpu_simple_resource *res; + struct virtio_gpu_resource_attach_backing ab; + int ret; + + VUGPU_FILL_CMD(ab); + virtio_gpu_bswap_32(&ab, sizeof(ab)); + + res = virtio_gpu_find_resource(g, ab.resource_id); + if (!res) { + g_critical("%s: illegal resource specified %d", + __func__, ab.resource_id); + cmd->error = VIRTIO_GPU_RESP_ERR_INVALID_RESOURCE_ID; + return; + } + + ret = vg_create_mapping_iov(g, &ab, cmd, &res->iov); + if (ret != 0) { + cmd->error = VIRTIO_GPU_RESP_ERR_UNSPEC; + return; + } + + res->iov_cnt = ab.nr_entries; +} + +static void +vg_resource_detach_backing(VuGpu *g, + struct virtio_gpu_ctrl_command *cmd) +{ + struct virtio_gpu_simple_resource *res; + struct virtio_gpu_resource_detach_backing detach; + + VUGPU_FILL_CMD(detach); + virtio_gpu_bswap_32(&detach, sizeof(detach)); + + res = virtio_gpu_find_resource(g, detach.resource_id); + if (!res || !res->iov) { + g_critical("%s: illegal resource specified %d", + __func__, detach.resource_id); + cmd->error = VIRTIO_GPU_RESP_ERR_INVALID_RESOURCE_ID; + return; + } + + g_free(res->iov); + res->iov = NULL; + res->iov_cnt = 0; +} + +static void +vg_transfer_to_host_2d(VuGpu *g, + struct virtio_gpu_ctrl_command *cmd) +{ + struct virtio_gpu_simple_resource *res; + int h; + uint32_t src_offset, dst_offset, stride; + int bpp; + pixman_format_code_t format; + struct virtio_gpu_transfer_to_host_2d t2d; + + VUGPU_FILL_CMD(t2d); + virtio_gpu_t2d_bswap(&t2d); + + res = virtio_gpu_find_resource(g, t2d.resource_id); + if (!res || !res->iov) { + g_critical("%s: illegal resource specified %d", + __func__, t2d.resource_id); + cmd->error = VIRTIO_GPU_RESP_ERR_INVALID_RESOURCE_ID; + return; + } + + if (t2d.r.x > res->width || + t2d.r.y > res->height || + t2d.r.width > res->width || + t2d.r.height > res->height || + t2d.r.x + t2d.r.width > res->width || + t2d.r.y + t2d.r.height > res->height) { + g_critical("%s: transfer bounds outside resource" + " bounds for resource %d: %d %d %d %d vs %d %d", + __func__, t2d.resource_id, t2d.r.x, t2d.r.y, + t2d.r.width, t2d.r.height, res->width, res->height); + cmd->error = VIRTIO_GPU_RESP_ERR_INVALID_PARAMETER; + return; + } + + format = pixman_image_get_format(res->image); + bpp = (PIXMAN_FORMAT_BPP(format) + 7) / 8; + stride = pixman_image_get_stride(res->image); + + if (t2d.offset || t2d.r.x || t2d.r.y || + t2d.r.width != pixman_image_get_width(res->image)) { + void *img_data = pixman_image_get_data(res->image); + for (h = 0; h < t2d.r.height; h++) { + src_offset = t2d.offset + stride * h; + dst_offset = (t2d.r.y + h) * stride + (t2d.r.x * bpp); + + iov_to_buf(res->iov, res->iov_cnt, src_offset, + img_data + + dst_offset, t2d.r.width * bpp); + } + } else { + iov_to_buf(res->iov, res->iov_cnt, 0, + pixman_image_get_data(res->image), + pixman_image_get_stride(res->image) + * pixman_image_get_height(res->image)); + } +} + +static void +vg_set_scanout(VuGpu *g, + struct virtio_gpu_ctrl_command *cmd) +{ + struct virtio_gpu_simple_resource *res, *ores; + struct virtio_gpu_scanout *scanout; + struct virtio_gpu_set_scanout ss; + int fd; + + VUGPU_FILL_CMD(ss); + virtio_gpu_bswap_32(&ss, sizeof(ss)); + + if (ss.scanout_id >= VIRTIO_GPU_MAX_SCANOUTS) { + g_critical("%s: illegal scanout id specified %d", + __func__, ss.scanout_id); + cmd->error = VIRTIO_GPU_RESP_ERR_INVALID_SCANOUT_ID; + return; + } + + if (ss.resource_id == 0) { + vg_disable_scanout(g, ss.scanout_id); + return; + } + + /* create a surface for this scanout */ + res = virtio_gpu_find_resource(g, ss.resource_id); + if (!res) { + g_critical("%s: illegal resource specified %d", + __func__, ss.resource_id); + cmd->error = VIRTIO_GPU_RESP_ERR_INVALID_RESOURCE_ID; + return; + } + + if (ss.r.x > res->width || + ss.r.y > res->height || + ss.r.width > res->width || + ss.r.height > res->height || + ss.r.x + ss.r.width > res->width || + ss.r.y + ss.r.height > res->height) { + g_critical("%s: illegal scanout %d bounds for" + " resource %d, (%d,%d)+%d,%d vs %d %d", + __func__, ss.scanout_id, ss.resource_id, ss.r.x, ss.r.y, + ss.r.width, ss.r.height, res->width, res->height); + cmd->error = VIRTIO_GPU_RESP_ERR_INVALID_PARAMETER; + return; + } + + scanout = &g->scanout[ss.scanout_id]; + + ores = virtio_gpu_find_resource(g, scanout->resource_id); + if (ores) { + ores->scanout_bitmask &= ~(1 << ss.scanout_id); + } + + res->scanout_bitmask |= (1 << ss.scanout_id); + scanout->resource_id = ss.resource_id; + scanout->x = ss.r.x; + scanout->y = ss.r.y; + scanout->width = ss.r.width; + scanout->height = ss.r.height; + + struct vugbm_buffer *buffer = &res->buffer; + + if (vugbm_buffer_can_get_dmabuf_fd(buffer)) { + VhostUserGpuMsg msg = { + .request = VHOST_USER_GPU_DMABUF_SCANOUT, + .size = sizeof(VhostUserGpuDMABUFScanout), + .payload.dmabuf_scanout = (VhostUserGpuDMABUFScanout) { + .scanout_id = ss.scanout_id, + .x = ss.r.x, + .y = ss.r.y, + .width = ss.r.width, + .height = ss.r.height, + .fd_width = buffer->width, + .fd_height = buffer->height, + .fd_stride = buffer->stride, + .fd_drm_fourcc = buffer->format + } + }; + + if (vugbm_buffer_get_dmabuf_fd(buffer, &fd)) { + vg_send_msg(g, &msg, fd); + close(fd); + } + } else { + VhostUserGpuMsg msg = { + .request = VHOST_USER_GPU_SCANOUT, + .size = sizeof(VhostUserGpuScanout), + .payload.scanout = (VhostUserGpuScanout) { + .scanout_id = ss.scanout_id, + .width = scanout->width, + .height = scanout->height + } + }; + vg_send_msg(g, &msg, -1); + } +} + +static void +vg_resource_flush(VuGpu *g, + struct virtio_gpu_ctrl_command *cmd) +{ + struct virtio_gpu_simple_resource *res; + struct virtio_gpu_resource_flush rf; + pixman_region16_t flush_region; + int i; + + VUGPU_FILL_CMD(rf); + virtio_gpu_bswap_32(&rf, sizeof(rf)); + + res = virtio_gpu_find_resource(g, rf.resource_id); + if (!res) { + g_critical("%s: illegal resource specified %d\n", + __func__, rf.resource_id); + cmd->error = VIRTIO_GPU_RESP_ERR_INVALID_RESOURCE_ID; + return; + } + + if (rf.r.x > res->width || + rf.r.y > res->height || + rf.r.width > res->width || + rf.r.height > res->height || + rf.r.x + rf.r.width > res->width || + rf.r.y + rf.r.height > res->height) { + g_critical("%s: flush bounds outside resource" + " bounds for resource %d: %d %d %d %d vs %d %d\n", + __func__, rf.resource_id, rf.r.x, rf.r.y, + rf.r.width, rf.r.height, res->width, res->height); + cmd->error = VIRTIO_GPU_RESP_ERR_INVALID_PARAMETER; + return; + } + + pixman_region_init_rect(&flush_region, + rf.r.x, rf.r.y, rf.r.width, rf.r.height); + for (i = 0; i < VIRTIO_GPU_MAX_SCANOUTS; i++) { + struct virtio_gpu_scanout *scanout; + pixman_region16_t region, finalregion; + pixman_box16_t *extents; + + if (!(res->scanout_bitmask & (1 << i))) { + continue; + } + scanout = &g->scanout[i]; + + pixman_region_init(&finalregion); + pixman_region_init_rect(®ion, scanout->x, scanout->y, + scanout->width, scanout->height); + + pixman_region_intersect(&finalregion, &flush_region, ®ion); + + extents = pixman_region_extents(&finalregion); + size_t width = extents->x2 - extents->x1; + size_t height = extents->y2 - extents->y1; + + if (vugbm_buffer_can_get_dmabuf_fd(&res->buffer)) { + VhostUserGpuMsg vmsg = { + .request = VHOST_USER_GPU_DMABUF_UPDATE, + .size = sizeof(VhostUserGpuUpdate), + .payload.update = (VhostUserGpuUpdate) { + .scanout_id = i, + .x = extents->x1, + .y = extents->y1, + .width = width, + .height = height, + } + }; + vg_send_msg(g, &vmsg, -1); + vg_wait_ok(g); + } else { + size_t bpp = + PIXMAN_FORMAT_BPP(pixman_image_get_format(res->image)) / 8; + size_t size = width * height * bpp; + + void *p = g_malloc(VHOST_USER_GPU_HDR_SIZE + + sizeof(VhostUserGpuUpdate) + size); + VhostUserGpuMsg *msg = p; + msg->request = VHOST_USER_GPU_UPDATE; + msg->size = sizeof(VhostUserGpuUpdate) + size; + msg->payload.update = (VhostUserGpuUpdate) { + .scanout_id = i, + .x = extents->x1, + .y = extents->y1, + .width = width, + .height = height, + }; + pixman_image_t *i = + pixman_image_create_bits(pixman_image_get_format(res->image), + msg->payload.update.width, + msg->payload.update.height, + p + offsetof(VhostUserGpuMsg, + payload.update.data), + width * bpp); + pixman_image_composite(PIXMAN_OP_SRC, + res->image, NULL, i, + extents->x1, extents->y1, + 0, 0, 0, 0, + width, height); + pixman_image_unref(i); + vg_send_msg(g, msg, -1); + g_free(msg); + } + pixman_region_fini(®ion); + pixman_region_fini(&finalregion); + } + pixman_region_fini(&flush_region); +} + +static void +vg_process_cmd(VuGpu *vg, struct virtio_gpu_ctrl_command *cmd) +{ + switch (cmd->cmd_hdr.type) { + case VIRTIO_GPU_CMD_GET_DISPLAY_INFO: + vg_get_display_info(vg, cmd); + break; + case VIRTIO_GPU_CMD_RESOURCE_CREATE_2D: + vg_resource_create_2d(vg, cmd); + break; + case VIRTIO_GPU_CMD_RESOURCE_UNREF: + vg_resource_unref(vg, cmd); + break; + case VIRTIO_GPU_CMD_RESOURCE_FLUSH: + vg_resource_flush(vg, cmd); + break; + case VIRTIO_GPU_CMD_TRANSFER_TO_HOST_2D: + vg_transfer_to_host_2d(vg, cmd); + break; + case VIRTIO_GPU_CMD_SET_SCANOUT: + vg_set_scanout(vg, cmd); + break; + case VIRTIO_GPU_CMD_RESOURCE_ATTACH_BACKING: + vg_resource_attach_backing(vg, cmd); + break; + case VIRTIO_GPU_CMD_RESOURCE_DETACH_BACKING: + vg_resource_detach_backing(vg, cmd); + break; + /* case VIRTIO_GPU_CMD_GET_EDID: */ + /* break */ + default: + g_warning("TODO handle ctrl %x\n", cmd->cmd_hdr.type); + cmd->error = VIRTIO_GPU_RESP_ERR_UNSPEC; + break; + } + if (!cmd->finished) { + vg_ctrl_response_nodata(vg, cmd, cmd->error ? cmd->error : + VIRTIO_GPU_RESP_OK_NODATA); + } +} + +static void +vg_handle_ctrl(VuDev *dev, int qidx) +{ + VuGpu *vg = container_of(dev, VuGpu, dev.parent); + VuVirtq *vq = vu_get_queue(dev, qidx); + struct virtio_gpu_ctrl_command *cmd = NULL; + size_t len; + + for (;;) { + if (vg->wait_ok != 0) { + return; + } + + cmd = vu_queue_pop(dev, vq, sizeof(struct virtio_gpu_ctrl_command)); + if (!cmd) { + break; + } + cmd->vq = vq; + cmd->error = 0; + cmd->finished = false; + + len = iov_to_buf(cmd->elem.out_sg, cmd->elem.out_num, + 0, &cmd->cmd_hdr, sizeof(cmd->cmd_hdr)); + if (len != sizeof(cmd->cmd_hdr)) { + g_warning("%s: command size incorrect %zu vs %zu\n", + __func__, len, sizeof(cmd->cmd_hdr)); + } + + virtio_gpu_ctrl_hdr_bswap(&cmd->cmd_hdr); + g_debug("%d %s\n", cmd->cmd_hdr.type, + vg_cmd_to_string(cmd->cmd_hdr.type)); + + if (vg->virgl) { + vg_virgl_process_cmd(vg, cmd); + } else { + vg_process_cmd(vg, cmd); + } + + if (!cmd->finished) { + QTAILQ_INSERT_TAIL(&vg->fenceq, cmd, next); + vg->inflight++; + } else { + g_free(cmd); + } + } +} + +static void +update_cursor_data_simple(VuGpu *g, uint32_t resource_id, gpointer data) +{ + struct virtio_gpu_simple_resource *res; + + res = virtio_gpu_find_resource(g, resource_id); + g_return_if_fail(res != NULL); + g_return_if_fail(pixman_image_get_width(res->image) == 64); + g_return_if_fail(pixman_image_get_height(res->image) == 64); + g_return_if_fail( + PIXMAN_FORMAT_BPP(pixman_image_get_format(res->image)) == 32); + + memcpy(data, pixman_image_get_data(res->image), 64 * 64 * sizeof(uint32_t)); +} + +static void +vg_process_cursor_cmd(VuGpu *g, struct virtio_gpu_update_cursor *cursor) +{ + bool move = cursor->hdr.type != VIRTIO_GPU_CMD_MOVE_CURSOR; + + g_debug("%s move:%d\n", G_STRFUNC, move); + + if (move) { + VhostUserGpuMsg msg = { + .request = cursor->resource_id ? + VHOST_USER_GPU_CURSOR_POS : VHOST_USER_GPU_CURSOR_POS_HIDE, + .size = sizeof(VhostUserGpuCursorPos), + .payload.cursor_pos = { + .scanout_id = cursor->pos.scanout_id, + .x = cursor->pos.x, + .y = cursor->pos.y, + } + }; + vg_send_msg(g, &msg, -1); + } else { + VhostUserGpuMsg msg = { + .request = VHOST_USER_GPU_CURSOR_UPDATE, + .size = sizeof(VhostUserGpuCursorUpdate), + .payload.cursor_update = { + .pos = { + .scanout_id = cursor->pos.scanout_id, + .x = cursor->pos.x, + .y = cursor->pos.y, + }, + .hot_x = cursor->hot_x, + .hot_y = cursor->hot_y, + } + }; + if (g->virgl) { + vg_virgl_update_cursor_data(g, cursor->resource_id, + msg.payload.cursor_update.data); + } else { + update_cursor_data_simple(g, cursor->resource_id, + msg.payload.cursor_update.data); + } + vg_send_msg(g, &msg, -1); + } +} + +static void +vg_handle_cursor(VuDev *dev, int qidx) +{ + VuGpu *g = container_of(dev, VuGpu, dev.parent); + VuVirtq *vq = vu_get_queue(dev, qidx); + VuVirtqElement *elem; + size_t len; + struct virtio_gpu_update_cursor cursor; + + for (;;) { + elem = vu_queue_pop(dev, vq, sizeof(VuVirtqElement)); + if (!elem) { + break; + } + g_debug("cursor out:%d in:%d\n", elem->out_num, elem->in_num); + + len = iov_to_buf(elem->out_sg, elem->out_num, + 0, &cursor, sizeof(cursor)); + if (len != sizeof(cursor)) { + g_warning("%s: cursor size incorrect %zu vs %zu\n", + __func__, len, sizeof(cursor)); + } else { + virtio_gpu_bswap_32(&cursor, sizeof(cursor)); + vg_process_cursor_cmd(g, &cursor); + } + vu_queue_push(dev, vq, elem, 0); + vu_queue_notify(dev, vq); + g_free(elem); + } +} + +static void +vg_panic(VuDev *dev, const char *msg) +{ + g_critical("%s\n", msg); + exit(1); +} + +static void +vg_queue_set_started(VuDev *dev, int qidx, bool started) +{ + VuVirtq *vq = vu_get_queue(dev, qidx); + + g_debug("queue started %d:%d\n", qidx, started); + + switch (qidx) { + case 0: + vu_set_queue_handler(dev, vq, started ? vg_handle_ctrl : NULL); + break; + case 1: + vu_set_queue_handler(dev, vq, started ? vg_handle_cursor : NULL); + break; + default: + break; + } +} + +static void +set_gpu_protocol_features(VuGpu *g) +{ + uint64_t u64; + VhostUserGpuMsg msg = { + .request = VHOST_USER_GPU_GET_PROTOCOL_FEATURES + }; + + assert(g->wait_ok == 0); + vg_send_msg(g, &msg, -1); + if (!vg_recv_msg(g, msg.request, sizeof(u64), &u64)) { + return; + } + + msg = (VhostUserGpuMsg) { + .request = VHOST_USER_GPU_SET_PROTOCOL_FEATURES, + .size = sizeof(uint64_t), + .payload.u64 = 0 + }; + vg_send_msg(g, &msg, -1); +} + +static int +vg_process_msg(VuDev *dev, VhostUserMsg *msg, int *do_reply) +{ + VuGpu *g = container_of(dev, VuGpu, dev.parent); + + switch (msg->request) { + case VHOST_USER_GPU_SET_SOCKET: { + g_return_val_if_fail(msg->fd_num == 1, 1); + g_return_val_if_fail(g->sock_fd == -1, 1); + g->sock_fd = msg->fds[0]; + set_gpu_protocol_features(g); + return 1; + } + default: + return 0; + } + + return 0; +} + +static uint64_t +vg_get_features(VuDev *dev) +{ + uint64_t features = 0; + + if (opt_virgl) { + features |= 1 << VIRTIO_GPU_F_VIRGL; + } + + return features; +} + +static void +vg_set_features(VuDev *dev, uint64_t features) +{ + VuGpu *g = container_of(dev, VuGpu, dev.parent); + bool virgl = features & (1 << VIRTIO_GPU_F_VIRGL); + + if (virgl && !g->virgl_inited) { + if (!vg_virgl_init(g)) { + vg_panic(dev, "Failed to initialize virgl"); + } + g->virgl_inited = true; + } + + g->virgl = virgl; +} + +static int +vg_get_config(VuDev *dev, uint8_t *config, uint32_t len) +{ + VuGpu *g = container_of(dev, VuGpu, dev.parent); + + g_return_val_if_fail(len <= sizeof(struct virtio_gpu_config), -1); + + if (opt_virgl) { + g->virtio_config.num_capsets = vg_virgl_get_num_capsets(); + } + + memcpy(config, &g->virtio_config, len); + + return 0; +} + +static int +vg_set_config(VuDev *dev, const uint8_t *data, + uint32_t offset, uint32_t size, + uint32_t flags) +{ + VuGpu *g = container_of(dev, VuGpu, dev.parent); + struct virtio_gpu_config *config = (struct virtio_gpu_config *)data; + + if (config->events_clear) { + g->virtio_config.events_read &= ~config->events_clear; + } + + return 0; +} + +static const VuDevIface vuiface = { + .set_features = vg_set_features, + .get_features = vg_get_features, + .queue_set_started = vg_queue_set_started, + .process_msg = vg_process_msg, + .get_config = vg_get_config, + .set_config = vg_set_config, +}; + +static void +vg_destroy(VuGpu *g) +{ + struct virtio_gpu_simple_resource *res, *tmp; + + vug_deinit(&g->dev); + + vg_sock_fd_close(g); + + QTAILQ_FOREACH_SAFE(res, &g->reslist, next, tmp) { + vg_resource_destroy(g, res); + } + + vugbm_device_destroy(&g->gdev); +} + +static GOptionEntry entries[] = { + { "print-capabilities", 'c', 0, G_OPTION_ARG_NONE, &opt_print_caps, + "Print capabilities", NULL }, + { "fd", 'f', 0, G_OPTION_ARG_INT, &opt_fdnum, + "Use inherited fd socket", "FDNUM" }, + { "socket-path", 's', 0, G_OPTION_ARG_FILENAME, &opt_socket_path, + "Use UNIX socket path", "PATH" }, + { "render-node", 'r', 0, G_OPTION_ARG_FILENAME, &opt_render_node, + "Specify DRM render node", "PATH" }, + { "virgl", 'v', 0, G_OPTION_ARG_NONE, &opt_virgl, + "Turn virgl rendering on", NULL }, + { NULL, } +}; + +int +main(int argc, char *argv[]) +{ + GOptionContext *context; + GError *error = NULL; + GMainLoop *loop = NULL; + int fd; + VuGpu g = { .sock_fd = -1, .drm_rnode_fd = -1 }; + + QTAILQ_INIT(&g.reslist); + QTAILQ_INIT(&g.fenceq); + + context = g_option_context_new("QEMU vhost-user-gpu"); + g_option_context_add_main_entries(context, entries, NULL); + if (!g_option_context_parse(context, &argc, &argv, &error)) { + g_printerr("Option parsing failed: %s\n", error->message); + exit(EXIT_FAILURE); + } + g_option_context_free(context); + + if (opt_print_caps) { + g_print("{\n"); + g_print(" \"type\": \"gpu\",\n"); + g_print(" \"features\": [\n"); + g_print(" \"render-node\",\n"); + g_print(" \"virgl\"\n"); + g_print(" ]\n"); + g_print("}\n"); + exit(EXIT_SUCCESS); + } + + g.drm_rnode_fd = qemu_drm_rendernode_open(opt_render_node); + if (opt_render_node && g.drm_rnode_fd == -1) { + g_printerr("Failed to open DRM rendernode.\n"); + exit(EXIT_FAILURE); + } + + if (g.drm_rnode_fd >= 0) { + if (!vugbm_device_init(&g.gdev, g.drm_rnode_fd)) { + g_warning("Failed to init DRM device, using fallback path"); + } + } + + if ((!!opt_socket_path + (opt_fdnum != -1)) != 1) { + g_printerr("Please specify either --fd or --socket-path\n"); + exit(EXIT_FAILURE); + } + + if (opt_socket_path) { + int lsock = unix_listen(opt_socket_path, &error_fatal); + fd = accept(lsock, NULL, NULL); + close(lsock); + } else { + fd = opt_fdnum; + } + if (fd == -1) { + g_printerr("Invalid socket"); + exit(EXIT_FAILURE); + } + + vug_init(&g.dev, fd, vg_panic, &vuiface); + + loop = g_main_loop_new(NULL, FALSE); + g_main_loop_run(loop); + g_main_loop_unref(loop); + + vg_destroy(&g); + if (g.drm_rnode_fd >= 0) { + close(g.drm_rnode_fd); + } + + return 0; +} diff --git a/contrib/vhost-user-gpu/virgl.c b/contrib/vhost-user-gpu/virgl.c new file mode 100644 index 0000000000..43413e29df --- /dev/null +++ b/contrib/vhost-user-gpu/virgl.c @@ -0,0 +1,579 @@ +/* + * Virtio vhost-user GPU Device + * + * Copyright Red Hat, Inc. 2013-2018 + * + * Authors: + * Dave Airlie <airlied@redhat.com> + * Gerd Hoffmann <kraxel@redhat.com> + * Marc-André Lureau <marcandre.lureau@redhat.com> + * + * This work is licensed under the terms of the GNU GPL, version 2 or later. + * See the COPYING file in the top-level directory. + */ + +#include <virglrenderer.h> +#include "virgl.h" + +void +vg_virgl_update_cursor_data(VuGpu *g, uint32_t resource_id, + gpointer data) +{ + uint32_t width, height; + uint32_t *cursor; + + cursor = virgl_renderer_get_cursor_data(resource_id, &width, &height); + g_return_if_fail(cursor != NULL); + g_return_if_fail(width == 64); + g_return_if_fail(height == 64); + + memcpy(data, cursor, 64 * 64 * sizeof(uint32_t)); + free(cursor); +} + +static void +virgl_cmd_context_create(VuGpu *g, + struct virtio_gpu_ctrl_command *cmd) +{ + struct virtio_gpu_ctx_create cc; + + VUGPU_FILL_CMD(cc); + + virgl_renderer_context_create(cc.hdr.ctx_id, cc.nlen, + cc.debug_name); +} + +static void +virgl_cmd_context_destroy(VuGpu *g, + struct virtio_gpu_ctrl_command *cmd) +{ + struct virtio_gpu_ctx_destroy cd; + + VUGPU_FILL_CMD(cd); + + virgl_renderer_context_destroy(cd.hdr.ctx_id); +} + +static void +virgl_cmd_create_resource_2d(VuGpu *g, + struct virtio_gpu_ctrl_command *cmd) +{ + struct virtio_gpu_resource_create_2d c2d; + struct virgl_renderer_resource_create_args args; + + VUGPU_FILL_CMD(c2d); + + args.handle = c2d.resource_id; + args.target = 2; + args.format = c2d.format; + args.bind = (1 << 1); + args.width = c2d.width; + args.height = c2d.height; + args.depth = 1; + args.array_size = 1; + args.last_level = 0; + args.nr_samples = 0; + args.flags = VIRTIO_GPU_RESOURCE_FLAG_Y_0_TOP; + virgl_renderer_resource_create(&args, NULL, 0); +} + +static void +virgl_cmd_create_resource_3d(VuGpu *g, + struct virtio_gpu_ctrl_command *cmd) +{ + struct virtio_gpu_resource_create_3d c3d; + struct virgl_renderer_resource_create_args args; + + VUGPU_FILL_CMD(c3d); + + args.handle = c3d.resource_id; + args.target = c3d.target; + args.format = c3d.format; + args.bind = c3d.bind; + args.width = c3d.width; + args.height = c3d.height; + args.depth = c3d.depth; + args.array_size = c3d.array_size; + args.last_level = c3d.last_level; + args.nr_samples = c3d.nr_samples; + args.flags = c3d.flags; + virgl_renderer_resource_create(&args, NULL, 0); +} + +static void +virgl_cmd_resource_unref(VuGpu *g, + struct virtio_gpu_ctrl_command *cmd) +{ + struct virtio_gpu_resource_unref unref; + + VUGPU_FILL_CMD(unref); + + virgl_renderer_resource_unref(unref.resource_id); +} + +/* Not yet(?) defined in standard-headers, remove when possible */ +#ifndef VIRTIO_GPU_CAPSET_VIRGL2 +#define VIRTIO_GPU_CAPSET_VIRGL2 2 +#endif + +static void +virgl_cmd_get_capset_info(VuGpu *g, + struct virtio_gpu_ctrl_command *cmd) +{ + struct virtio_gpu_get_capset_info info; + struct virtio_gpu_resp_capset_info resp; + + VUGPU_FILL_CMD(info); + + if (info.capset_index == 0) { + resp.capset_id = VIRTIO_GPU_CAPSET_VIRGL; + virgl_renderer_get_cap_set(resp.capset_id, + &resp.capset_max_version, + &resp.capset_max_size); + } else if (info.capset_index == 1) { + resp.capset_id = VIRTIO_GPU_CAPSET_VIRGL2; + virgl_renderer_get_cap_set(resp.capset_id, + &resp.capset_max_version, + &resp.capset_max_size); + } else { + resp.capset_max_version = 0; + resp.capset_max_size = 0; + } + resp.hdr.type = VIRTIO_GPU_RESP_OK_CAPSET_INFO; + vg_ctrl_response(g, cmd, &resp.hdr, sizeof(resp)); +} + +uint32_t +vg_virgl_get_num_capsets(void) +{ + uint32_t capset2_max_ver, capset2_max_size; + virgl_renderer_get_cap_set(VIRTIO_GPU_CAPSET_VIRGL2, + &capset2_max_ver, + &capset2_max_size); + + return capset2_max_ver ? 2 : 1; +} + +static void +virgl_cmd_get_capset(VuGpu *g, + struct virtio_gpu_ctrl_command *cmd) +{ + struct virtio_gpu_get_capset gc; + struct virtio_gpu_resp_capset *resp; + uint32_t max_ver, max_size; + + VUGPU_FILL_CMD(gc); + + virgl_renderer_get_cap_set(gc.capset_id, &max_ver, + &max_size); + resp = g_malloc0(sizeof(*resp) + max_size); + + resp->hdr.type = VIRTIO_GPU_RESP_OK_CAPSET; + virgl_renderer_fill_caps(gc.capset_id, + gc.capset_version, + (void *)resp->capset_data); + vg_ctrl_response(g, cmd, &resp->hdr, sizeof(*resp) + max_size); + g_free(resp); +} + +static void +virgl_cmd_submit_3d(VuGpu *g, + struct virtio_gpu_ctrl_command *cmd) +{ + struct virtio_gpu_cmd_submit cs; + void *buf; + size_t s; + + VUGPU_FILL_CMD(cs); + + buf = g_malloc(cs.size); + s = iov_to_buf(cmd->elem.out_sg, cmd->elem.out_num, + sizeof(cs), buf, cs.size); + if (s != cs.size) { + g_critical("%s: size mismatch (%zd/%d)", __func__, s, cs.size); + cmd->error = VIRTIO_GPU_RESP_ERR_INVALID_PARAMETER; + goto out; + } + + virgl_renderer_submit_cmd(buf, cs.hdr.ctx_id, cs.size / 4); + +out: + g_free(buf); +} + +static void +virgl_cmd_transfer_to_host_2d(VuGpu *g, + struct virtio_gpu_ctrl_command *cmd) +{ + struct virtio_gpu_transfer_to_host_2d t2d; + struct virtio_gpu_box box; + + VUGPU_FILL_CMD(t2d); + + box.x = t2d.r.x; + box.y = t2d.r.y; + box.z = 0; + box.w = t2d.r.width; + box.h = t2d.r.height; + box.d = 1; + + virgl_renderer_transfer_write_iov(t2d.resource_id, + 0, + 0, + 0, + 0, + (struct virgl_box *)&box, + t2d.offset, NULL, 0); +} + +static void +virgl_cmd_transfer_to_host_3d(VuGpu *g, + struct virtio_gpu_ctrl_command *cmd) +{ + struct virtio_gpu_transfer_host_3d t3d; + + VUGPU_FILL_CMD(t3d); + + virgl_renderer_transfer_write_iov(t3d.resource_id, + t3d.hdr.ctx_id, + t3d.level, + t3d.stride, + t3d.layer_stride, + (struct virgl_box *)&t3d.box, + t3d.offset, NULL, 0); +} + +static void +virgl_cmd_transfer_from_host_3d(VuGpu *g, + struct virtio_gpu_ctrl_command *cmd) +{ + struct virtio_gpu_transfer_host_3d tf3d; + + VUGPU_FILL_CMD(tf3d); + + virgl_renderer_transfer_read_iov(tf3d.resource_id, + tf3d.hdr.ctx_id, + tf3d.level, + tf3d.stride, + tf3d.layer_stride, + (struct virgl_box *)&tf3d.box, + tf3d.offset, NULL, 0); +} + +static void +virgl_resource_attach_backing(VuGpu *g, + struct virtio_gpu_ctrl_command *cmd) +{ + struct virtio_gpu_resource_attach_backing att_rb; + struct iovec *res_iovs; + int ret; + + VUGPU_FILL_CMD(att_rb); + + ret = vg_create_mapping_iov(g, &att_rb, cmd, &res_iovs); + if (ret != 0) { + cmd->error = VIRTIO_GPU_RESP_ERR_UNSPEC; + return; + } + + virgl_renderer_resource_attach_iov(att_rb.resource_id, + res_iovs, att_rb.nr_entries); +} + +static void +virgl_resource_detach_backing(VuGpu *g, + struct virtio_gpu_ctrl_command *cmd) +{ + struct virtio_gpu_resource_detach_backing detach_rb; + struct iovec *res_iovs = NULL; + int num_iovs = 0; + + VUGPU_FILL_CMD(detach_rb); + + virgl_renderer_resource_detach_iov(detach_rb.resource_id, + &res_iovs, + &num_iovs); + if (res_iovs == NULL || num_iovs == 0) { + return; + } + g_free(res_iovs); +} + +static void +virgl_cmd_set_scanout(VuGpu *g, + struct virtio_gpu_ctrl_command *cmd) +{ + struct virtio_gpu_set_scanout ss; + struct virgl_renderer_resource_info info; + int ret; + + VUGPU_FILL_CMD(ss); + + if (ss.scanout_id >= VIRTIO_GPU_MAX_SCANOUTS) { + g_critical("%s: illegal scanout id specified %d", + __func__, ss.scanout_id); + cmd->error = VIRTIO_GPU_RESP_ERR_INVALID_SCANOUT_ID; + return; + } + + memset(&info, 0, sizeof(info)); + + if (ss.resource_id && ss.r.width && ss.r.height) { + ret = virgl_renderer_resource_get_info(ss.resource_id, &info); + if (ret == -1) { + g_critical("%s: illegal resource specified %d\n", + __func__, ss.resource_id); + cmd->error = VIRTIO_GPU_RESP_ERR_INVALID_RESOURCE_ID; + return; + } + + int fd = -1; + if (virgl_renderer_get_fd_for_texture(info.tex_id, &fd) < 0) { + g_critical("%s: failed to get fd for texture\n", __func__); + cmd->error = VIRTIO_GPU_RESP_ERR_INVALID_RESOURCE_ID; + return; + } + assert(fd >= 0); + VhostUserGpuMsg msg = { + .request = VHOST_USER_GPU_DMABUF_SCANOUT, + .size = sizeof(VhostUserGpuDMABUFScanout), + .payload.dmabuf_scanout.scanout_id = ss.scanout_id, + .payload.dmabuf_scanout.x = ss.r.x, + .payload.dmabuf_scanout.y = ss.r.y, + .payload.dmabuf_scanout.width = ss.r.width, + .payload.dmabuf_scanout.height = ss.r.height, + .payload.dmabuf_scanout.fd_width = info.width, + .payload.dmabuf_scanout.fd_height = info.height, + .payload.dmabuf_scanout.fd_stride = info.stride, + .payload.dmabuf_scanout.fd_flags = info.flags, + .payload.dmabuf_scanout.fd_drm_fourcc = info.drm_fourcc + }; + vg_send_msg(g, &msg, fd); + close(fd); + } else { + VhostUserGpuMsg msg = { + .request = VHOST_USER_GPU_DMABUF_SCANOUT, + .size = sizeof(VhostUserGpuDMABUFScanout), + .payload.dmabuf_scanout.scanout_id = ss.scanout_id, + }; + g_debug("disable scanout"); + vg_send_msg(g, &msg, -1); + } + g->scanout[ss.scanout_id].resource_id = ss.resource_id; +} + +static void +virgl_cmd_resource_flush(VuGpu *g, + struct virtio_gpu_ctrl_command *cmd) +{ + struct virtio_gpu_resource_flush rf; + int i; + + VUGPU_FILL_CMD(rf); + + if (!rf.resource_id) { + g_debug("bad resource id for flush..?"); + return; + } + for (i = 0; i < VIRTIO_GPU_MAX_SCANOUTS; i++) { + if (g->scanout[i].resource_id != rf.resource_id) { + continue; + } + VhostUserGpuMsg msg = { + .request = VHOST_USER_GPU_DMABUF_UPDATE, + .size = sizeof(VhostUserGpuUpdate), + .payload.update.scanout_id = i, + .payload.update.x = rf.r.x, + .payload.update.y = rf.r.y, + .payload.update.width = rf.r.width, + .payload.update.height = rf.r.height + }; + vg_send_msg(g, &msg, -1); + vg_wait_ok(g); + } +} + +static void +virgl_cmd_ctx_attach_resource(VuGpu *g, + struct virtio_gpu_ctrl_command *cmd) +{ + struct virtio_gpu_ctx_resource att_res; + + VUGPU_FILL_CMD(att_res); + + virgl_renderer_ctx_attach_resource(att_res.hdr.ctx_id, att_res.resource_id); +} + +static void +virgl_cmd_ctx_detach_resource(VuGpu *g, + struct virtio_gpu_ctrl_command *cmd) +{ + struct virtio_gpu_ctx_resource det_res; + + VUGPU_FILL_CMD(det_res); + + virgl_renderer_ctx_detach_resource(det_res.hdr.ctx_id, det_res.resource_id); +} + +void vg_virgl_process_cmd(VuGpu *g, struct virtio_gpu_ctrl_command *cmd) +{ + virgl_renderer_force_ctx_0(); + switch (cmd->cmd_hdr.type) { + case VIRTIO_GPU_CMD_CTX_CREATE: + virgl_cmd_context_create(g, cmd); + break; + case VIRTIO_GPU_CMD_CTX_DESTROY: + virgl_cmd_context_destroy(g, cmd); + break; + case VIRTIO_GPU_CMD_RESOURCE_CREATE_2D: + virgl_cmd_create_resource_2d(g, cmd); + break; + case VIRTIO_GPU_CMD_RESOURCE_CREATE_3D: + virgl_cmd_create_resource_3d(g, cmd); + break; + case VIRTIO_GPU_CMD_SUBMIT_3D: + virgl_cmd_submit_3d(g, cmd); + break; + case VIRTIO_GPU_CMD_TRANSFER_TO_HOST_2D: + virgl_cmd_transfer_to_host_2d(g, cmd); + break; + case VIRTIO_GPU_CMD_TRANSFER_TO_HOST_3D: + virgl_cmd_transfer_to_host_3d(g, cmd); + break; + case VIRTIO_GPU_CMD_TRANSFER_FROM_HOST_3D: + virgl_cmd_transfer_from_host_3d(g, cmd); + break; + case VIRTIO_GPU_CMD_RESOURCE_ATTACH_BACKING: + virgl_resource_attach_backing(g, cmd); + break; + case VIRTIO_GPU_CMD_RESOURCE_DETACH_BACKING: + virgl_resource_detach_backing(g, cmd); + break; + case VIRTIO_GPU_CMD_SET_SCANOUT: + virgl_cmd_set_scanout(g, cmd); + break; + case VIRTIO_GPU_CMD_RESOURCE_FLUSH: + virgl_cmd_resource_flush(g, cmd); + break; + case VIRTIO_GPU_CMD_RESOURCE_UNREF: + virgl_cmd_resource_unref(g, cmd); + break; + case VIRTIO_GPU_CMD_CTX_ATTACH_RESOURCE: + /* TODO add security */ + virgl_cmd_ctx_attach_resource(g, cmd); + break; + case VIRTIO_GPU_CMD_CTX_DETACH_RESOURCE: + /* TODO add security */ + virgl_cmd_ctx_detach_resource(g, cmd); + break; + case VIRTIO_GPU_CMD_GET_CAPSET_INFO: + virgl_cmd_get_capset_info(g, cmd); + break; + case VIRTIO_GPU_CMD_GET_CAPSET: + virgl_cmd_get_capset(g, cmd); + break; + case VIRTIO_GPU_CMD_GET_DISPLAY_INFO: + vg_get_display_info(g, cmd); + break; + default: + g_debug("TODO handle ctrl %x\n", cmd->cmd_hdr.type); + cmd->error = VIRTIO_GPU_RESP_ERR_UNSPEC; + break; + } + + if (cmd->finished) { + return; + } + + if (cmd->error) { + g_warning("%s: ctrl 0x%x, error 0x%x\n", __func__, + cmd->cmd_hdr.type, cmd->error); + vg_ctrl_response_nodata(g, cmd, cmd->error); + return; + } + + if (!(cmd->cmd_hdr.flags & VIRTIO_GPU_FLAG_FENCE)) { + vg_ctrl_response_nodata(g, cmd, VIRTIO_GPU_RESP_OK_NODATA); + return; + } + + g_debug("Creating fence id:%" PRId64 " type:%d", + cmd->cmd_hdr.fence_id, cmd->cmd_hdr.type); + virgl_renderer_create_fence(cmd->cmd_hdr.fence_id, cmd->cmd_hdr.type); +} + +static void +virgl_write_fence(void *opaque, uint32_t fence) +{ + VuGpu *g = opaque; + struct virtio_gpu_ctrl_command *cmd, *tmp; + + QTAILQ_FOREACH_SAFE(cmd, &g->fenceq, next, tmp) { + /* + * the guest can end up emitting fences out of order + * so we should check all fenced cmds not just the first one. + */ + if (cmd->cmd_hdr.fence_id > fence) { + continue; + } + g_debug("FENCE %" PRIu64, cmd->cmd_hdr.fence_id); + vg_ctrl_response_nodata(g, cmd, VIRTIO_GPU_RESP_OK_NODATA); + QTAILQ_REMOVE(&g->fenceq, cmd, next); + g_free(cmd); + g->inflight--; + } +} + +#if defined(VIRGL_RENDERER_CALLBACKS_VERSION) && \ + VIRGL_RENDERER_CALLBACKS_VERSION >= 2 +static int +virgl_get_drm_fd(void *opaque) +{ + VuGpu *g = opaque; + + return g->drm_rnode_fd; +} +#endif + +static struct virgl_renderer_callbacks virgl_cbs = { +#if defined(VIRGL_RENDERER_CALLBACKS_VERSION) && \ + VIRGL_RENDERER_CALLBACKS_VERSION >= 2 + .get_drm_fd = virgl_get_drm_fd, + .version = 2, +#else + .version = 1, +#endif + .write_fence = virgl_write_fence, +}; + +static void +vg_virgl_poll(VuDev *dev, int condition, void *data) +{ + virgl_renderer_poll(); +} + +bool +vg_virgl_init(VuGpu *g) +{ + int ret; + + if (g->drm_rnode_fd && virgl_cbs.version == 1) { + g_warning("virgl will use the default rendernode"); + } + + ret = virgl_renderer_init(g, + VIRGL_RENDERER_USE_EGL | + VIRGL_RENDERER_THREAD_SYNC, + &virgl_cbs); + if (ret != 0) { + return false; + } + + ret = virgl_renderer_get_poll_fd(); + if (ret != -1) { + g->renderer_source = + vug_source_new(&g->dev, ret, G_IO_IN, vg_virgl_poll, g); + } + + return true; +} diff --git a/contrib/vhost-user-gpu/virgl.h b/contrib/vhost-user-gpu/virgl.h new file mode 100644 index 0000000000..f952bc9d4f --- /dev/null +++ b/contrib/vhost-user-gpu/virgl.h @@ -0,0 +1,25 @@ +/* + * Virtio vhost-user GPU Device + * + * Copyright Red Hat, Inc. 2013-2018 + * + * Authors: + * Dave Airlie <airlied@redhat.com> + * Gerd Hoffmann <kraxel@redhat.com> + * Marc-André Lureau <marcandre.lureau@redhat.com> + * + * This work is licensed under the terms of the GNU GPL, version 2 or later. + * See the COPYING file in the top-level directory. + */ +#ifndef VUGPU_VIRGL_H_ +#define VUGPU_VIRGL_H_ + +#include "vugpu.h" + +bool vg_virgl_init(VuGpu *g); +uint32_t vg_virgl_get_num_capsets(void); +void vg_virgl_process_cmd(VuGpu *vg, struct virtio_gpu_ctrl_command *cmd); +void vg_virgl_update_cursor_data(VuGpu *g, uint32_t resource_id, + gpointer data); + +#endif diff --git a/contrib/vhost-user-gpu/vugbm.c b/contrib/vhost-user-gpu/vugbm.c new file mode 100644 index 0000000000..d3bb82ff0e --- /dev/null +++ b/contrib/vhost-user-gpu/vugbm.c @@ -0,0 +1,328 @@ +/* + * Virtio vhost-user GPU Device + * + * DRM helpers + * + * This work is licensed under the terms of the GNU GPL, version 2 or later. + * See the COPYING file in the top-level directory. + */ + +#include "vugbm.h" + +static bool +mem_alloc_bo(struct vugbm_buffer *buf) +{ + buf->mmap = g_malloc(buf->width * buf->height * 4); + buf->stride = buf->width * 4; + return true; +} + +static void +mem_free_bo(struct vugbm_buffer *buf) +{ + g_free(buf->mmap); +} + +static bool +mem_map_bo(struct vugbm_buffer *buf) +{ + return buf->mmap != NULL; +} + +static void +mem_unmap_bo(struct vugbm_buffer *buf) +{ +} + +static void +mem_device_destroy(struct vugbm_device *dev) +{ +} + +#ifdef CONFIG_MEMFD +struct udmabuf_create { + uint32_t memfd; + uint32_t flags; + uint64_t offset; + uint64_t size; +}; + +#define UDMABUF_CREATE _IOW('u', 0x42, struct udmabuf_create) + +static size_t +udmabuf_get_size(struct vugbm_buffer *buf) +{ + return ROUND_UP(buf->width * buf->height * 4, getpagesize()); +} + +static bool +udmabuf_alloc_bo(struct vugbm_buffer *buf) +{ + int ret; + + buf->memfd = memfd_create("udmabuf-bo", MFD_ALLOW_SEALING); + if (buf->memfd < 0) { + return false; + } + + ret = ftruncate(buf->memfd, udmabuf_get_size(buf)); + if (ret < 0) { + close(buf->memfd); + return false; + } + + ret = fcntl(buf->memfd, F_ADD_SEALS, F_SEAL_SHRINK); + if (ret < 0) { + close(buf->memfd); + return false; + } + + buf->stride = buf->width * 4; + + return true; +} + +static void +udmabuf_free_bo(struct vugbm_buffer *buf) +{ + close(buf->memfd); +} + +static bool +udmabuf_map_bo(struct vugbm_buffer *buf) +{ + buf->mmap = mmap(NULL, udmabuf_get_size(buf), + PROT_READ | PROT_WRITE, MAP_SHARED, buf->memfd, 0); + if (buf->mmap == MAP_FAILED) { + return false; + } + + return true; +} + +static bool +udmabuf_get_fd(struct vugbm_buffer *buf, int *fd) +{ + struct udmabuf_create create = { + .memfd = buf->memfd, + .offset = 0, + .size = udmabuf_get_size(buf), + }; + + *fd = ioctl(buf->dev->fd, UDMABUF_CREATE, &create); + + return *fd >= 0; +} + +static void +udmabuf_unmap_bo(struct vugbm_buffer *buf) +{ + munmap(buf->mmap, udmabuf_get_size(buf)); +} + +static void +udmabuf_device_destroy(struct vugbm_device *dev) +{ + close(dev->fd); +} +#endif + +#ifdef CONFIG_GBM +static bool +alloc_bo(struct vugbm_buffer *buf) +{ + struct gbm_device *dev = buf->dev->dev; + + assert(!buf->bo); + + buf->bo = gbm_bo_create(dev, buf->width, buf->height, + buf->format, + GBM_BO_USE_RENDERING | GBM_BO_USE_LINEAR); + + if (buf->bo) { + buf->stride = gbm_bo_get_stride(buf->bo); + return true; + } + + return false; +} + +static void +free_bo(struct vugbm_buffer *buf) +{ + gbm_bo_destroy(buf->bo); +} + +static bool +map_bo(struct vugbm_buffer *buf) +{ + uint32_t stride; + + buf->mmap = gbm_bo_map(buf->bo, 0, 0, buf->width, buf->height, + GBM_BO_TRANSFER_READ_WRITE, &stride, + &buf->mmap_data); + + assert(stride == buf->stride); + + return buf->mmap != NULL; +} + +static void +unmap_bo(struct vugbm_buffer *buf) +{ + gbm_bo_unmap(buf->bo, buf->mmap_data); +} + +static bool +get_fd(struct vugbm_buffer *buf, int *fd) +{ + *fd = gbm_bo_get_fd(buf->bo); + + return *fd >= 0; +} + +static void +device_destroy(struct vugbm_device *dev) +{ + gbm_device_destroy(dev->dev); +} +#endif + +void +vugbm_device_destroy(struct vugbm_device *dev) +{ + if (!dev->inited) { + return; + } + + dev->device_destroy(dev); +} + +bool +vugbm_device_init(struct vugbm_device *dev, int fd) +{ + dev->fd = fd; + +#ifdef CONFIG_GBM + dev->dev = gbm_create_device(fd); +#endif + + if (0) { + /* nothing */ + } +#ifdef CONFIG_GBM + else if (dev->dev != NULL) { + dev->alloc_bo = alloc_bo; + dev->free_bo = free_bo; + dev->get_fd = get_fd; + dev->map_bo = map_bo; + dev->unmap_bo = unmap_bo; + dev->device_destroy = device_destroy; + } +#endif +#ifdef CONFIG_MEMFD + else if (g_file_test("/dev/udmabuf", G_FILE_TEST_EXISTS)) { + dev->fd = open("/dev/udmabuf", O_RDWR); + if (dev->fd < 0) { + return false; + } + g_debug("Using experimental udmabuf backend"); + dev->alloc_bo = udmabuf_alloc_bo; + dev->free_bo = udmabuf_free_bo; + dev->get_fd = udmabuf_get_fd; + dev->map_bo = udmabuf_map_bo; + dev->unmap_bo = udmabuf_unmap_bo; + dev->device_destroy = udmabuf_device_destroy; + } +#endif + else { + g_debug("Using mem fallback"); + dev->alloc_bo = mem_alloc_bo; + dev->free_bo = mem_free_bo; + dev->map_bo = mem_map_bo; + dev->unmap_bo = mem_unmap_bo; + dev->device_destroy = mem_device_destroy; + return false; + } + + dev->inited = true; + return true; +} + +static bool +vugbm_buffer_map(struct vugbm_buffer *buf) +{ + struct vugbm_device *dev = buf->dev; + + return dev->map_bo(buf); +} + +static void +vugbm_buffer_unmap(struct vugbm_buffer *buf) +{ + struct vugbm_device *dev = buf->dev; + + dev->unmap_bo(buf); +} + +bool +vugbm_buffer_can_get_dmabuf_fd(struct vugbm_buffer *buffer) +{ + if (!buffer->dev->get_fd) { + return false; + } + + return true; +} + +bool +vugbm_buffer_get_dmabuf_fd(struct vugbm_buffer *buffer, int *fd) +{ + if (!vugbm_buffer_can_get_dmabuf_fd(buffer) || + !buffer->dev->get_fd(buffer, fd)) { + g_warning("Failed to get dmabuf"); + return false; + } + + if (*fd < 0) { + g_warning("error: dmabuf_fd < 0"); + return false; + } + + return true; +} + +bool +vugbm_buffer_create(struct vugbm_buffer *buffer, struct vugbm_device *dev, + uint32_t width, uint32_t height) +{ + buffer->dev = dev; + buffer->width = width; + buffer->height = height; + buffer->format = GBM_FORMAT_XRGB8888; + buffer->stride = 0; /* modified during alloc */ + if (!dev->alloc_bo(buffer)) { + g_warning("alloc_bo failed"); + return false; + } + + if (!vugbm_buffer_map(buffer)) { + g_warning("map_bo failed"); + goto err; + } + + return true; + +err: + dev->free_bo(buffer); + return false; +} + +void +vugbm_buffer_destroy(struct vugbm_buffer *buffer) +{ + struct vugbm_device *dev = buffer->dev; + + vugbm_buffer_unmap(buffer); + dev->free_bo(buffer); +} diff --git a/contrib/vhost-user-gpu/vugbm.h b/contrib/vhost-user-gpu/vugbm.h new file mode 100644 index 0000000000..c0bf27af9b --- /dev/null +++ b/contrib/vhost-user-gpu/vugbm.h @@ -0,0 +1,67 @@ +/* + * Virtio vhost-user GPU Device + * + * GBM helpers + * + * This work is licensed under the terms of the GNU GPL, version 2 or later. + * See the COPYING file in the top-level directory. + */ +#ifndef VHOST_USER_GPU_GBM_H +#define VHOST_USER_GPU_GBM_H + +#include "qemu/osdep.h" + +#ifdef CONFIG_MEMFD +#include <sys/mman.h> +#include <sys/ioctl.h> +#endif + +#ifdef CONFIG_GBM +#include <gbm.h> +#endif + +struct vugbm_buffer; + +struct vugbm_device { + bool inited; + int fd; +#ifdef CONFIG_GBM + struct gbm_device *dev; +#endif + + bool (*alloc_bo)(struct vugbm_buffer *buf); + void (*free_bo)(struct vugbm_buffer *buf); + bool (*get_fd)(struct vugbm_buffer *buf, int *fd); + bool (*map_bo)(struct vugbm_buffer *buf); + void (*unmap_bo)(struct vugbm_buffer *buf); + void (*device_destroy)(struct vugbm_device *dev); +}; + +struct vugbm_buffer { + struct vugbm_device *dev; + +#ifdef CONFIG_MEMFD + int memfd; +#endif +#ifdef CONFIG_GBM + struct gbm_bo *bo; + void *mmap_data; +#endif + + uint8_t *mmap; + uint32_t width; + uint32_t height; + uint32_t stride; + uint32_t format; +}; + +bool vugbm_device_init(struct vugbm_device *dev, int fd); +void vugbm_device_destroy(struct vugbm_device *dev); + +bool vugbm_buffer_create(struct vugbm_buffer *buffer, struct vugbm_device *dev, + uint32_t width, uint32_t height); +bool vugbm_buffer_can_get_dmabuf_fd(struct vugbm_buffer *buffer); +bool vugbm_buffer_get_dmabuf_fd(struct vugbm_buffer *buffer, int *fd); +void vugbm_buffer_destroy(struct vugbm_buffer *buffer); + +#endif diff --git a/contrib/vhost-user-gpu/vugpu.h b/contrib/vhost-user-gpu/vugpu.h new file mode 100644 index 0000000000..458e92a1b3 --- /dev/null +++ b/contrib/vhost-user-gpu/vugpu.h @@ -0,0 +1,177 @@ +/* + * Virtio vhost-user GPU Device + * + * Copyright Red Hat, Inc. 2013-2018 + * + * Authors: + * Dave Airlie <airlied@redhat.com> + * Gerd Hoffmann <kraxel@redhat.com> + * Marc-André Lureau <marcandre.lureau@redhat.com> + * + * This work is licensed under the terms of the GNU GPL, version 2 or later. + * See the COPYING file in the top-level directory. + */ +#ifndef VUGPU_H_ +#define VUGPU_H_ + +#include "qemu/osdep.h" + +#include "contrib/libvhost-user/libvhost-user-glib.h" +#include "standard-headers/linux/virtio_gpu.h" + +#include "qemu/queue.h" +#include "qemu/iov.h" +#include "qemu/bswap.h" +#include "vugbm.h" + +typedef enum VhostUserGpuRequest { + VHOST_USER_GPU_NONE = 0, + VHOST_USER_GPU_GET_PROTOCOL_FEATURES, + VHOST_USER_GPU_SET_PROTOCOL_FEATURES, + VHOST_USER_GPU_GET_DISPLAY_INFO, + VHOST_USER_GPU_CURSOR_POS, + VHOST_USER_GPU_CURSOR_POS_HIDE, + VHOST_USER_GPU_CURSOR_UPDATE, + VHOST_USER_GPU_SCANOUT, + VHOST_USER_GPU_UPDATE, + VHOST_USER_GPU_DMABUF_SCANOUT, + VHOST_USER_GPU_DMABUF_UPDATE, +} VhostUserGpuRequest; + +typedef struct VhostUserGpuDisplayInfoReply { + struct virtio_gpu_resp_display_info info; +} VhostUserGpuDisplayInfoReply; + +typedef struct VhostUserGpuCursorPos { + uint32_t scanout_id; + uint32_t x; + uint32_t y; +} QEMU_PACKED VhostUserGpuCursorPos; + +typedef struct VhostUserGpuCursorUpdate { + VhostUserGpuCursorPos pos; + uint32_t hot_x; + uint32_t hot_y; + uint32_t data[64 * 64]; +} QEMU_PACKED VhostUserGpuCursorUpdate; + +typedef struct VhostUserGpuScanout { + uint32_t scanout_id; + uint32_t width; + uint32_t height; +} QEMU_PACKED VhostUserGpuScanout; + +typedef struct VhostUserGpuUpdate { + uint32_t scanout_id; + uint32_t x; + uint32_t y; + uint32_t width; + uint32_t height; + uint8_t data[]; +} QEMU_PACKED VhostUserGpuUpdate; + +typedef struct VhostUserGpuDMABUFScanout { + uint32_t scanout_id; + uint32_t x; + uint32_t y; + uint32_t width; + uint32_t height; + uint32_t fd_width; + uint32_t fd_height; + uint32_t fd_stride; + uint32_t fd_flags; + int fd_drm_fourcc; +} QEMU_PACKED VhostUserGpuDMABUFScanout; + +typedef struct VhostUserGpuMsg { + uint32_t request; /* VhostUserGpuRequest */ + uint32_t flags; + uint32_t size; /* the following payload size */ + union { + VhostUserGpuCursorPos cursor_pos; + VhostUserGpuCursorUpdate cursor_update; + VhostUserGpuScanout scanout; + VhostUserGpuUpdate update; + VhostUserGpuDMABUFScanout dmabuf_scanout; + struct virtio_gpu_resp_display_info display_info; + uint64_t u64; + } payload; +} QEMU_PACKED VhostUserGpuMsg; + +static VhostUserGpuMsg m __attribute__ ((unused)); +#define VHOST_USER_GPU_HDR_SIZE \ + (sizeof(m.request) + sizeof(m.flags) + sizeof(m.size)) + +#define VHOST_USER_GPU_MSG_FLAG_REPLY 0x4 + +struct virtio_gpu_scanout { + uint32_t width, height; + int x, y; + int invalidate; + uint32_t resource_id; +}; + +typedef struct VuGpu { + VugDev dev; + struct virtio_gpu_config virtio_config; + struct vugbm_device gdev; + int sock_fd; + int drm_rnode_fd; + GSource *renderer_source; + guint wait_ok; + + bool virgl; + bool virgl_inited; + uint32_t inflight; + + struct virtio_gpu_scanout scanout[VIRTIO_GPU_MAX_SCANOUTS]; + QTAILQ_HEAD(, virtio_gpu_simple_resource) reslist; + QTAILQ_HEAD(, virtio_gpu_ctrl_command) fenceq; +} VuGpu; + +struct virtio_gpu_ctrl_command { + VuVirtqElement elem; + VuVirtq *vq; + struct virtio_gpu_ctrl_hdr cmd_hdr; + uint32_t error; + bool finished; + QTAILQ_ENTRY(virtio_gpu_ctrl_command) next; +}; + +#define VUGPU_FILL_CMD(out) do { \ + size_t s; \ + s = iov_to_buf(cmd->elem.out_sg, cmd->elem.out_num, 0, \ + &out, sizeof(out)); \ + if (s != sizeof(out)) { \ + g_critical("%s: command size incorrect %zu vs %zu", \ + __func__, s, sizeof(out)); \ + return; \ + } \ + } while (0) + + +void vg_ctrl_response(VuGpu *g, + struct virtio_gpu_ctrl_command *cmd, + struct virtio_gpu_ctrl_hdr *resp, + size_t resp_len); + +void vg_ctrl_response_nodata(VuGpu *g, + struct virtio_gpu_ctrl_command *cmd, + enum virtio_gpu_ctrl_type type); + +int vg_create_mapping_iov(VuGpu *g, + struct virtio_gpu_resource_attach_backing *ab, + struct virtio_gpu_ctrl_command *cmd, + struct iovec **iov); + +void vg_get_display_info(VuGpu *vg, struct virtio_gpu_ctrl_command *cmd); + +void vg_wait_ok(VuGpu *g); + +void vg_send_msg(VuGpu *g, const VhostUserGpuMsg *msg, int fd); + +bool vg_recv_msg(VuGpu *g, uint32_t expect_req, uint32_t expect_size, + gpointer payload); + + +#endif diff --git a/default-configs/arm-softmmu.mak b/default-configs/arm-softmmu.mak index f23ecfd5c5..1f2e0e7fde 100644 --- a/default-configs/arm-softmmu.mak +++ b/default-configs/arm-softmmu.mak @@ -39,3 +39,4 @@ CONFIG_MICROBIT=y CONFIG_FSL_IMX25=y CONFIG_FSL_IMX7=y CONFIG_FSL_IMX6UL=y +CONFIG_SEMIHOSTING=y diff --git a/default-configs/i386-softmmu.mak b/default-configs/i386-softmmu.mak index ba3fb3ff50..cd5ea391e8 100644 --- a/default-configs/i386-softmmu.mak +++ b/default-configs/i386-softmmu.mak @@ -25,3 +25,4 @@ CONFIG_ISAPC=y CONFIG_I440FX=y CONFIG_Q35=y +CONFIG_ACPI_PCI=y diff --git a/default-configs/lm32-softmmu.mak b/default-configs/lm32-softmmu.mak index 6d259665d6..115b3e34c9 100644 --- a/default-configs/lm32-softmmu.mak +++ b/default-configs/lm32-softmmu.mak @@ -4,6 +4,8 @@ # #CONFIG_MILKYMIST_TMU2=n # disabling it actually causes compile-time failures +CONFIG_SEMIHOSTING=y + # Boards: # CONFIG_LM32=y diff --git a/default-configs/m68k-softmmu.mak b/default-configs/m68k-softmmu.mak index e17495e2a0..4049a8f2ba 100644 --- a/default-configs/m68k-softmmu.mak +++ b/default-configs/m68k-softmmu.mak @@ -1,5 +1,7 @@ # Default configuration for m68k-softmmu +CONFIG_SEMIHOSTING=y + # Boards: # CONFIG_AN5206=y diff --git a/default-configs/mips-softmmu-common.mak b/default-configs/mips-softmmu-common.mak index 8e54a74b7a..e10ac4b20c 100644 --- a/default-configs/mips-softmmu-common.mak +++ b/default-configs/mips-softmmu-common.mak @@ -35,6 +35,7 @@ CONFIG_MIPS_CPS=y CONFIG_MIPS_ITU=y CONFIG_R4K=y CONFIG_MALTA=y +CONFIG_SEMIHOSTING=y CONFIG_PCNET_PCI=y CONFIG_MIPSSIM=y CONFIG_ACPI_SMBUS=y diff --git a/default-configs/nios2-softmmu.mak b/default-configs/nios2-softmmu.mak index e130d024e6..1bc4082ea9 100644 --- a/default-configs/nios2-softmmu.mak +++ b/default-configs/nios2-softmmu.mak @@ -1,5 +1,7 @@ # Default configuration for nios2-softmmu +CONFIG_SEMIHOSTING=y + # Boards: # CONFIG_NIOS2_10M50=y diff --git a/default-configs/xtensa-softmmu.mak b/default-configs/xtensa-softmmu.mak index 7e4d1cc097..3aa20a47a7 100644 --- a/default-configs/xtensa-softmmu.mak +++ b/default-configs/xtensa-softmmu.mak @@ -1,5 +1,7 @@ # Default configuration for Xtensa +CONFIG_SEMIHOSTING=y + # Boards: # CONFIG_XTENSA_SIM=y diff --git a/docs/devel/build-system.txt b/docs/devel/build-system.txt index addd274eeb..41bd08ea3a 100644 --- a/docs/devel/build-system.txt +++ b/docs/devel/build-system.txt @@ -413,18 +413,13 @@ context. - default-configs/*.mak The files under default-configs/ control what emulated hardware is built -into each QEMU system and userspace emulator targets. They merely -contain a long list of config variable definitions. For example, -default-configs/x86_64-softmmu.mak has: - - include sound.mak - include usb.mak - CONFIG_QXL=$(CONFIG_SPICE) - CONFIG_VGA_ISA=y - CONFIG_VGA_CIRRUS=y - CONFIG_VMWARE_VGA=y - CONFIG_VIRTIO_VGA=y - ...snip... +into each QEMU system and userspace emulator targets. They merely contain +a list of config variable definitions like the machines that should be +included. For example, default-configs/aarch64-softmmu.mak has: + + include arm-softmmu.mak + CONFIG_XLNX_ZYNQMP_ARM=y + CONFIG_XLNX_VERSAL=y These files rarely need changing unless new devices / hardware need to be enabled for a particular system/userspace emulation target diff --git a/docs/devel/multiple-iothreads.txt b/docs/devel/multiple-iothreads.txt index 4f9012d154..aeb997bed5 100644 --- a/docs/devel/multiple-iothreads.txt +++ b/docs/devel/multiple-iothreads.txt @@ -109,7 +109,7 @@ The AioContext originates from the QEMU block layer, even though nowadays AioContext is a generic event loop that can be used by any QEMU subsystem. The block layer has support for AioContext integrated. Each BlockDriverState -is associated with an AioContext using bdrv_set_aio_context() and +is associated with an AioContext using bdrv_try_set_aio_context() and bdrv_get_aio_context(). This allows block layer code to process I/O inside the right AioContext. Other subsystems may wish to follow a similar approach. @@ -134,5 +134,5 @@ Long-running jobs (usually in the form of coroutines) are best scheduled in the BlockDriverState's AioContext to avoid the need to acquire/release around each bdrv_*() call. The functions bdrv_add/remove_aio_context_notifier, or alternatively blk_add/remove_aio_context_notifier if you use BlockBackends, -can be used to get a notification whenever bdrv_set_aio_context() moves a +can be used to get a notification whenever bdrv_try_set_aio_context() moves a BlockDriverState to a different AioContext. diff --git a/docs/index.rst b/docs/index.rst index 3690955dd1..baa5791c17 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -12,4 +12,5 @@ Welcome to QEMU's documentation! interop/index devel/index + specs/index diff --git a/docs/interop/index.rst b/docs/interop/index.rst index a037bd67ec..b4bfcab417 100644 --- a/docs/interop/index.rst +++ b/docs/interop/index.rst @@ -16,3 +16,4 @@ Contents: live-block-operations pr-helper vhost-user + vhost-user-gpu diff --git a/docs/interop/vhost-user-gpu.rst b/docs/interop/vhost-user-gpu.rst new file mode 100644 index 0000000000..688f8b4259 --- /dev/null +++ b/docs/interop/vhost-user-gpu.rst @@ -0,0 +1,242 @@ +======================= +Vhost-user-gpu Protocol +======================= + +:Licence: This work is licensed under the terms of the GNU GPL, + version 2 or later. See the COPYING file in the top-level + directory. + +.. contents:: Table of Contents + +Introduction +============ + +The vhost-user-gpu protocol is aiming at sharing the rendering result +of a virtio-gpu, done from a vhost-user slave process to a vhost-user +master process (such as QEMU). It bears a resemblance to a display +server protocol, if you consider QEMU as the display server and the +slave as the client, but in a very limited way. Typically, it will +work by setting a scanout/display configuration, before sending flush +events for the display updates. It will also update the cursor shape +and position. + +The protocol is sent over a UNIX domain stream socket, since it uses +socket ancillary data to share opened file descriptors (DMABUF fds or +shared memory). The socket is usually obtained via +``VHOST_USER_GPU_SET_SOCKET``. + +Requests are sent by the *slave*, and the optional replies by the +*master*. + +Wire format +=========== + +Unless specified differently, numbers are in the machine native byte +order. + +A vhost-user-gpu message (request and reply) consists of 3 header +fields and a payload. + ++---------+-------+------+---------+ +| request | flags | size | payload | ++---------+-------+------+---------+ + +Header +------ + +:request: ``u32``, type of the request + +:flags: ``u32``, 32-bit bit field: + + - Bit 2 is the reply flag - needs to be set on each reply + +:size: ``u32``, size of the payload + +Payload types +------------- + +Depending on the request type, **payload** can be: + +VhostUserGpuCursorPos +^^^^^^^^^^^^^^^^^^^^^ + ++------------+---+---+ +| scanout-id | x | y | ++------------+---+---+ + +:scanout-id: ``u32``, the scanout where the cursor is located + +:x/y: ``u32``, the cursor postion + +VhostUserGpuCursorUpdate +^^^^^^^^^^^^^^^^^^^^^^^^ + ++-----+-------+-------+--------+ +| pos | hot_x | hot_y | cursor | ++-----+-------+-------+--------+ + +:pos: a ``VhostUserGpuCursorPos``, the cursor location + +:hot_x/hot_y: ``u32``, the cursor hot location + +:cursor: ``[u32; 64 * 64]``, 64x64 RGBA cursor data (PIXMAN_a8r8g8b8 format) + +VhostUserGpuScanout +^^^^^^^^^^^^^^^^^^^ + ++------------+---+---+ +| scanout-id | w | h | ++------------+---+---+ + +:scanout-id: ``u32``, the scanout configuration to set + +:w/h: ``u32``, the scanout width/height size + +VhostUserGpuUpdate +^^^^^^^^^^^^^^^^^^ + ++------------+---+---+---+---+------+ +| scanout-id | x | y | w | h | data | ++------------+---+---+---+---+------+ + +:scanout-id: ``u32``, the scanout content to update + +:x/y/w/h: ``u32``, region of the update + +:data: RGB data (PIXMAN_x8r8g8b8 format) + +VhostUserGpuDMABUFScanout +^^^^^^^^^^^^^^^^^^^^^^^^^ + ++------------+---+---+---+---+-----+-----+--------+-------+--------+ +| scanout-id | x | y | w | h | fdw | fwh | stride | flags | fourcc | ++------------+---+---+---+---+-----+-----+--------+-------+--------+ + +:scanout-id: ``u32``, the scanout configuration to set + +:x/y: ``u32``, the location of the scanout within the DMABUF + +:w/h: ``u32``, the scanout width/height size + +:fdw/fdh/stride/flags: ``u32``, the DMABUF width/height/stride/flags + +:fourcc: ``i32``, the DMABUF fourcc + + +C structure +----------- + +In QEMU the vhost-user-gpu message is implemented with the following struct: + +.. code:: c + + typedef struct VhostUserGpuMsg { + uint32_t request; /* VhostUserGpuRequest */ + uint32_t flags; + uint32_t size; /* the following payload size */ + union { + VhostUserGpuCursorPos cursor_pos; + VhostUserGpuCursorUpdate cursor_update; + VhostUserGpuScanout scanout; + VhostUserGpuUpdate update; + VhostUserGpuDMABUFScanout dmabuf_scanout; + struct virtio_gpu_resp_display_info display_info; + uint64_t u64; + } payload; + } QEMU_PACKED VhostUserGpuMsg; + +Protocol features +----------------- + +None yet. + +As the protocol may need to evolve, new messages and communication +changes are negotiated thanks to preliminary +``VHOST_USER_GPU_GET_PROTOCOL_FEATURES`` and +``VHOST_USER_GPU_SET_PROTOCOL_FEATURES`` requests. + +Communication +============= + +Message types +------------- + +``VHOST_USER_GPU_GET_PROTOCOL_FEATURES`` + :id: 1 + :request payload: N/A + :reply payload: ``u64`` + + Get the supported protocol features bitmask. + +``VHOST_USER_GPU_SET_PROTOCOL_FEATURES`` + :id: 2 + :request payload: ``u64`` + :reply payload: N/A + + Enable protocol features using a bitmask. + +``VHOST_USER_GPU_GET_DISPLAY_INFO`` + :id: 3 + :request payload: N/A + :reply payload: ``struct virtio_gpu_resp_display_info`` (from virtio specification) + + Get the preferred display configuration. + +``VHOST_USER_GPU_CURSOR_POS`` + :id: 4 + :request payload: ``VhostUserGpuCursorPos`` + :reply payload: N/A + + Set/show the cursor position. + +``VHOST_USER_GPU_CURSOR_POS_HIDE`` + :id: 5 + :request payload: ``VhostUserGpuCursorPos`` + :reply payload: N/A + + Set/hide the cursor. + +``VHOST_USER_GPU_CURSOR_UPDATE`` + :id: 6 + :request payload: ``VhostUserGpuCursorUpdate`` + :reply payload: N/A + + Update the cursor shape and location. + +``VHOST_USER_GPU_SCANOUT`` + :id: 7 + :request payload: ``VhostUserGpuScanout`` + :reply payload: N/A + + Set the scanout resolution. To disable a scanout, the dimensions + width/height are set to 0. + +``VHOST_USER_GPU_UPDATE`` + :id: 8 + :request payload: ``VhostUserGpuUpdate`` + :reply payload: N/A + + Update the scanout content. The data payload contains the graphical bits. + The display should be flushed and presented. + +``VHOST_USER_GPU_DMABUF_SCANOUT`` + :id: 9 + :request payload: ``VhostUserGpuDMABUFScanout`` + :reply payload: N/A + + Set the scanout resolution/configuration, and share a DMABUF file + descriptor for the scanout content, which is passed as ancillary + data. To disable a scanout, the dimensions width/height are set + to 0, there is no file descriptor passed. + +``VHOST_USER_GPU_DMABUF_UPDATE`` + :id: 10 + :request payload: ``VhostUserGpuUpdate`` + :reply payload: empty payload + + The display should be flushed and presented according to updated + region from ``VhostUserGpuUpdate``. + + Note: there is no data payload, since the scanout is shared thanks + to DMABUF, that must have been set previously with + ``VHOST_USER_GPU_DMABUF_SCANOUT``. diff --git a/docs/interop/vhost-user.rst b/docs/interop/vhost-user.rst index 7f3232c798..dc0ff9211f 100644 --- a/docs/interop/vhost-user.rst +++ b/docs/interop/vhost-user.rst @@ -1163,6 +1163,15 @@ Master message types send the shared inflight buffer back to slave so that slave could get inflight I/O after a crash or restart. +``VHOST_USER_GPU_SET_SOCKET`` + :id: 33 + :equivalent ioctl: N/A + :master payload: N/A + + Sets the GPU protocol socket file descriptor, which is passed as + ancillary data. The GPU protocol is used to inform the master of + rendering state and updates. See vhost-user-gpu.rst for details. + Slave message types ------------------- diff --git a/docs/specs/index.rst b/docs/specs/index.rst new file mode 100644 index 0000000000..2e927519c2 --- /dev/null +++ b/docs/specs/index.rst @@ -0,0 +1,13 @@ +. This is the top level page for the 'specs' manual + + +QEMU full-system emulation guest hardware specifications +======================================================== + + +Contents: + +.. toctree:: + :maxdepth: 2 + + xive diff --git a/docs/specs/ppc-spapr-xive.rst b/docs/specs/ppc-spapr-xive.rst new file mode 100644 index 0000000000..539ce7ca4e --- /dev/null +++ b/docs/specs/ppc-spapr-xive.rst @@ -0,0 +1,174 @@ +XIVE for sPAPR (pseries machines) +================================= + +The POWER9 processor comes with a new interrupt controller +architecture, called XIVE as "eXternal Interrupt Virtualization +Engine". It supports a larger number of interrupt sources and offers +virtualization features which enables the HW to deliver interrupts +directly to virtual processors without hypervisor assistance. + +A QEMU ``pseries`` machine (which is PAPR compliant) using POWER9 +processors can run under two interrupt modes: + +- *Legacy Compatibility Mode* + + the hypervisor provides identical interfaces and similar + functionality to PAPR+ Version 2.7. This is the default mode + + It is also referred as *XICS* in QEMU. + +- *XIVE native exploitation mode* + + the hypervisor provides new interfaces to manage the XIVE control + structures, and provides direct control for interrupt management + through MMIO pages. + +Which interrupt modes can be used by the machine is negotiated with +the guest O/S during the Client Architecture Support negotiation +sequence. The two modes are mutually exclusive. + +Both interrupt mode share the same IRQ number space. See below for the +layout. + +CAS Negotiation +--------------- + +QEMU advertises the supported interrupt modes in the device tree +property "ibm,arch-vec-5-platform-support" in byte 23 and the OS +Selection for XIVE is indicated in the "ibm,architecture-vec-5" +property byte 23. + +The interrupt modes supported by the machine depend on the CPU type +(POWER9 is required for XIVE) but also on the machine property +``ic-mode`` which can be set on the command line. It can take the +following values: ``xics``, ``xive``, ``dual`` and currently ``xics`` +is the default but it may change in the future. + +The choosen interrupt mode is activated after a reconfiguration done +in a machine reset. + +XIVE Device tree properties +--------------------------- + +The properties for the PAPR interrupt controller node when the *XIVE +native exploitation mode* is selected shoud contain: + +- ``device_type`` + + value should be "power-ivpe". + +- ``compatible`` + + value should be "ibm,power-ivpe". + +- ``reg`` + + contains the base address and size of the thread interrupt + managnement areas (TIMA), for the User level and for the Guest OS + level. Only the Guest OS level is taken into account today. + +- ``ibm,xive-eq-sizes`` + + the size of the event queues. One cell per size supported, contains + log2 of size, in ascending order. + +- ``ibm,xive-lisn-ranges`` + + the IRQ interrupt number ranges assigned to the guest for the IPIs. + +The root node also exports : + +- ``ibm,plat-res-int-priorities`` + + contains a list of priorities that the hypervisor has reserved for + its own use. + +IRQ number space +---------------- + +IRQ Number space of the ``pseries`` machine is 8K wide and is the same +for both interrupt mode. The different ranges are defined as follow : + +- ``0x0000 .. 0x0FFF`` 4K CPU IPIs (only used under XIVE) +- ``0x1000 .. 0x1000`` 1 EPOW +- ``0x1001 .. 0x1001`` 1 HOTPLUG +- ``0x1100 .. 0x11FF`` 256 VIO devices +- ``0x1200 .. 0x127F`` 32 PHBs devices +- ``0x1280 .. 0x12FF`` unused +- ``0x1300 .. 0x1FFF`` PHB MSIs + +Monitoring XIVE +--------------- + +The state of the XIVE interrupt controller can be queried through the +monitor commands ``info pic``. The output comes in two parts. + +First, the state of the thread interrupt context registers is dumped +for each CPU : + +:: + + (qemu) info pic + CPU[0000]: QW NSR CPPR IPB LSMFB ACK# INC AGE PIPR W2 + CPU[0000]: USER 00 00 00 00 00 00 00 00 00000000 + CPU[0000]: OS 00 ff 00 00 ff 00 ff ff 80000400 + CPU[0000]: POOL 00 00 00 00 00 00 00 00 00000000 + CPU[0000]: PHYS 00 00 00 00 00 00 00 ff 00000000 + ... + +In the case of a ``pseries`` machine, QEMU acts as the hypervisor and only +the O/S and USER register rings make sense. ``W2`` contains the vCPU CAM +line which is set to the VP identifier. + +Then comes the routing information which aggregates the EAS and the +END configuration: + +:: + + ... + LISN PQ EISN CPU/PRIO EQ + 00000000 MSI -- 00000010 0/6 380/16384 @1fe3e0000 ^1 [ 80000010 ... ] + 00000001 MSI -- 00000010 1/6 305/16384 @1fc230000 ^1 [ 80000010 ... ] + 00000002 MSI -- 00000010 2/6 220/16384 @1fc2f0000 ^1 [ 80000010 ... ] + 00000003 MSI -- 00000010 3/6 201/16384 @1fc390000 ^1 [ 80000010 ... ] + 00000004 MSI -Q M 00000000 + 00000005 MSI -Q M 00000000 + 00000006 MSI -Q M 00000000 + 00000007 MSI -Q M 00000000 + 00001000 MSI -- 00000012 0/6 380/16384 @1fe3e0000 ^1 [ 80000010 ... ] + 00001001 MSI -- 00000013 0/6 380/16384 @1fe3e0000 ^1 [ 80000010 ... ] + 00001100 MSI -- 00000100 1/6 305/16384 @1fc230000 ^1 [ 80000010 ... ] + 00001101 MSI -Q M 00000000 + 00001200 LSI -Q M 00000000 + 00001201 LSI -Q M 00000000 + 00001202 LSI -Q M 00000000 + 00001203 LSI -Q M 00000000 + 00001300 MSI -- 00000102 1/6 305/16384 @1fc230000 ^1 [ 80000010 ... ] + 00001301 MSI -- 00000103 2/6 220/16384 @1fc2f0000 ^1 [ 80000010 ... ] + 00001302 MSI -- 00000104 3/6 201/16384 @1fc390000 ^1 [ 80000010 ... ] + +The source information and configuration: + +- The ``LISN`` column outputs the interrupt number of the source in + range ``[ 0x0 ... 0x1FFF ]`` and its type : ``MSI`` or ``LSI`` +- The ``PQ`` column reflects the state of the PQ bits of the source : + + - ``--`` source is ready to take events + - ``P-`` an event was sent and an EOI is PENDING + - ``PQ`` an event was QUEUED + - ``-Q`` source is OFF + + a ``M`` indicates that source is *MASKED* at the EAS level, + +The targeting configuration : + +- The ``EISN`` column is the event data that will be queued in the event + queue of the O/S. +- The ``CPU/PRIO`` column is the tuple defining the CPU number and + priority queue serving the source. +- The ``EQ`` column outputs : + + - the current index of the event queue/ the max number of entries + - the O/S event queue address + - the toggle bit + - the last entries that were pushed in the event queue. diff --git a/docs/specs/ppc-xive.rst b/docs/specs/ppc-xive.rst new file mode 100644 index 0000000000..b997dc0629 --- /dev/null +++ b/docs/specs/ppc-xive.rst @@ -0,0 +1,199 @@ +================================ +POWER9 XIVE interrupt controller +================================ + +The POWER9 processor comes with a new interrupt controller +architecture, called XIVE as "eXternal Interrupt Virtualization +Engine". + +Compared to the previous architecture, the main characteristics of +XIVE are to support a larger number of interrupt sources and to +deliver interrupts directly to virtual processors without hypervisor +assistance. This removes the context switches required for the +delivery process. + + +XIVE architecture +================= + +The XIVE IC is composed of three sub-engines, each taking care of a +processing layer of external interrupts: + +- Interrupt Virtualization Source Engine (IVSE), or Source Controller + (SC). These are found in PCI PHBs, in the PSI host bridge + controller, but also inside the main controller for the core IPIs + and other sub-chips (NX, CAP, NPU) of the chip/processor. They are + configured to feed the IVRE with events. +- Interrupt Virtualization Routing Engine (IVRE) or Virtualization + Controller (VC). It handles event coalescing and perform interrupt + routing by matching an event source number with an Event + Notification Descriptor (END). +- Interrupt Virtualization Presentation Engine (IVPE) or Presentation + Controller (PC). It maintains the interrupt context state of each + thread and handles the delivery of the external interrupt to the + thread. + +:: + + XIVE Interrupt Controller + +------------------------------------+ IPIs + | +---------+ +---------+ +--------+ | +-------+ + | |IVRE | |Common Q | |IVPE |----> | CORES | + | | esb | | | | |----> | | + | | eas | | Bridge | | tctx |----> | | + | |SC end | | | | nvt | | | | + +------+ | +---------+ +----+----+ +--------+ | +-+-+-+-+ + | RAM | +------------------|-----------------+ | | | + | | | | | | + | | | | | | + | | +--------------------v------------------------v-v-v--+ other + | <--+ Power Bus +--> chips + | esb | +---------+-----------------------+------------------+ + | eas | | | + | end | +--|------+ | + | nvt | +----+----+ | +----+----+ + +------+ |IVSE | | |IVSE | + | | | | | + | PQ-bits | | | PQ-bits | + | local |-+ | in VC | + +---------+ +---------+ + PCIe NX,NPU,CAPI + + + PQ-bits: 2 bits source state machine (P:pending Q:queued) + esb: Event State Buffer (Array of PQ bits in an IVSE) + eas: Event Assignment Structure + end: Event Notification Descriptor + nvt: Notification Virtual Target + tctx: Thread interrupt Context registers + + + +XIVE internal tables +-------------------- + +Each of the sub-engines uses a set of tables to redirect interrupts +from event sources to CPU threads. + +:: + + +-------+ + User or O/S | EQ | + or +------>|entries| + Hypervisor | | .. | + Memory | +-------+ + | ^ + | | + +-------------------------------------------------+ + | | + Hypervisor +------+ +---+--+ +---+--+ +------+ + Memory | ESB | | EAT | | ENDT | | NVTT | + (skiboot) +----+-+ +----+-+ +----+-+ +------+ + ^ | ^ | ^ | ^ + | | | | | | | + +-------------------------------------------------+ + | | | | | | | + | | | | | | | + +----|--|--------|--|--------|--|-+ +-|-----+ +------+ + | | | | | | | | | | tctx| |Thread| + IPI or ---+ + v + v + v |---| + .. |-----> | + HW events | | | | | | + | IVRE | | IVPE | +------+ + +---------------------------------+ +-------+ + + +The IVSE have a 2-bits state machine, P for pending and Q for queued, +for each source that allows events to be triggered. They are stored in +an Event State Buffer (ESB) array and can be controlled by MMIOs. + +If the event is let through, the IVRE looks up in the Event Assignment +Structure (EAS) table for an Event Notification Descriptor (END) +configured for the source. Each Event Notification Descriptor defines +a notification path to a CPU and an in-memory Event Queue, in which +will be enqueued an EQ data for the O/S to pull. + +The IVPE determines if a Notification Virtual Target (NVT) can handle +the event by scanning the thread contexts of the VCPUs dispatched on +the processor HW threads. It maintains the interrupt context state of +each thread in a NVT table. + +XIVE thread interrupt context +----------------------------- + +The XIVE presenter can generate four different exceptions to its +HW threads: + +- hypervisor exception +- O/S exception +- Event-Based Branch (user level) +- msgsnd (doorbell) + +Each exception has a state independent from the others called a Thread +Interrupt Management context. This context is a set of registers which +lets the thread handle priority management and interrupt +acknowledgment among other things. The most important ones being : + +- Interrupt Priority Register (PIPR) +- Interrupt Pending Buffer (IPB) +- Current Processor Priority (CPPR) +- Notification Source Register (NSR) + +TIMA +~~~~ + +The Thread Interrupt Management registers are accessible through a +specific MMIO region, called the Thread Interrupt Management Area +(TIMA), four aligned pages, each exposing a different view of the +registers. First page (page address ending in ``0b00``) gives access +to the entire context and is reserved for the ring 0 view for the +physical thread context. The second (page address ending in ``0b01``) +is for the hypervisor, ring 1 view. The third (page address ending in +``0b10``) is for the operating system, ring 2 view. The fourth (page +address ending in ``0b11``) is for user level, ring 3 view. + +Interrupt flow from an O/S perspective +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +After an event data has been enqueued in the O/S Event Queue, the IVPE +raises the bit corresponding to the priority of the pending interrupt +in the register IBP (Interrupt Pending Buffer) to indicate that an +event is pending in one of the 8 priority queues. The Pending +Interrupt Priority Register (PIPR) is also updated using the IPB. This +register represent the priority of the most favored pending +notification. + +The PIPR is then compared to the the Current Processor Priority +Register (CPPR). If it is more favored (numerically less than), the +CPU interrupt line is raised and the EO bit of the Notification Source +Register (NSR) is updated to notify the presence of an exception for +the O/S. The O/S acknowledges the interrupt with a special load in the +Thread Interrupt Management Area. + +The O/S handles the interrupt and when done, performs an EOI using a +MMIO operation on the ESB management page of the associate source. + +Overview of the QEMU models for XIVE +==================================== + +The XiveSource models the IVSE in general, internal and external. It +handles the source ESBs and the MMIO interface to control them. + +The XiveNotifier is a small helper interface interconnecting the +XiveSource to the XiveRouter. + +The XiveRouter is an abstract model acting as a combined IVRE and +IVPE. It routes event notifications using the EAS and END tables to +the IVPE sub-engine which does a CAM scan to find a CPU to deliver the +exception. Storage should be provided by the inheriting classes. + +XiveEnDSource is a special source object. It exposes the END ESB MMIOs +of the Event Queues which are used for coalescing event notifications +and for escalation. Not used on the field, only to sync the EQ cache +in OPAL. + +Finally, the XiveTCTX contains the interrupt state context of a thread, +four sets of registers, one for each exception that can be delivered +to a CPU. These contexts are scanned by the IVPE to find a matching VP +when a notification is triggered. It also models the Thread Interrupt +Management Area (TIMA), which exposes the thread context registers to +the CPU for interrupt management. @@ -37,7 +37,7 @@ #include "qemu/sockets.h" #include "sysemu/hw_accel.h" #include "sysemu/kvm.h" -#include "exec/semihost.h" +#include "hw/semihosting/semihost.h" #include "exec/exec-all.h" #ifdef CONFIG_USER_ONLY @@ -2560,7 +2560,8 @@ void hmp_qemu_io(Monitor *mon, const QDict *qdict) if (!blk) { BlockDriverState *bs = bdrv_lookup_bs(NULL, device, &err); if (bs) { - blk = local_blk = blk_new(0, BLK_PERM_ALL); + blk = local_blk = blk_new(bdrv_get_aio_context(bs), + 0, BLK_PERM_ALL); ret = blk_insert_bs(blk, bs, &err); if (ret < 0) { goto fail; diff --git a/hw/Kconfig b/hw/Kconfig index 88b9f15007..195f541e50 100644 --- a/hw/Kconfig +++ b/hw/Kconfig @@ -29,6 +29,7 @@ source pci/Kconfig source rdma/Kconfig source scsi/Kconfig source sd/Kconfig +source semihosting/Kconfig source smbios/Kconfig source ssi/Kconfig source timer/Kconfig diff --git a/hw/Makefile.objs b/hw/Makefile.objs index 82aa7fab8e..d770926ba9 100644 --- a/hw/Makefile.objs +++ b/hw/Makefile.objs @@ -36,6 +36,7 @@ devices-dirs-$(CONFIG_SOFTMMU) += watchdog/ devices-dirs-$(CONFIG_SOFTMMU) += xen/ devices-dirs-$(CONFIG_MEM_DEVICE) += mem/ devices-dirs-$(CONFIG_SOFTMMU) += smbios/ +devices-dirs-y += semihosting/ devices-dirs-y += core/ common-obj-y += $(devices-dirs-y) obj-y += $(devices-dirs-y) diff --git a/hw/acpi/Kconfig b/hw/acpi/Kconfig index eca3beed75..7c59cf900b 100644 --- a/hw/acpi/Kconfig +++ b/hw/acpi/Kconfig @@ -23,6 +23,10 @@ config ACPI_NVDIMM bool depends on ACPI +config ACPI_PCI + bool + depends on ACPI && PCI + config ACPI_VMGENID bool default y diff --git a/hw/acpi/Makefile.objs b/hw/acpi/Makefile.objs index 2d46e3789a..661a9b8c2f 100644 --- a/hw/acpi/Makefile.objs +++ b/hw/acpi/Makefile.objs @@ -11,6 +11,7 @@ common-obj-$(call lnot,$(CONFIG_ACPI_X86)) += acpi-stub.o common-obj-y += acpi_interface.o common-obj-y += bios-linker-loader.o common-obj-y += aml-build.o +common-obj-$(CONFIG_ACPI_PCI) += pci.o common-obj-$(CONFIG_TPM) += tpm.o common-obj-$(CONFIG_IPMI) += ipmi.o diff --git a/hw/acpi/pci.c b/hw/acpi/pci.c new file mode 100644 index 0000000000..9510597a19 --- /dev/null +++ b/hw/acpi/pci.c @@ -0,0 +1,61 @@ +/* + * Support for generating PCI related ACPI tables and passing them to Guests + * + * Copyright (C) 2006 Fabrice Bellard + * Copyright (C) 2008-2010 Kevin O'Connor <kevin@koconnor.net> + * Copyright (C) 2013-2019 Red Hat Inc + * Copyright (C) 2019 Intel Corporation + * + * Author: Wei Yang <richardw.yang@linux.intel.com> + * Author: Michael S. Tsirkin <mst@redhat.com> + * + * This program 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, see <http://www.gnu.org/licenses/>. + */ + +#include "qemu/osdep.h" +#include "hw/acpi/aml-build.h" +#include "hw/acpi/pci.h" +#include "hw/pci/pcie_host.h" + +void build_mcfg(GArray *table_data, BIOSLinker *linker, AcpiMcfgInfo *info) +{ + int mcfg_start = table_data->len; + + /* + * PCI Firmware Specification, Revision 3.0 + * 4.1.2 MCFG Table Description. + */ + acpi_data_push(table_data, sizeof(AcpiTableHeader)); + /* Reserved */ + build_append_int_noprefix(table_data, 0, 8); + + /* + * Memory Mapped Enhanced Configuration Space Base Address Allocation + * Structure + */ + /* Base address, processor-relative */ + build_append_int_noprefix(table_data, info->base, 8); + /* PCI segment group number */ + build_append_int_noprefix(table_data, 0, 2); + /* Starting PCI Bus number */ + build_append_int_noprefix(table_data, 0, 1); + /* Final PCI Bus number */ + build_append_int_noprefix(table_data, PCIE_MMCFG_BUS(info->size - 1), 1); + /* Reserved */ + build_append_int_noprefix(table_data, 0, 4); + + build_header(linker, table_data, (void *)(table_data->data + mcfg_start), + "MCFG", table_data->len - mcfg_start, 1, NULL, NULL); +} + diff --git a/hw/arm/Kconfig b/hw/arm/Kconfig index af8cffde9c..9aced9d54d 100644 --- a/hw/arm/Kconfig +++ b/hw/arm/Kconfig @@ -19,6 +19,7 @@ config ARM_VIRT select PLATFORM_BUS select SMBIOS select VIRTIO_MMIO + select ACPI_PCI config CHEETAH bool diff --git a/hw/arm/aspeed.c b/hw/arm/aspeed.c index 415cff7a01..33070a6df8 100644 --- a/hw/arm/aspeed.c +++ b/hw/arm/aspeed.c @@ -160,9 +160,9 @@ static void aspeed_board_init(MachineState *machine, ram_addr_t max_ram_size; bmc = g_new0(AspeedBoardState, 1); - object_initialize(&bmc->soc, (sizeof(bmc->soc)), cfg->soc_name); - object_property_add_child(OBJECT(machine), "soc", OBJECT(&bmc->soc), - &error_abort); + object_initialize_child(OBJECT(machine), "soc", &bmc->soc, + (sizeof(bmc->soc)), cfg->soc_name, &error_abort, + NULL); sc = ASPEED_SOC_GET_CLASS(&bmc->soc); diff --git a/hw/arm/aspeed_soc.c b/hw/arm/aspeed_soc.c index a27233d487..faff42b84a 100644 --- a/hw/arm/aspeed_soc.c +++ b/hw/arm/aspeed_soc.c @@ -106,12 +106,11 @@ static void aspeed_soc_init(Object *obj) AspeedSoCClass *sc = ASPEED_SOC_GET_CLASS(s); int i; - object_initialize(&s->cpu, sizeof(s->cpu), sc->info->cpu_type); - object_property_add_child(obj, "cpu", OBJECT(&s->cpu), NULL); + object_initialize_child(obj, "cpu", OBJECT(&s->cpu), sizeof(s->cpu), + sc->info->cpu_type, &error_abort, NULL); - object_initialize(&s->scu, sizeof(s->scu), TYPE_ASPEED_SCU); - object_property_add_child(obj, "scu", OBJECT(&s->scu), NULL); - qdev_set_parent_bus(DEVICE(&s->scu), sysbus_get_default()); + sysbus_init_child_obj(obj, "scu", OBJECT(&s->scu), sizeof(s->scu), + TYPE_ASPEED_SCU); qdev_prop_set_uint32(DEVICE(&s->scu), "silicon-rev", sc->info->silicon_rev); object_property_add_alias(obj, "hw-strap1", OBJECT(&s->scu), @@ -121,36 +120,29 @@ static void aspeed_soc_init(Object *obj) object_property_add_alias(obj, "hw-prot-key", OBJECT(&s->scu), "hw-prot-key", &error_abort); - object_initialize(&s->vic, sizeof(s->vic), TYPE_ASPEED_VIC); - object_property_add_child(obj, "vic", OBJECT(&s->vic), NULL); - qdev_set_parent_bus(DEVICE(&s->vic), sysbus_get_default()); + sysbus_init_child_obj(obj, "vic", OBJECT(&s->vic), sizeof(s->vic), + TYPE_ASPEED_VIC); - object_initialize(&s->timerctrl, sizeof(s->timerctrl), TYPE_ASPEED_TIMER); - object_property_add_child(obj, "timerctrl", OBJECT(&s->timerctrl), NULL); + sysbus_init_child_obj(obj, "timerctrl", OBJECT(&s->timerctrl), + sizeof(s->timerctrl), TYPE_ASPEED_TIMER); object_property_add_const_link(OBJECT(&s->timerctrl), "scu", OBJECT(&s->scu), &error_abort); - qdev_set_parent_bus(DEVICE(&s->timerctrl), sysbus_get_default()); - object_initialize(&s->i2c, sizeof(s->i2c), TYPE_ASPEED_I2C); - object_property_add_child(obj, "i2c", OBJECT(&s->i2c), NULL); - qdev_set_parent_bus(DEVICE(&s->i2c), sysbus_get_default()); + sysbus_init_child_obj(obj, "i2c", OBJECT(&s->i2c), sizeof(s->i2c), + TYPE_ASPEED_I2C); - object_initialize(&s->fmc, sizeof(s->fmc), sc->info->fmc_typename); - object_property_add_child(obj, "fmc", OBJECT(&s->fmc), NULL); - qdev_set_parent_bus(DEVICE(&s->fmc), sysbus_get_default()); + sysbus_init_child_obj(obj, "fmc", OBJECT(&s->fmc), sizeof(s->fmc), + sc->info->fmc_typename); object_property_add_alias(obj, "num-cs", OBJECT(&s->fmc), "num-cs", &error_abort); for (i = 0; i < sc->info->spis_num; i++) { - object_initialize(&s->spi[i], sizeof(s->spi[i]), - sc->info->spi_typename[i]); - object_property_add_child(obj, "spi[*]", OBJECT(&s->spi[i]), NULL); - qdev_set_parent_bus(DEVICE(&s->spi[i]), sysbus_get_default()); + sysbus_init_child_obj(obj, "spi[*]", OBJECT(&s->spi[i]), + sizeof(s->spi[i]), sc->info->spi_typename[i]); } - object_initialize(&s->sdmc, sizeof(s->sdmc), TYPE_ASPEED_SDMC); - object_property_add_child(obj, "sdmc", OBJECT(&s->sdmc), NULL); - qdev_set_parent_bus(DEVICE(&s->sdmc), sysbus_get_default()); + sysbus_init_child_obj(obj, "sdmc", OBJECT(&s->sdmc), sizeof(s->sdmc), + TYPE_ASPEED_SDMC); qdev_prop_set_uint32(DEVICE(&s->sdmc), "silicon-rev", sc->info->silicon_rev); object_property_add_alias(obj, "ram-size", OBJECT(&s->sdmc), @@ -159,16 +151,14 @@ static void aspeed_soc_init(Object *obj) "max-ram-size", &error_abort); for (i = 0; i < sc->info->wdts_num; i++) { - object_initialize(&s->wdt[i], sizeof(s->wdt[i]), TYPE_ASPEED_WDT); - object_property_add_child(obj, "wdt[*]", OBJECT(&s->wdt[i]), NULL); - qdev_set_parent_bus(DEVICE(&s->wdt[i]), sysbus_get_default()); + sysbus_init_child_obj(obj, "wdt[*]", OBJECT(&s->wdt[i]), + sizeof(s->wdt[i]), TYPE_ASPEED_WDT); qdev_prop_set_uint32(DEVICE(&s->wdt[i]), "silicon-rev", sc->info->silicon_rev); } - object_initialize(&s->ftgmac100, sizeof(s->ftgmac100), TYPE_FTGMAC100); - object_property_add_child(obj, "ftgmac100", OBJECT(&s->ftgmac100), NULL); - qdev_set_parent_bus(DEVICE(&s->ftgmac100), sysbus_get_default()); + sysbus_init_child_obj(obj, "ftgmac100", OBJECT(&s->ftgmac100), + sizeof(s->ftgmac100), TYPE_FTGMAC100); } static void aspeed_soc_realize(DeviceState *dev, Error **errp) diff --git a/hw/arm/bcm2835_peripherals.c b/hw/arm/bcm2835_peripherals.c index 6be7660e8c..0fb54c7964 100644 --- a/hw/arm/bcm2835_peripherals.c +++ b/hw/arm/bcm2835_peripherals.c @@ -41,44 +41,36 @@ static void bcm2835_peripherals_init(Object *obj) MBOX_CHAN_COUNT << MBOX_AS_CHAN_SHIFT); /* Interrupt Controller */ - object_initialize(&s->ic, sizeof(s->ic), TYPE_BCM2835_IC); - object_property_add_child(obj, "ic", OBJECT(&s->ic), NULL); - qdev_set_parent_bus(DEVICE(&s->ic), sysbus_get_default()); + sysbus_init_child_obj(obj, "ic", &s->ic, sizeof(s->ic), TYPE_BCM2835_IC); /* UART0 */ - s->uart0 = SYS_BUS_DEVICE(object_new("pl011")); - object_property_add_child(obj, "uart0", OBJECT(s->uart0), NULL); - qdev_set_parent_bus(DEVICE(s->uart0), sysbus_get_default()); + sysbus_init_child_obj(obj, "uart0", &s->uart0, sizeof(s->uart0), + TYPE_PL011); /* AUX / UART1 */ - object_initialize(&s->aux, sizeof(s->aux), TYPE_BCM2835_AUX); - object_property_add_child(obj, "aux", OBJECT(&s->aux), NULL); - qdev_set_parent_bus(DEVICE(&s->aux), sysbus_get_default()); + sysbus_init_child_obj(obj, "aux", &s->aux, sizeof(s->aux), + TYPE_BCM2835_AUX); /* Mailboxes */ - object_initialize(&s->mboxes, sizeof(s->mboxes), TYPE_BCM2835_MBOX); - object_property_add_child(obj, "mbox", OBJECT(&s->mboxes), NULL); - qdev_set_parent_bus(DEVICE(&s->mboxes), sysbus_get_default()); + sysbus_init_child_obj(obj, "mbox", &s->mboxes, sizeof(s->mboxes), + TYPE_BCM2835_MBOX); object_property_add_const_link(OBJECT(&s->mboxes), "mbox-mr", OBJECT(&s->mbox_mr), &error_abort); /* Framebuffer */ - object_initialize(&s->fb, sizeof(s->fb), TYPE_BCM2835_FB); - object_property_add_child(obj, "fb", OBJECT(&s->fb), NULL); + sysbus_init_child_obj(obj, "fb", &s->fb, sizeof(s->fb), TYPE_BCM2835_FB); object_property_add_alias(obj, "vcram-size", OBJECT(&s->fb), "vcram-size", &error_abort); - qdev_set_parent_bus(DEVICE(&s->fb), sysbus_get_default()); object_property_add_const_link(OBJECT(&s->fb), "dma-mr", OBJECT(&s->gpu_bus_mr), &error_abort); /* Property channel */ - object_initialize(&s->property, sizeof(s->property), TYPE_BCM2835_PROPERTY); - object_property_add_child(obj, "property", OBJECT(&s->property), NULL); + sysbus_init_child_obj(obj, "property", &s->property, sizeof(s->property), + TYPE_BCM2835_PROPERTY); object_property_add_alias(obj, "board-rev", OBJECT(&s->property), "board-rev", &error_abort); - qdev_set_parent_bus(DEVICE(&s->property), sysbus_get_default()); object_property_add_const_link(OBJECT(&s->property), "fb", OBJECT(&s->fb), &error_abort); @@ -86,32 +78,27 @@ static void bcm2835_peripherals_init(Object *obj) OBJECT(&s->gpu_bus_mr), &error_abort); /* Random Number Generator */ - object_initialize(&s->rng, sizeof(s->rng), TYPE_BCM2835_RNG); - object_property_add_child(obj, "rng", OBJECT(&s->rng), NULL); - qdev_set_parent_bus(DEVICE(&s->rng), sysbus_get_default()); + sysbus_init_child_obj(obj, "rng", &s->rng, sizeof(s->rng), + TYPE_BCM2835_RNG); /* Extended Mass Media Controller */ - object_initialize(&s->sdhci, sizeof(s->sdhci), TYPE_SYSBUS_SDHCI); - object_property_add_child(obj, "sdhci", OBJECT(&s->sdhci), NULL); - qdev_set_parent_bus(DEVICE(&s->sdhci), sysbus_get_default()); + sysbus_init_child_obj(obj, "sdhci", &s->sdhci, sizeof(s->sdhci), + TYPE_SYSBUS_SDHCI); /* SDHOST */ - object_initialize(&s->sdhost, sizeof(s->sdhost), TYPE_BCM2835_SDHOST); - object_property_add_child(obj, "sdhost", OBJECT(&s->sdhost), NULL); - qdev_set_parent_bus(DEVICE(&s->sdhost), sysbus_get_default()); + sysbus_init_child_obj(obj, "sdhost", &s->sdhost, sizeof(s->sdhost), + TYPE_BCM2835_SDHOST); /* DMA Channels */ - object_initialize(&s->dma, sizeof(s->dma), TYPE_BCM2835_DMA); - object_property_add_child(obj, "dma", OBJECT(&s->dma), NULL); - qdev_set_parent_bus(DEVICE(&s->dma), sysbus_get_default()); + sysbus_init_child_obj(obj, "dma", &s->dma, sizeof(s->dma), + TYPE_BCM2835_DMA); object_property_add_const_link(OBJECT(&s->dma), "dma-mr", OBJECT(&s->gpu_bus_mr), &error_abort); /* GPIO */ - object_initialize(&s->gpio, sizeof(s->gpio), TYPE_BCM2835_GPIO); - object_property_add_child(obj, "gpio", OBJECT(&s->gpio), NULL); - qdev_set_parent_bus(DEVICE(&s->gpio), sysbus_get_default()); + sysbus_init_child_obj(obj, "gpio", &s->gpio, sizeof(s->gpio), + TYPE_BCM2835_GPIO); object_property_add_const_link(OBJECT(&s->gpio), "sdbus-sdhci", OBJECT(&s->sdhci.sdbus), &error_abort); @@ -166,16 +153,16 @@ static void bcm2835_peripherals_realize(DeviceState *dev, Error **errp) sysbus_pass_irq(SYS_BUS_DEVICE(s), SYS_BUS_DEVICE(&s->ic)); /* UART0 */ - qdev_prop_set_chr(DEVICE(s->uart0), "chardev", serial_hd(0)); - object_property_set_bool(OBJECT(s->uart0), true, "realized", &err); + qdev_prop_set_chr(DEVICE(&s->uart0), "chardev", serial_hd(0)); + object_property_set_bool(OBJECT(&s->uart0), true, "realized", &err); if (err) { error_propagate(errp, err); return; } memory_region_add_subregion(&s->peri_mr, UART0_OFFSET, - sysbus_mmio_get_region(s->uart0, 0)); - sysbus_connect_irq(s->uart0, 0, + sysbus_mmio_get_region(SYS_BUS_DEVICE(&s->uart0), 0)); + sysbus_connect_irq(SYS_BUS_DEVICE(&s->uart0), 0, qdev_get_gpio_in_named(DEVICE(&s->ic), BCM2835_IC_GPU_IRQ, INTERRUPT_UART)); /* AUX / UART1 */ diff --git a/hw/arm/digic.c b/hw/arm/digic.c index 726abb9b48..6ef26c6bac 100644 --- a/hw/arm/digic.c +++ b/hw/arm/digic.c @@ -32,27 +32,22 @@ static void digic_init(Object *obj) { DigicState *s = DIGIC(obj); - DeviceState *dev; int i; - object_initialize(&s->cpu, sizeof(s->cpu), "arm946-" TYPE_ARM_CPU); - object_property_add_child(obj, "cpu", OBJECT(&s->cpu), NULL); + object_initialize_child(obj, "cpu", &s->cpu, sizeof(s->cpu), + "arm946-" TYPE_ARM_CPU, &error_abort, NULL); for (i = 0; i < DIGIC4_NB_TIMERS; i++) { #define DIGIC_TIMER_NAME_MLEN 11 char name[DIGIC_TIMER_NAME_MLEN]; - object_initialize(&s->timer[i], sizeof(s->timer[i]), TYPE_DIGIC_TIMER); - dev = DEVICE(&s->timer[i]); - qdev_set_parent_bus(dev, sysbus_get_default()); snprintf(name, DIGIC_TIMER_NAME_MLEN, "timer[%d]", i); - object_property_add_child(obj, name, OBJECT(&s->timer[i]), NULL); + sysbus_init_child_obj(obj, name, &s->timer[i], sizeof(s->timer[i]), + TYPE_DIGIC_TIMER); } - object_initialize(&s->uart, sizeof(s->uart), TYPE_DIGIC_UART); - dev = DEVICE(&s->uart); - qdev_set_parent_bus(dev, sysbus_get_default()); - object_property_add_child(obj, "uart", OBJECT(&s->uart), NULL); + sysbus_init_child_obj(obj, "uart", &s->uart, sizeof(s->uart), + TYPE_DIGIC_UART); } static void digic_realize(DeviceState *dev, Error **errp) diff --git a/hw/arm/imx25_pdk.c b/hw/arm/imx25_pdk.c index 9f3ee14739..a0423ffb67 100644 --- a/hw/arm/imx25_pdk.c +++ b/hw/arm/imx25_pdk.c @@ -72,9 +72,8 @@ static void imx25_pdk_init(MachineState *machine) unsigned int alias_offset; int i; - object_initialize(&s->soc, sizeof(s->soc), TYPE_FSL_IMX25); - object_property_add_child(OBJECT(machine), "soc", OBJECT(&s->soc), - &error_abort); + object_initialize_child(OBJECT(machine), "soc", &s->soc, sizeof(s->soc), + TYPE_FSL_IMX25, &error_abort, NULL); object_property_set_bool(OBJECT(&s->soc), true, "realized", &error_fatal); @@ -132,15 +131,6 @@ static void imx25_pdk_init(MachineState *machine) */ if (!qtest_enabled()) { arm_load_kernel(&s->soc.cpu, &imx25_pdk_binfo); - } else { - /* - * This I2C device doesn't exist on the real board. - * We add it here (only on qtest usage) to be able to do a bit - * of simple qtest. See "make check" for details. - */ - i2c_create_slave((I2CBus *)qdev_get_child_bus(DEVICE(&s->soc.i2c[0]), - "i2c-bus.0"), - "ds1338", 0x68); } } diff --git a/hw/arm/kzm.c b/hw/arm/kzm.c index 139934c4ec..44cba8782b 100644 --- a/hw/arm/kzm.c +++ b/hw/arm/kzm.c @@ -71,9 +71,8 @@ static void kzm_init(MachineState *machine) unsigned int alias_offset; unsigned int i; - object_initialize(&s->soc, sizeof(s->soc), TYPE_FSL_IMX31); - object_property_add_child(OBJECT(machine), "soc", OBJECT(&s->soc), - &error_abort); + object_initialize_child(OBJECT(machine), "soc", &s->soc, sizeof(s->soc), + TYPE_FSL_IMX31, &error_abort, NULL); object_property_set_bool(OBJECT(&s->soc), true, "realized", &error_fatal); diff --git a/hw/arm/mps2-tz.c b/hw/arm/mps2-tz.c index c167a5fa59..d85dc2c4bd 100644 --- a/hw/arm/mps2-tz.c +++ b/hw/arm/mps2-tz.c @@ -214,9 +214,9 @@ static MemoryRegion *make_scc(MPS2TZMachineState *mms, void *opaque, DeviceState *sccdev; MPS2TZMachineClass *mmc = MPS2TZ_MACHINE_GET_CLASS(mms); - object_initialize(scc, sizeof(mms->scc), TYPE_MPS2_SCC); + sysbus_init_child_obj(OBJECT(mms), "scc", scc, + sizeof(mms->scc), TYPE_MPS2_SCC); sccdev = DEVICE(scc); - qdev_set_parent_bus(sccdev, sysbus_get_default()); qdev_prop_set_uint32(sccdev, "scc-cfg4", 0x2); qdev_prop_set_uint32(sccdev, "scc-aid", 0x00200008); qdev_prop_set_uint32(sccdev, "scc-id", mmc->scc_id); @@ -229,8 +229,8 @@ static MemoryRegion *make_fpgaio(MPS2TZMachineState *mms, void *opaque, { MPS2FPGAIO *fpgaio = opaque; - object_initialize(fpgaio, sizeof(mms->fpgaio), TYPE_MPS2_FPGAIO); - qdev_set_parent_bus(DEVICE(fpgaio), sysbus_get_default()); + sysbus_init_child_obj(OBJECT(mms), "fpgaio", fpgaio, + sizeof(mms->fpgaio), TYPE_MPS2_FPGAIO); object_property_set_bool(OBJECT(fpgaio), true, "realized", &error_fatal); return sysbus_mmio_get_region(SYS_BUS_DEVICE(fpgaio), 0); } diff --git a/hw/arm/mps2.c b/hw/arm/mps2.c index b74f1378c9..10efff36b2 100644 --- a/hw/arm/mps2.c +++ b/hw/arm/mps2.c @@ -174,9 +174,9 @@ static void mps2_common_init(MachineState *machine) g_assert_not_reached(); } - object_initialize(&mms->armv7m, sizeof(mms->armv7m), TYPE_ARMV7M); + sysbus_init_child_obj(OBJECT(mms), "armv7m", &mms->armv7m, + sizeof(mms->armv7m), TYPE_ARMV7M); armv7m = DEVICE(&mms->armv7m); - qdev_set_parent_bus(armv7m, sysbus_get_default()); switch (mmc->fpga_type) { case FPGA_AN385: qdev_prop_set_uint32(armv7m, "num-irq", 32); @@ -308,9 +308,9 @@ static void mps2_common_init(MachineState *machine) qdev_get_gpio_in(armv7m, 10)); sysbus_mmio_map(SYS_BUS_DEVICE(&mms->dualtimer), 0, 0x40002000); - object_initialize(&mms->scc, sizeof(mms->scc), TYPE_MPS2_SCC); + sysbus_init_child_obj(OBJECT(mms), "scc", &mms->scc, + sizeof(mms->scc), TYPE_MPS2_SCC); sccdev = DEVICE(&mms->scc); - qdev_set_parent_bus(sccdev, sysbus_get_default()); qdev_prop_set_uint32(sccdev, "scc-cfg4", 0x2); qdev_prop_set_uint32(sccdev, "scc-aid", 0x00200008); qdev_prop_set_uint32(sccdev, "scc-id", mmc->scc_id); diff --git a/hw/arm/raspi.c b/hw/arm/raspi.c index 2b5fe10e2f..8c249fcabb 100644 --- a/hw/arm/raspi.c +++ b/hw/arm/raspi.c @@ -182,10 +182,9 @@ static void raspi_init(MachineState *machine, int version) exit(1); } - object_initialize(&s->soc, sizeof(s->soc), - version == 3 ? TYPE_BCM2837 : TYPE_BCM2836); - object_property_add_child(OBJECT(machine), "soc", OBJECT(&s->soc), - &error_abort); + object_initialize_child(OBJECT(machine), "soc", &s->soc, sizeof(s->soc), + version == 3 ? TYPE_BCM2837 : TYPE_BCM2836, + &error_abort, NULL); /* Allocate and map RAM */ memory_region_allocate_system_memory(&s->ram, OBJECT(machine), "ram", diff --git a/hw/arm/sabrelite.c b/hw/arm/sabrelite.c index ee140e5d9e..f1b00de229 100644 --- a/hw/arm/sabrelite.c +++ b/hw/arm/sabrelite.c @@ -55,9 +55,8 @@ static void sabrelite_init(MachineState *machine) exit(1); } - object_initialize(&s->soc, sizeof(s->soc), TYPE_FSL_IMX6); - object_property_add_child(OBJECT(machine), "soc", OBJECT(&s->soc), - &error_abort); + object_initialize_child(OBJECT(machine), "soc", &s->soc, sizeof(s->soc), + TYPE_FSL_IMX6, &error_abort, NULL); object_property_set_bool(OBJECT(&s->soc), true, "realized", &err); if (err != NULL) { diff --git a/hw/arm/virt-acpi-build.c b/hw/arm/virt-acpi-build.c index e7c96d658e..4a64f9985c 100644 --- a/hw/arm/virt-acpi-build.c +++ b/hw/arm/virt-acpi-build.c @@ -546,23 +546,6 @@ build_srat(GArray *table_data, BIOSLinker *linker, VirtMachineState *vms) "SRAT", table_data->len - srat_start, 3, NULL, NULL); } -static void -build_mcfg(GArray *table_data, BIOSLinker *linker, AcpiMcfgInfo *info) -{ - AcpiTableMcfg *mcfg; - int len = sizeof(*mcfg) + sizeof(mcfg->allocation[0]); - - mcfg = acpi_data_push(table_data, len); - mcfg->allocation[0].address = cpu_to_le64(info->base); - - /* Only a single allocation so no need to play with segments */ - mcfg->allocation[0].pci_segment = cpu_to_le16(0); - mcfg->allocation[0].start_bus_number = 0; - mcfg->allocation[0].end_bus_number = PCIE_MMCFG_BUS(info->size - 1); - - build_header(linker, table_data, (void *)mcfg, "MCFG", len, 1, NULL, NULL); -} - /* GTDT */ static void build_gtdt(GArray *table_data, BIOSLinker *linker, VirtMachineState *vms) diff --git a/hw/arm/xlnx-zcu102.c b/hw/arm/xlnx-zcu102.c index b6bc6a93b8..c802f26fbd 100644 --- a/hw/arm/xlnx-zcu102.c +++ b/hw/arm/xlnx-zcu102.c @@ -91,9 +91,8 @@ static void xlnx_zcu102_init(MachineState *machine) memory_region_allocate_system_memory(&s->ddr_ram, NULL, "ddr-ram", ram_size); - object_initialize(&s->soc, sizeof(s->soc), TYPE_XLNX_ZYNQMP); - object_property_add_child(OBJECT(machine), "soc", OBJECT(&s->soc), - &error_abort); + object_initialize_child(OBJECT(machine), "soc", &s->soc, sizeof(s->soc), + TYPE_XLNX_ZYNQMP, &error_abort, NULL); object_property_set_link(OBJECT(&s->soc), OBJECT(&s->ddr_ram), "ddr-ram", &error_abort); diff --git a/hw/arm/xlnx-zynqmp.c b/hw/arm/xlnx-zynqmp.c index 4f8bc41d9d..6e99190302 100644 --- a/hw/arm/xlnx-zynqmp.c +++ b/hw/arm/xlnx-zynqmp.c @@ -191,10 +191,10 @@ static void xlnx_zynqmp_create_rpu(XlnxZynqMPState *s, const char *boot_cpu, for (i = 0; i < num_rpus; i++) { char *name; - object_initialize(&s->rpu_cpu[i], sizeof(s->rpu_cpu[i]), - "cortex-r5f-" TYPE_ARM_CPU); - object_property_add_child(OBJECT(&s->rpu_cluster), "rpu-cpu[*]", - OBJECT(&s->rpu_cpu[i]), &error_abort); + object_initialize_child(OBJECT(&s->rpu_cluster), "rpu-cpu[*]", + &s->rpu_cpu[i], sizeof(s->rpu_cpu[i]), + "cortex-r5f-" TYPE_ARM_CPU, &error_abort, + NULL); name = object_get_canonical_path_component(OBJECT(&s->rpu_cpu[i])); if (strcmp(name, boot_cpu)) { diff --git a/hw/audio/ac97.c b/hw/audio/ac97.c index 2265622d44..a4e8d99e77 100644 --- a/hw/audio/ac97.c +++ b/hw/audio/ac97.c @@ -1388,7 +1388,7 @@ static void ac97_realize(PCIDevice *dev, Error **errp) pci_register_bar (&s->dev, 0, PCI_BASE_ADDRESS_SPACE_IO, &s->io_nam); pci_register_bar (&s->dev, 1, PCI_BASE_ADDRESS_SPACE_IO, &s->io_nabm); AUD_register_card ("ac97", &s->card); - ac97_on_reset (&s->dev.qdev); + ac97_on_reset(DEVICE(s)); } static void ac97_exit(PCIDevice *dev) diff --git a/hw/block/dataplane/virtio-blk.c b/hw/block/dataplane/virtio-blk.c index 8c37bd314a..158c78f852 100644 --- a/hw/block/dataplane/virtio-blk.c +++ b/hw/block/dataplane/virtio-blk.c @@ -173,6 +173,7 @@ int virtio_blk_data_plane_start(VirtIODevice *vdev) VirtioBusClass *k = VIRTIO_BUS_GET_CLASS(qbus); unsigned i; unsigned nvqs = s->conf->num_queues; + Error *local_err = NULL; int r; if (vblk->dataplane_started || s->starting) { @@ -212,7 +213,11 @@ int virtio_blk_data_plane_start(VirtIODevice *vdev) vblk->dataplane_started = true; trace_virtio_blk_data_plane_start(s); - blk_set_aio_context(s->conf->conf.blk, s->ctx); + r = blk_set_aio_context(s->conf->conf.blk, s->ctx, &local_err); + if (r < 0) { + error_report_err(local_err); + goto fail_guest_notifiers; + } /* Kick right away to begin processing requests already in vring */ for (i = 0; i < nvqs; i++) { @@ -281,8 +286,9 @@ void virtio_blk_data_plane_stop(VirtIODevice *vdev) aio_context_acquire(s->ctx); aio_wait_bh_oneshot(s->ctx, virtio_blk_data_plane_stop_bh, s); - /* Drain and switch bs back to the QEMU main loop */ - blk_set_aio_context(s->conf->conf.blk, qemu_get_aio_context()); + /* Drain and try to switch bs back to the QEMU main loop. If other users + * keep the BlockBackend in the iothread, that's ok */ + blk_set_aio_context(s->conf->conf.blk, qemu_get_aio_context(), NULL); aio_context_release(s->ctx); diff --git a/hw/block/dataplane/xen-block.c b/hw/block/dataplane/xen-block.c index bb8f1186e4..f7ad452bbd 100644 --- a/hw/block/dataplane/xen-block.c +++ b/hw/block/dataplane/xen-block.c @@ -682,7 +682,8 @@ void xen_block_dataplane_stop(XenBlockDataPlane *dataplane) } aio_context_acquire(dataplane->ctx); - blk_set_aio_context(dataplane->blk, qemu_get_aio_context()); + /* Xen doesn't have multiple users for nodes, so this can't fail */ + blk_set_aio_context(dataplane->blk, qemu_get_aio_context(), &error_abort); aio_context_release(dataplane->ctx); xendev = dataplane->xendev; @@ -811,7 +812,8 @@ void xen_block_dataplane_start(XenBlockDataPlane *dataplane, } aio_context_acquire(dataplane->ctx); - blk_set_aio_context(dataplane->blk, dataplane->ctx); + /* If other users keep the BlockBackend in the iothread, that's ok */ + blk_set_aio_context(dataplane->blk, dataplane->ctx, NULL); aio_context_release(dataplane->ctx); return; diff --git a/hw/block/fdc.c b/hw/block/fdc.c index 6f19f127a5..37ccedc9f7 100644 --- a/hw/block/fdc.c +++ b/hw/block/fdc.c @@ -538,7 +538,7 @@ static void floppy_drive_realize(DeviceState *qdev, Error **errp) if (!dev->conf.blk) { /* Anonymous BlockBackend for an empty drive */ - dev->conf.blk = blk_new(0, BLK_PERM_ALL); + dev->conf.blk = blk_new(qemu_get_aio_context(), 0, BLK_PERM_ALL); ret = blk_attach_dev(dev->conf.blk, qdev); assert(ret == 0); } diff --git a/hw/block/nvme.c b/hw/block/nvme.c index 63a5b58849..30e50f7a38 100644 --- a/hw/block/nvme.c +++ b/hw/block/nvme.c @@ -219,6 +219,30 @@ static uint16_t nvme_map_prp(QEMUSGList *qsg, QEMUIOVector *iov, uint64_t prp1, return NVME_INVALID_FIELD | NVME_DNR; } +static uint16_t nvme_dma_write_prp(NvmeCtrl *n, uint8_t *ptr, uint32_t len, + uint64_t prp1, uint64_t prp2) +{ + QEMUSGList qsg; + QEMUIOVector iov; + uint16_t status = NVME_SUCCESS; + + if (nvme_map_prp(&qsg, &iov, prp1, prp2, len, n)) { + return NVME_INVALID_FIELD | NVME_DNR; + } + if (qsg.nsg > 0) { + if (dma_buf_write(ptr, len, &qsg)) { + status = NVME_INVALID_FIELD | NVME_DNR; + } + qemu_sglist_destroy(&qsg); + } else { + if (qemu_iovec_to_buf(&iov, 0, ptr, len) != len) { + status = NVME_INVALID_FIELD | NVME_DNR; + } + qemu_iovec_destroy(&iov); + } + return status; +} + static uint16_t nvme_dma_read_prp(NvmeCtrl *n, uint8_t *ptr, uint32_t len, uint64_t prp1, uint64_t prp2) { @@ -678,7 +702,6 @@ static uint16_t nvme_identify_nslist(NvmeCtrl *n, NvmeIdentify *c) return ret; } - static uint16_t nvme_identify(NvmeCtrl *n, NvmeCmd *cmd) { NvmeIdentify *c = (NvmeIdentify *)cmd; @@ -696,6 +719,57 @@ static uint16_t nvme_identify(NvmeCtrl *n, NvmeCmd *cmd) } } +static inline void nvme_set_timestamp(NvmeCtrl *n, uint64_t ts) +{ + trace_nvme_setfeat_timestamp(ts); + + n->host_timestamp = le64_to_cpu(ts); + n->timestamp_set_qemu_clock_ms = qemu_clock_get_ms(QEMU_CLOCK_VIRTUAL); +} + +static inline uint64_t nvme_get_timestamp(const NvmeCtrl *n) +{ + uint64_t current_time = qemu_clock_get_ms(QEMU_CLOCK_VIRTUAL); + uint64_t elapsed_time = current_time - n->timestamp_set_qemu_clock_ms; + + union nvme_timestamp { + struct { + uint64_t timestamp:48; + uint64_t sync:1; + uint64_t origin:3; + uint64_t rsvd1:12; + }; + uint64_t all; + }; + + union nvme_timestamp ts; + ts.all = 0; + + /* + * If the sum of the Timestamp value set by the host and the elapsed + * time exceeds 2^48, the value returned should be reduced modulo 2^48. + */ + ts.timestamp = (n->host_timestamp + elapsed_time) & 0xffffffffffff; + + /* If the host timestamp is non-zero, set the timestamp origin */ + ts.origin = n->host_timestamp ? 0x01 : 0x00; + + trace_nvme_getfeat_timestamp(ts.all); + + return cpu_to_le64(ts.all); +} + +static uint16_t nvme_get_feature_timestamp(NvmeCtrl *n, NvmeCmd *cmd) +{ + uint64_t prp1 = le64_to_cpu(cmd->prp1); + uint64_t prp2 = le64_to_cpu(cmd->prp2); + + uint64_t timestamp = nvme_get_timestamp(n); + + return nvme_dma_read_prp(n, (uint8_t *)×tamp, + sizeof(timestamp), prp1, prp2); +} + static uint16_t nvme_get_feature(NvmeCtrl *n, NvmeCmd *cmd, NvmeRequest *req) { uint32_t dw10 = le32_to_cpu(cmd->cdw10); @@ -710,6 +784,9 @@ static uint16_t nvme_get_feature(NvmeCtrl *n, NvmeCmd *cmd, NvmeRequest *req) result = cpu_to_le32((n->num_queues - 2) | ((n->num_queues - 2) << 16)); trace_nvme_getfeat_numq(result); break; + case NVME_TIMESTAMP: + return nvme_get_feature_timestamp(n, cmd); + break; default: trace_nvme_err_invalid_getfeat(dw10); return NVME_INVALID_FIELD | NVME_DNR; @@ -719,6 +796,24 @@ static uint16_t nvme_get_feature(NvmeCtrl *n, NvmeCmd *cmd, NvmeRequest *req) return NVME_SUCCESS; } +static uint16_t nvme_set_feature_timestamp(NvmeCtrl *n, NvmeCmd *cmd) +{ + uint16_t ret; + uint64_t timestamp; + uint64_t prp1 = le64_to_cpu(cmd->prp1); + uint64_t prp2 = le64_to_cpu(cmd->prp2); + + ret = nvme_dma_write_prp(n, (uint8_t *)×tamp, + sizeof(timestamp), prp1, prp2); + if (ret != NVME_SUCCESS) { + return ret; + } + + nvme_set_timestamp(n, timestamp); + + return NVME_SUCCESS; +} + static uint16_t nvme_set_feature(NvmeCtrl *n, NvmeCmd *cmd, NvmeRequest *req) { uint32_t dw10 = le32_to_cpu(cmd->cdw10); @@ -735,6 +830,11 @@ static uint16_t nvme_set_feature(NvmeCtrl *n, NvmeCmd *cmd, NvmeRequest *req) req->cqe.result = cpu_to_le32((n->num_queues - 2) | ((n->num_queues - 2) << 16)); break; + + case NVME_TIMESTAMP: + return nvme_set_feature_timestamp(n, cmd); + break; + default: trace_nvme_err_invalid_setfeat(dw10); return NVME_INVALID_FIELD | NVME_DNR; @@ -907,6 +1007,8 @@ static int nvme_start_ctrl(NvmeCtrl *n) nvme_init_sq(&n->admin_sq, n, n->bar.asq, 0, 0, NVME_AQA_ASQS(n->bar.aqa) + 1); + nvme_set_timestamp(n, 0ULL); + return 0; } @@ -1270,7 +1372,7 @@ static void nvme_realize(PCIDevice *pci_dev, Error **errp) id->sqes = (0x6 << 4) | 0x6; id->cqes = (0x4 << 4) | 0x4; id->nn = cpu_to_le32(n->num_namespaces); - id->oncs = cpu_to_le16(NVME_ONCS_WRITE_ZEROS); + id->oncs = cpu_to_le16(NVME_ONCS_WRITE_ZEROS | NVME_ONCS_TIMESTAMP); id->psd[0].mp = cpu_to_le16(0x9c4); id->psd[0].enlat = cpu_to_le32(0x10); id->psd[0].exlat = cpu_to_le32(0x4); diff --git a/hw/block/nvme.h b/hw/block/nvme.h index 56c9d4b4b1..557194ee19 100644 --- a/hw/block/nvme.h +++ b/hw/block/nvme.h @@ -79,6 +79,8 @@ typedef struct NvmeCtrl { uint32_t cmbloc; uint8_t *cmbuf; uint64_t irq_status; + uint64_t host_timestamp; /* Timestamp sent by the host */ + uint64_t timestamp_set_qemu_clock_ms; /* QEMU clock time */ char *serial; NvmeNamespace *namespaces; diff --git a/hw/block/trace-events b/hw/block/trace-events index b92039a573..97a17838ed 100644 --- a/hw/block/trace-events +++ b/hw/block/trace-events @@ -46,6 +46,8 @@ nvme_identify_nslist(uint16_t ns) "identify namespace list, nsid=%"PRIu16"" nvme_getfeat_vwcache(const char* result) "get feature volatile write cache, result=%s" nvme_getfeat_numq(int result) "get feature number of queues, result=%d" nvme_setfeat_numq(int reqcq, int reqsq, int gotcq, int gotsq) "requested cq_count=%d sq_count=%d, responding with cq_count=%d sq_count=%d" +nvme_setfeat_timestamp(uint64_t ts) "set feature timestamp = 0x%"PRIx64"" +nvme_getfeat_timestamp(uint64_t ts) "get feature timestamp = 0x%"PRIx64"" nvme_mmio_intm_set(uint64_t data, uint64_t new_mask) "wrote MMIO, interrupt mask set, data=0x%"PRIx64", new_mask=0x%"PRIx64"" nvme_mmio_intm_clr(uint64_t data, uint64_t new_mask) "wrote MMIO, interrupt mask clr, data=0x%"PRIx64", new_mask=0x%"PRIx64"" nvme_mmio_cfg(uint64_t data) "wrote MMIO, config controller config=0x%"PRIx64"" diff --git a/hw/block/xen-block.c b/hw/block/xen-block.c index ef635be4c2..31b0f5ccc8 100644 --- a/hw/block/xen-block.c +++ b/hw/block/xen-block.c @@ -609,7 +609,7 @@ static void xen_cdrom_realize(XenBlockDevice *blockdev, Error **errp) int rc; /* Set up an empty drive */ - conf->blk = blk_new(0, BLK_PERM_ALL); + conf->blk = blk_new(qemu_get_aio_context(), 0, BLK_PERM_ALL); rc = blk_attach_dev(conf->blk, DEVICE(blockdev)); if (!rc) { diff --git a/hw/core/machine.c b/hw/core/machine.c index 16ba667434..f1a0f45f9c 100644 --- a/hw/core/machine.c +++ b/hw/core/machine.c @@ -24,6 +24,9 @@ #include "hw/pci/pci.h" #include "hw/mem/nvdimm.h" +GlobalProperty hw_compat_4_0_1[] = {}; +const size_t hw_compat_4_0_1_len = G_N_ELEMENTS(hw_compat_4_0_1); + GlobalProperty hw_compat_4_0[] = {}; const size_t hw_compat_4_0_len = G_N_ELEMENTS(hw_compat_4_0); diff --git a/hw/core/qdev-properties-system.c b/hw/core/qdev-properties-system.c index b45a7ef54b..ba412dd2ca 100644 --- a/hw/core/qdev-properties-system.c +++ b/hw/core/qdev-properties-system.c @@ -69,8 +69,8 @@ static void set_pointer(Object *obj, Visitor *v, Property *prop, /* --- drive --- */ -static void parse_drive(DeviceState *dev, const char *str, void **ptr, - const char *propname, Error **errp) +static void do_parse_drive(DeviceState *dev, const char *str, void **ptr, + const char *propname, bool iothread, Error **errp) { BlockBackend *blk; bool blk_created = false; @@ -80,7 +80,16 @@ static void parse_drive(DeviceState *dev, const char *str, void **ptr, if (!blk) { BlockDriverState *bs = bdrv_lookup_bs(NULL, str, NULL); if (bs) { - blk = blk_new(0, BLK_PERM_ALL); + /* + * If the device supports iothreads, it will make sure to move the + * block node to the right AioContext if necessary (or fail if this + * isn't possible because of other users). Devices that are not + * aware of iothreads require their BlockBackends to be in the main + * AioContext. + */ + AioContext *ctx = iothread ? bdrv_get_aio_context(bs) : + qemu_get_aio_context(); + blk = blk_new(ctx, 0, BLK_PERM_ALL); blk_created = true; ret = blk_insert_bs(blk, bs, errp); @@ -118,6 +127,18 @@ fail: } } +static void parse_drive(DeviceState *dev, const char *str, void **ptr, + const char *propname, Error **errp) +{ + do_parse_drive(dev, str, ptr, propname, false, errp); +} + +static void parse_drive_iothread(DeviceState *dev, const char *str, void **ptr, + const char *propname, Error **errp) +{ + do_parse_drive(dev, str, ptr, propname, true, errp); +} + static void release_drive(Object *obj, const char *name, void *opaque) { DeviceState *dev = DEVICE(obj); @@ -160,6 +181,12 @@ static void set_drive(Object *obj, Visitor *v, const char *name, void *opaque, set_pointer(obj, v, opaque, parse_drive, name, errp); } +static void set_drive_iothread(Object *obj, Visitor *v, const char *name, + void *opaque, Error **errp) +{ + set_pointer(obj, v, opaque, parse_drive_iothread, name, errp); +} + const PropertyInfo qdev_prop_drive = { .name = "str", .description = "Node name or ID of a block device to use as a backend", @@ -168,6 +195,14 @@ const PropertyInfo qdev_prop_drive = { .release = release_drive, }; +const PropertyInfo qdev_prop_drive_iothread = { + .name = "str", + .description = "Node name or ID of a block device to use as a backend", + .get = get_drive, + .set = set_drive_iothread, + .release = release_drive, +}; + /* --- character device --- */ static void get_chr(Object *obj, Visitor *v, const char *name, void *opaque, diff --git a/hw/core/sysbus.c b/hw/core/sysbus.c index 307cf90a51..689a867a22 100644 --- a/hw/core/sysbus.c +++ b/hw/core/sysbus.c @@ -153,6 +153,16 @@ static void sysbus_mmio_map_common(SysBusDevice *dev, int n, hwaddr addr, } } +void sysbus_mmio_unmap(SysBusDevice *dev, int n) +{ + assert(n >= 0 && n < dev->num_mmio); + + if (dev->mmio[n].addr != (hwaddr)-1) { + memory_region_del_subregion(get_system_memory(), dev->mmio[n].memory); + dev->mmio[n].addr = (hwaddr)-1; + } +} + void sysbus_mmio_map(SysBusDevice *dev, int n, hwaddr addr) { sysbus_mmio_map_common(dev, n, addr, false, 0); diff --git a/hw/display/Kconfig b/hw/display/Kconfig index dc1f113df2..910dccb2f7 100644 --- a/hw/display/Kconfig +++ b/hw/display/Kconfig @@ -111,6 +111,16 @@ config VIRTIO_VGA depends on VIRTIO_PCI select VGA +config VHOST_USER_GPU + bool + default y + depends on VIRTIO_GPU && VHOST_USER + +config VHOST_USER_VGA + bool + default y + depends on VIRTIO_VGA && VHOST_USER_GPU + config DPCD bool select AUX diff --git a/hw/display/Makefile.objs b/hw/display/Makefile.objs index 650031f725..a64998fc7b 100644 --- a/hw/display/Makefile.objs +++ b/hw/display/Makefile.objs @@ -43,9 +43,12 @@ obj-$(CONFIG_VGA) += vga.o common-obj-$(CONFIG_QXL) += qxl.o qxl-logger.o qxl-render.o -obj-$(CONFIG_VIRTIO_GPU) += virtio-gpu.o virtio-gpu-3d.o +obj-$(CONFIG_VIRTIO_GPU) += virtio-gpu-base.o virtio-gpu.o virtio-gpu-3d.o +obj-$(CONFIG_VHOST_USER_GPU) += vhost-user-gpu.o obj-$(call land,$(CONFIG_VIRTIO_GPU),$(CONFIG_VIRTIO_PCI)) += virtio-gpu-pci.o +obj-$(call land,$(CONFIG_VHOST_USER_GPU),$(CONFIG_VIRTIO_PCI)) += vhost-user-gpu-pci.o obj-$(CONFIG_VIRTIO_VGA) += virtio-vga.o +obj-$(CONFIG_VHOST_USER_VGA) += vhost-user-vga.o virtio-gpu.o-cflags := $(VIRGL_CFLAGS) virtio-gpu.o-libs += $(VIRGL_LIBS) virtio-gpu-3d.o-cflags := $(VIRGL_CFLAGS) diff --git a/hw/display/vhost-user-gpu-pci.c b/hw/display/vhost-user-gpu-pci.c new file mode 100644 index 0000000000..7d9b1f5a8c --- /dev/null +++ b/hw/display/vhost-user-gpu-pci.c @@ -0,0 +1,51 @@ +/* + * vhost-user GPU PCI device + * + * Copyright Red Hat, Inc. 2018 + * + * This work is licensed under the terms of the GNU GPL, version 2 or later. + * See the COPYING file in the top-level directory. + * + */ + +#include "qemu/osdep.h" +#include "qapi/error.h" +#include "hw/virtio/virtio-gpu-pci.h" + +#define TYPE_VHOST_USER_GPU_PCI "vhost-user-gpu-pci" +#define VHOST_USER_GPU_PCI(obj) \ + OBJECT_CHECK(VhostUserGPUPCI, (obj), TYPE_VHOST_USER_GPU_PCI) + +typedef struct VhostUserGPUPCI { + VirtIOGPUPCIBase parent_obj; + + VhostUserGPU vdev; +} VhostUserGPUPCI; + +static void vhost_user_gpu_pci_initfn(Object *obj) +{ + VhostUserGPUPCI *dev = VHOST_USER_GPU_PCI(obj); + + virtio_instance_init_common(obj, &dev->vdev, sizeof(dev->vdev), + TYPE_VHOST_USER_GPU); + + VIRTIO_GPU_PCI_BASE(obj)->vgpu = VIRTIO_GPU_BASE(&dev->vdev); + + object_property_add_alias(obj, "chardev", + OBJECT(&dev->vdev), "chardev", + &error_abort); +} + +static const VirtioPCIDeviceTypeInfo vhost_user_gpu_pci_info = { + .generic_name = TYPE_VHOST_USER_GPU_PCI, + .parent = TYPE_VIRTIO_GPU_PCI_BASE, + .instance_size = sizeof(VhostUserGPUPCI), + .instance_init = vhost_user_gpu_pci_initfn, +}; + +static void vhost_user_gpu_pci_register_types(void) +{ + virtio_pci_types_register(&vhost_user_gpu_pci_info); +} + +type_init(vhost_user_gpu_pci_register_types) diff --git a/hw/display/vhost-user-gpu.c b/hw/display/vhost-user-gpu.c new file mode 100644 index 0000000000..7181d9cdba --- /dev/null +++ b/hw/display/vhost-user-gpu.c @@ -0,0 +1,607 @@ +/* + * vhost-user GPU Device + * + * Copyright Red Hat, Inc. 2018 + * + * Authors: + * Marc-André Lureau <marcandre.lureau@redhat.com> + * + * This work is licensed under the terms of the GNU GPL, version 2 or later. + * See the COPYING file in the top-level directory. + */ + +#include "qemu/osdep.h" +#include "hw/virtio/virtio-gpu.h" +#include "chardev/char-fe.h" +#include "qapi/error.h" +#include "migration/blocker.h" + +#define VHOST_USER_GPU(obj) \ + OBJECT_CHECK(VhostUserGPU, (obj), TYPE_VHOST_USER_GPU) + +typedef enum VhostUserGpuRequest { + VHOST_USER_GPU_NONE = 0, + VHOST_USER_GPU_GET_PROTOCOL_FEATURES, + VHOST_USER_GPU_SET_PROTOCOL_FEATURES, + VHOST_USER_GPU_GET_DISPLAY_INFO, + VHOST_USER_GPU_CURSOR_POS, + VHOST_USER_GPU_CURSOR_POS_HIDE, + VHOST_USER_GPU_CURSOR_UPDATE, + VHOST_USER_GPU_SCANOUT, + VHOST_USER_GPU_UPDATE, + VHOST_USER_GPU_DMABUF_SCANOUT, + VHOST_USER_GPU_DMABUF_UPDATE, +} VhostUserGpuRequest; + +typedef struct VhostUserGpuDisplayInfoReply { + struct virtio_gpu_resp_display_info info; +} VhostUserGpuDisplayInfoReply; + +typedef struct VhostUserGpuCursorPos { + uint32_t scanout_id; + uint32_t x; + uint32_t y; +} QEMU_PACKED VhostUserGpuCursorPos; + +typedef struct VhostUserGpuCursorUpdate { + VhostUserGpuCursorPos pos; + uint32_t hot_x; + uint32_t hot_y; + uint32_t data[64 * 64]; +} QEMU_PACKED VhostUserGpuCursorUpdate; + +typedef struct VhostUserGpuScanout { + uint32_t scanout_id; + uint32_t width; + uint32_t height; +} QEMU_PACKED VhostUserGpuScanout; + +typedef struct VhostUserGpuUpdate { + uint32_t scanout_id; + uint32_t x; + uint32_t y; + uint32_t width; + uint32_t height; + uint8_t data[]; +} QEMU_PACKED VhostUserGpuUpdate; + +typedef struct VhostUserGpuDMABUFScanout { + uint32_t scanout_id; + uint32_t x; + uint32_t y; + uint32_t width; + uint32_t height; + uint32_t fd_width; + uint32_t fd_height; + uint32_t fd_stride; + uint32_t fd_flags; + int fd_drm_fourcc; +} QEMU_PACKED VhostUserGpuDMABUFScanout; + +typedef struct VhostUserGpuMsg { + uint32_t request; /* VhostUserGpuRequest */ + uint32_t flags; + uint32_t size; /* the following payload size */ + union { + VhostUserGpuCursorPos cursor_pos; + VhostUserGpuCursorUpdate cursor_update; + VhostUserGpuScanout scanout; + VhostUserGpuUpdate update; + VhostUserGpuDMABUFScanout dmabuf_scanout; + struct virtio_gpu_resp_display_info display_info; + uint64_t u64; + } payload; +} QEMU_PACKED VhostUserGpuMsg; + +static VhostUserGpuMsg m __attribute__ ((unused)); +#define VHOST_USER_GPU_HDR_SIZE \ + (sizeof(m.request) + sizeof(m.size) + sizeof(m.flags)) + +#define VHOST_USER_GPU_MSG_FLAG_REPLY 0x4 + +static void vhost_user_gpu_update_blocked(VhostUserGPU *g, bool blocked); + +static void +vhost_user_gpu_handle_cursor(VhostUserGPU *g, VhostUserGpuMsg *msg) +{ + VhostUserGpuCursorPos *pos = &msg->payload.cursor_pos; + struct virtio_gpu_scanout *s; + + if (pos->scanout_id >= g->parent_obj.conf.max_outputs) { + return; + } + s = &g->parent_obj.scanout[pos->scanout_id]; + + if (msg->request == VHOST_USER_GPU_CURSOR_UPDATE) { + VhostUserGpuCursorUpdate *up = &msg->payload.cursor_update; + if (!s->current_cursor) { + s->current_cursor = cursor_alloc(64, 64); + } + + s->current_cursor->hot_x = up->hot_x; + s->current_cursor->hot_y = up->hot_y; + + memcpy(s->current_cursor->data, up->data, + 64 * 64 * sizeof(uint32_t)); + + dpy_cursor_define(s->con, s->current_cursor); + } + + dpy_mouse_set(s->con, pos->x, pos->y, + msg->request != VHOST_USER_GPU_CURSOR_POS_HIDE); +} + +static void +vhost_user_gpu_send_msg(VhostUserGPU *g, const VhostUserGpuMsg *msg) +{ + qemu_chr_fe_write(&g->vhost_chr, (uint8_t *)msg, + VHOST_USER_GPU_HDR_SIZE + msg->size); +} + +static void +vhost_user_gpu_unblock(VhostUserGPU *g) +{ + VhostUserGpuMsg msg = { + .request = VHOST_USER_GPU_DMABUF_UPDATE, + .flags = VHOST_USER_GPU_MSG_FLAG_REPLY, + }; + + vhost_user_gpu_send_msg(g, &msg); +} + +static void +vhost_user_gpu_handle_display(VhostUserGPU *g, VhostUserGpuMsg *msg) +{ + QemuConsole *con = NULL; + struct virtio_gpu_scanout *s; + + switch (msg->request) { + case VHOST_USER_GPU_GET_PROTOCOL_FEATURES: { + VhostUserGpuMsg reply = { + .request = msg->request, + .flags = VHOST_USER_GPU_MSG_FLAG_REPLY, + .size = sizeof(uint64_t), + }; + + vhost_user_gpu_send_msg(g, &reply); + break; + } + case VHOST_USER_GPU_SET_PROTOCOL_FEATURES: { + break; + } + case VHOST_USER_GPU_GET_DISPLAY_INFO: { + struct virtio_gpu_resp_display_info display_info = { {} }; + VhostUserGpuMsg reply = { + .request = msg->request, + .flags = VHOST_USER_GPU_MSG_FLAG_REPLY, + .size = sizeof(struct virtio_gpu_resp_display_info), + }; + + display_info.hdr.type = VIRTIO_GPU_RESP_OK_DISPLAY_INFO; + virtio_gpu_base_fill_display_info(VIRTIO_GPU_BASE(g), &display_info); + memcpy(&reply.payload.display_info, &display_info, + sizeof(display_info)); + vhost_user_gpu_send_msg(g, &reply); + break; + } + case VHOST_USER_GPU_SCANOUT: { + VhostUserGpuScanout *m = &msg->payload.scanout; + + if (m->scanout_id >= g->parent_obj.conf.max_outputs) { + return; + } + + g->parent_obj.enable = 1; + s = &g->parent_obj.scanout[m->scanout_id]; + con = s->con; + + if (m->scanout_id == 0 && m->width == 0) { + s->ds = qemu_create_message_surface(640, 480, + "Guest disabled display."); + dpy_gfx_replace_surface(con, s->ds); + } else { + s->ds = qemu_create_displaysurface(m->width, m->height); + /* replace surface on next update */ + } + + break; + } + case VHOST_USER_GPU_DMABUF_SCANOUT: { + VhostUserGpuDMABUFScanout *m = &msg->payload.dmabuf_scanout; + int fd = qemu_chr_fe_get_msgfd(&g->vhost_chr); + QemuDmaBuf *dmabuf; + + if (m->scanout_id >= g->parent_obj.conf.max_outputs) { + error_report("invalid scanout: %d", m->scanout_id); + if (fd >= 0) { + close(fd); + } + break; + } + + g->parent_obj.enable = 1; + con = g->parent_obj.scanout[m->scanout_id].con; + dmabuf = &g->dmabuf[m->scanout_id]; + if (dmabuf->fd >= 0) { + close(dmabuf->fd); + dmabuf->fd = -1; + } + if (!console_has_gl_dmabuf(con)) { + /* it would be nice to report that error earlier */ + error_report("console doesn't support dmabuf!"); + break; + } + dpy_gl_release_dmabuf(con, dmabuf); + if (fd == -1) { + dpy_gl_scanout_disable(con); + break; + } + *dmabuf = (QemuDmaBuf) { + .fd = fd, + .width = m->fd_width, + .height = m->fd_height, + .stride = m->fd_stride, + .fourcc = m->fd_drm_fourcc, + .y0_top = m->fd_flags & VIRTIO_GPU_RESOURCE_FLAG_Y_0_TOP, + }; + dpy_gl_scanout_dmabuf(con, dmabuf); + break; + } + case VHOST_USER_GPU_DMABUF_UPDATE: { + VhostUserGpuUpdate *m = &msg->payload.update; + + if (m->scanout_id >= g->parent_obj.conf.max_outputs || + !g->parent_obj.scanout[m->scanout_id].con) { + error_report("invalid scanout update: %d", m->scanout_id); + vhost_user_gpu_unblock(g); + break; + } + + con = g->parent_obj.scanout[m->scanout_id].con; + if (!console_has_gl(con)) { + error_report("console doesn't support GL!"); + vhost_user_gpu_unblock(g); + break; + } + dpy_gl_update(con, m->x, m->y, m->width, m->height); + g->backend_blocked = true; + break; + } + case VHOST_USER_GPU_UPDATE: { + VhostUserGpuUpdate *m = &msg->payload.update; + + if (m->scanout_id >= g->parent_obj.conf.max_outputs) { + break; + } + s = &g->parent_obj.scanout[m->scanout_id]; + con = s->con; + pixman_image_t *image = + pixman_image_create_bits(PIXMAN_x8r8g8b8, + m->width, + m->height, + (uint32_t *)m->data, + m->width * 4); + + pixman_image_composite(PIXMAN_OP_SRC, + image, NULL, s->ds->image, + 0, 0, 0, 0, m->x, m->y, m->width, m->height); + + pixman_image_unref(image); + if (qemu_console_surface(con) != s->ds) { + dpy_gfx_replace_surface(con, s->ds); + } else { + dpy_gfx_update(con, m->x, m->y, m->width, m->height); + } + break; + } + default: + g_warning("unhandled message %d %d", msg->request, msg->size); + } + + if (con && qemu_console_is_gl_blocked(con)) { + vhost_user_gpu_update_blocked(g, true); + } +} + +static void +vhost_user_gpu_chr_read(void *opaque) +{ + VhostUserGPU *g = opaque; + VhostUserGpuMsg *msg = NULL; + VhostUserGpuRequest request; + uint32_t size, flags; + int r; + + r = qemu_chr_fe_read_all(&g->vhost_chr, + (uint8_t *)&request, sizeof(uint32_t)); + if (r != sizeof(uint32_t)) { + error_report("failed to read msg header: %d, %d", r, errno); + goto end; + } + + r = qemu_chr_fe_read_all(&g->vhost_chr, + (uint8_t *)&flags, sizeof(uint32_t)); + if (r != sizeof(uint32_t)) { + error_report("failed to read msg flags"); + goto end; + } + + r = qemu_chr_fe_read_all(&g->vhost_chr, + (uint8_t *)&size, sizeof(uint32_t)); + if (r != sizeof(uint32_t)) { + error_report("failed to read msg size"); + goto end; + } + + msg = g_malloc(VHOST_USER_GPU_HDR_SIZE + size); + g_return_if_fail(msg != NULL); + + r = qemu_chr_fe_read_all(&g->vhost_chr, + (uint8_t *)&msg->payload, size); + if (r != size) { + error_report("failed to read msg payload %d != %d", r, size); + goto end; + } + + msg->request = request; + msg->flags = size; + msg->size = size; + + if (request == VHOST_USER_GPU_CURSOR_UPDATE || + request == VHOST_USER_GPU_CURSOR_POS || + request == VHOST_USER_GPU_CURSOR_POS_HIDE) { + vhost_user_gpu_handle_cursor(g, msg); + } else { + vhost_user_gpu_handle_display(g, msg); + } + +end: + g_free(msg); +} + +static void +vhost_user_gpu_update_blocked(VhostUserGPU *g, bool blocked) +{ + qemu_set_fd_handler(g->vhost_gpu_fd, + blocked ? NULL : vhost_user_gpu_chr_read, NULL, g); +} + +static void +vhost_user_gpu_gl_unblock(VirtIOGPUBase *b) +{ + VhostUserGPU *g = VHOST_USER_GPU(b); + + if (g->backend_blocked) { + vhost_user_gpu_unblock(VHOST_USER_GPU(g)); + g->backend_blocked = false; + } + + vhost_user_gpu_update_blocked(VHOST_USER_GPU(g), false); +} + +static bool +vhost_user_gpu_do_set_socket(VhostUserGPU *g, Error **errp) +{ + Chardev *chr; + int sv[2]; + + if (socketpair(PF_UNIX, SOCK_STREAM, 0, sv) == -1) { + error_setg_errno(errp, errno, "socketpair() failed"); + return false; + } + + chr = CHARDEV(object_new(TYPE_CHARDEV_SOCKET)); + if (!chr || qemu_chr_add_client(chr, sv[0]) == -1) { + error_setg(errp, "Failed to make socket chardev"); + goto err; + } + if (!qemu_chr_fe_init(&g->vhost_chr, chr, errp)) { + goto err; + } + if (vhost_user_gpu_set_socket(&g->vhost->dev, sv[1]) < 0) { + error_setg(errp, "Failed to set vhost-user-gpu socket"); + qemu_chr_fe_deinit(&g->vhost_chr, false); + goto err; + } + + g->vhost_gpu_fd = sv[0]; + vhost_user_gpu_update_blocked(g, false); + close(sv[1]); + return true; + +err: + close(sv[0]); + close(sv[1]); + if (chr) { + object_unref(OBJECT(chr)); + } + return false; +} + +static void +vhost_user_gpu_get_config(VirtIODevice *vdev, uint8_t *config_data) +{ + VhostUserGPU *g = VHOST_USER_GPU(vdev); + VirtIOGPUBase *b = VIRTIO_GPU_BASE(vdev); + struct virtio_gpu_config *vgconfig = + (struct virtio_gpu_config *)config_data; + int ret; + + memset(config_data, 0, sizeof(struct virtio_gpu_config)); + + ret = vhost_dev_get_config(&g->vhost->dev, + config_data, sizeof(struct virtio_gpu_config)); + if (ret) { + error_report("vhost-user-gpu: get device config space failed"); + return; + } + + /* those fields are managed by qemu */ + vgconfig->num_scanouts = b->virtio_config.num_scanouts; + vgconfig->events_read = b->virtio_config.events_read; + vgconfig->events_clear = b->virtio_config.events_clear; +} + +static void +vhost_user_gpu_set_config(VirtIODevice *vdev, + const uint8_t *config_data) +{ + VhostUserGPU *g = VHOST_USER_GPU(vdev); + VirtIOGPUBase *b = VIRTIO_GPU_BASE(vdev); + const struct virtio_gpu_config *vgconfig = + (const struct virtio_gpu_config *)config_data; + int ret; + + if (vgconfig->events_clear) { + b->virtio_config.events_read &= ~vgconfig->events_clear; + } + + ret = vhost_dev_set_config(&g->vhost->dev, config_data, + 0, sizeof(struct virtio_gpu_config), + VHOST_SET_CONFIG_TYPE_MASTER); + if (ret) { + error_report("vhost-user-gpu: set device config space failed"); + return; + } +} + +static void +vhost_user_gpu_set_status(VirtIODevice *vdev, uint8_t val) +{ + VhostUserGPU *g = VHOST_USER_GPU(vdev); + Error *err = NULL; + + if (val & VIRTIO_CONFIG_S_DRIVER_OK && vdev->vm_running) { + if (!vhost_user_gpu_do_set_socket(g, &err)) { + error_report_err(err); + return; + } + vhost_user_backend_start(g->vhost); + } else { + /* unblock any wait and stop processing */ + if (g->vhost_gpu_fd != -1) { + vhost_user_gpu_update_blocked(g, true); + qemu_chr_fe_deinit(&g->vhost_chr, true); + g->vhost_gpu_fd = -1; + } + vhost_user_backend_stop(g->vhost); + } +} + +static bool +vhost_user_gpu_guest_notifier_pending(VirtIODevice *vdev, int idx) +{ + VhostUserGPU *g = VHOST_USER_GPU(vdev); + + return vhost_virtqueue_pending(&g->vhost->dev, idx); +} + +static void +vhost_user_gpu_guest_notifier_mask(VirtIODevice *vdev, int idx, bool mask) +{ + VhostUserGPU *g = VHOST_USER_GPU(vdev); + + vhost_virtqueue_mask(&g->vhost->dev, vdev, idx, mask); +} + +static void +vhost_user_gpu_instance_init(Object *obj) +{ + VhostUserGPU *g = VHOST_USER_GPU(obj); + + g->vhost = VHOST_USER_BACKEND(object_new(TYPE_VHOST_USER_BACKEND)); + object_property_add_alias(obj, "chardev", + OBJECT(g->vhost), "chardev", &error_abort); +} + +static void +vhost_user_gpu_instance_finalize(Object *obj) +{ + VhostUserGPU *g = VHOST_USER_GPU(obj); + + object_unref(OBJECT(g->vhost)); +} + +static void +vhost_user_gpu_reset(VirtIODevice *vdev) +{ + VhostUserGPU *g = VHOST_USER_GPU(vdev); + + virtio_gpu_base_reset(VIRTIO_GPU_BASE(vdev)); + + vhost_user_backend_stop(g->vhost); +} + +static int +vhost_user_gpu_config_change(struct vhost_dev *dev) +{ + error_report("vhost-user-gpu: unhandled backend config change"); + return -1; +} + +static const VhostDevConfigOps config_ops = { + .vhost_dev_config_notifier = vhost_user_gpu_config_change, +}; + +static void +vhost_user_gpu_device_realize(DeviceState *qdev, Error **errp) +{ + VhostUserGPU *g = VHOST_USER_GPU(qdev); + VirtIODevice *vdev = VIRTIO_DEVICE(g); + + vhost_dev_set_config_notifier(&g->vhost->dev, &config_ops); + if (vhost_user_backend_dev_init(g->vhost, vdev, 2, errp) < 0) { + return; + } + + if (virtio_has_feature(g->vhost->dev.features, VIRTIO_GPU_F_VIRGL)) { + g->parent_obj.conf.flags |= 1 << VIRTIO_GPU_FLAG_VIRGL_ENABLED; + } + + if (!virtio_gpu_base_device_realize(qdev, NULL, NULL, errp)) { + return; + } + + g->vhost_gpu_fd = -1; +} + +static Property vhost_user_gpu_properties[] = { + VIRTIO_GPU_BASE_PROPERTIES(VhostUserGPU, parent_obj.conf), + DEFINE_PROP_END_OF_LIST(), +}; + +static void +vhost_user_gpu_class_init(ObjectClass *klass, void *data) +{ + DeviceClass *dc = DEVICE_CLASS(klass); + VirtioDeviceClass *vdc = VIRTIO_DEVICE_CLASS(klass); + VirtIOGPUBaseClass *vgc = VIRTIO_GPU_BASE_CLASS(klass); + + vgc->gl_unblock = vhost_user_gpu_gl_unblock; + + vdc->realize = vhost_user_gpu_device_realize; + vdc->reset = vhost_user_gpu_reset; + vdc->set_status = vhost_user_gpu_set_status; + vdc->guest_notifier_mask = vhost_user_gpu_guest_notifier_mask; + vdc->guest_notifier_pending = vhost_user_gpu_guest_notifier_pending; + vdc->get_config = vhost_user_gpu_get_config; + vdc->set_config = vhost_user_gpu_set_config; + + dc->props = vhost_user_gpu_properties; +} + +static const TypeInfo vhost_user_gpu_info = { + .name = TYPE_VHOST_USER_GPU, + .parent = TYPE_VIRTIO_GPU_BASE, + .instance_size = sizeof(VhostUserGPU), + .instance_init = vhost_user_gpu_instance_init, + .instance_finalize = vhost_user_gpu_instance_finalize, + .class_init = vhost_user_gpu_class_init, +}; + +static void vhost_user_gpu_register_types(void) +{ + type_register_static(&vhost_user_gpu_info); +} + +type_init(vhost_user_gpu_register_types) diff --git a/hw/display/vhost-user-vga.c b/hw/display/vhost-user-vga.c new file mode 100644 index 0000000000..a7195276d9 --- /dev/null +++ b/hw/display/vhost-user-vga.c @@ -0,0 +1,52 @@ +/* + * vhost-user VGA device + * + * Copyright Red Hat, Inc. 2018 + * + * This work is licensed under the terms of the GNU GPL, version 2 or later. + * See the COPYING file in the top-level directory. + * + */ + +#include "qemu/osdep.h" +#include "qapi/error.h" +#include "virtio-vga.h" + +#define TYPE_VHOST_USER_VGA "vhost-user-vga" + +#define VHOST_USER_VGA(obj) \ + OBJECT_CHECK(VhostUserVGA, (obj), TYPE_VHOST_USER_VGA) + +typedef struct VhostUserVGA { + VirtIOVGABase parent_obj; + + VhostUserGPU vdev; +} VhostUserVGA; + +static void vhost_user_vga_inst_initfn(Object *obj) +{ + VhostUserVGA *dev = VHOST_USER_VGA(obj); + + virtio_instance_init_common(obj, &dev->vdev, sizeof(dev->vdev), + TYPE_VHOST_USER_GPU); + + VIRTIO_VGA_BASE(dev)->vgpu = VIRTIO_GPU_BASE(&dev->vdev); + + object_property_add_alias(obj, "chardev", + OBJECT(&dev->vdev), "chardev", + &error_abort); +} + +static const VirtioPCIDeviceTypeInfo vhost_user_vga_info = { + .generic_name = TYPE_VHOST_USER_VGA, + .parent = TYPE_VIRTIO_VGA_BASE, + .instance_size = sizeof(struct VhostUserVGA), + .instance_init = vhost_user_vga_inst_initfn, +}; + +static void vhost_user_vga_register_types(void) +{ + virtio_pci_types_register(&vhost_user_vga_info); +} + +type_init(vhost_user_vga_register_types) diff --git a/hw/display/virtio-gpu-3d.c b/hw/display/virtio-gpu-3d.c index 2d302526ab..b918167aec 100644 --- a/hw/display/virtio-gpu-3d.c +++ b/hw/display/virtio-gpu-3d.c @@ -118,11 +118,11 @@ static void virgl_cmd_context_destroy(VirtIOGPU *g, static void virtio_gpu_rect_update(VirtIOGPU *g, int idx, int x, int y, int width, int height) { - if (!g->scanout[idx].con) { + if (!g->parent_obj.scanout[idx].con) { return; } - dpy_gl_update(g->scanout[idx].con, x, y, width, height); + dpy_gl_update(g->parent_obj.scanout[idx].con, x, y, width, height); } static void virgl_cmd_resource_flush(VirtIOGPU *g, @@ -135,8 +135,8 @@ static void virgl_cmd_resource_flush(VirtIOGPU *g, trace_virtio_gpu_cmd_res_flush(rf.resource_id, rf.r.width, rf.r.height, rf.r.x, rf.r.y); - for (i = 0; i < g->conf.max_outputs; i++) { - if (g->scanout[i].resource_id != rf.resource_id) { + for (i = 0; i < g->parent_obj.conf.max_outputs; i++) { + if (g->parent_obj.scanout[i].resource_id != rf.resource_id) { continue; } virtio_gpu_rect_update(g, i, rf.r.x, rf.r.y, rf.r.width, rf.r.height); @@ -154,13 +154,13 @@ static void virgl_cmd_set_scanout(VirtIOGPU *g, trace_virtio_gpu_cmd_set_scanout(ss.scanout_id, ss.resource_id, ss.r.width, ss.r.height, ss.r.x, ss.r.y); - if (ss.scanout_id >= g->conf.max_outputs) { + if (ss.scanout_id >= g->parent_obj.conf.max_outputs) { qemu_log_mask(LOG_GUEST_ERROR, "%s: illegal scanout id specified %d", __func__, ss.scanout_id); cmd->error = VIRTIO_GPU_RESP_ERR_INVALID_SCANOUT_ID; return; } - g->enable = 1; + g->parent_obj.enable = 1; memset(&info, 0, sizeof(info)); @@ -173,20 +173,22 @@ static void virgl_cmd_set_scanout(VirtIOGPU *g, cmd->error = VIRTIO_GPU_RESP_ERR_INVALID_RESOURCE_ID; return; } - qemu_console_resize(g->scanout[ss.scanout_id].con, + qemu_console_resize(g->parent_obj.scanout[ss.scanout_id].con, ss.r.width, ss.r.height); virgl_renderer_force_ctx_0(); - dpy_gl_scanout_texture(g->scanout[ss.scanout_id].con, info.tex_id, - info.flags & 1 /* FIXME: Y_0_TOP */, - info.width, info.height, - ss.r.x, ss.r.y, ss.r.width, ss.r.height); + dpy_gl_scanout_texture( + g->parent_obj.scanout[ss.scanout_id].con, info.tex_id, + info.flags & 1 /* FIXME: Y_0_TOP */, + info.width, info.height, + ss.r.x, ss.r.y, ss.r.width, ss.r.height); } else { if (ss.scanout_id != 0) { - dpy_gfx_replace_surface(g->scanout[ss.scanout_id].con, NULL); + dpy_gfx_replace_surface( + g->parent_obj.scanout[ss.scanout_id].con, NULL); } - dpy_gl_scanout_disable(g->scanout[ss.scanout_id].con); + dpy_gl_scanout_disable(g->parent_obj.scanout[ss.scanout_id].con); } - g->scanout[ss.scanout_id].resource_id = ss.resource_id; + g->parent_obj.scanout[ss.scanout_id].resource_id = ss.resource_id; } static void virgl_cmd_submit_3d(VirtIOGPU *g, @@ -209,7 +211,7 @@ static void virgl_cmd_submit_3d(VirtIOGPU *g, goto out; } - if (virtio_gpu_stats_enabled(g->conf)) { + if (virtio_gpu_stats_enabled(g->parent_obj.conf)) { g->stats.req_3d++; g->stats.bytes_3d += cs.size; } @@ -507,7 +509,7 @@ static void virgl_write_fence(void *opaque, uint32_t fence) QTAILQ_REMOVE(&g->fenceq, cmd, next); g_free(cmd); g->inflight--; - if (virtio_gpu_stats_enabled(g->conf)) { + if (virtio_gpu_stats_enabled(g->parent_obj.conf)) { fprintf(stderr, "inflight: %3d (-)\r", g->inflight); } } @@ -524,7 +526,7 @@ virgl_create_context(void *opaque, int scanout_idx, qparams.major_ver = params->major_ver; qparams.minor_ver = params->minor_ver; - ctx = dpy_gl_ctx_create(g->scanout[scanout_idx].con, &qparams); + ctx = dpy_gl_ctx_create(g->parent_obj.scanout[scanout_idx].con, &qparams); return (virgl_renderer_gl_context)ctx; } @@ -533,7 +535,7 @@ static void virgl_destroy_context(void *opaque, virgl_renderer_gl_context ctx) VirtIOGPU *g = opaque; QEMUGLContext qctx = (QEMUGLContext)ctx; - dpy_gl_ctx_destroy(g->scanout[0].con, qctx); + dpy_gl_ctx_destroy(g->parent_obj.scanout[0].con, qctx); } static int virgl_make_context_current(void *opaque, int scanout_idx, @@ -542,7 +544,8 @@ static int virgl_make_context_current(void *opaque, int scanout_idx, VirtIOGPU *g = opaque; QEMUGLContext qctx = (QEMUGLContext)ctx; - return dpy_gl_ctx_make_current(g->scanout[scanout_idx].con, qctx); + return dpy_gl_ctx_make_current(g->parent_obj.scanout[scanout_idx].con, + qctx); } static struct virgl_renderer_callbacks virtio_gpu_3d_cbs = { @@ -594,11 +597,11 @@ void virtio_gpu_virgl_reset(VirtIOGPU *g) int i; /* virgl_renderer_reset() ??? */ - for (i = 0; i < g->conf.max_outputs; i++) { + for (i = 0; i < g->parent_obj.conf.max_outputs; i++) { if (i != 0) { - dpy_gfx_replace_surface(g->scanout[i].con, NULL); + dpy_gfx_replace_surface(g->parent_obj.scanout[i].con, NULL); } - dpy_gl_scanout_disable(g->scanout[i].con); + dpy_gl_scanout_disable(g->parent_obj.scanout[i].con); } } @@ -614,7 +617,7 @@ int virtio_gpu_virgl_init(VirtIOGPU *g) g->fence_poll = timer_new_ms(QEMU_CLOCK_VIRTUAL, virtio_gpu_fence_poll, g); - if (virtio_gpu_stats_enabled(g->conf)) { + if (virtio_gpu_stats_enabled(g->parent_obj.conf)) { g->print_stats = timer_new_ms(QEMU_CLOCK_VIRTUAL, virtio_gpu_print_stats, g); timer_mod(g->print_stats, qemu_clock_get_ms(QEMU_CLOCK_VIRTUAL) + 1000); diff --git a/hw/display/virtio-gpu-base.c b/hw/display/virtio-gpu-base.c new file mode 100644 index 0000000000..55e07995fe --- /dev/null +++ b/hw/display/virtio-gpu-base.c @@ -0,0 +1,268 @@ +/* + * Virtio GPU Device + * + * Copyright Red Hat, Inc. 2013-2014 + * + * Authors: + * Dave Airlie <airlied@redhat.com> + * Gerd Hoffmann <kraxel@redhat.com> + * + * This work is licensed under the terms of the GNU GPL, version 2 or later. + * See the COPYING file in the top-level directory. + */ + +#include "qemu/osdep.h" + +#include "hw/virtio/virtio-gpu.h" +#include "migration/blocker.h" +#include "qapi/error.h" +#include "qemu/error-report.h" +#include "trace.h" + +void +virtio_gpu_base_reset(VirtIOGPUBase *g) +{ + int i; + + g->enable = 0; + g->use_virgl_renderer = false; + + for (i = 0; i < g->conf.max_outputs; i++) { + g->scanout[i].resource_id = 0; + g->scanout[i].width = 0; + g->scanout[i].height = 0; + g->scanout[i].x = 0; + g->scanout[i].y = 0; + g->scanout[i].ds = NULL; + } +} + +void +virtio_gpu_base_fill_display_info(VirtIOGPUBase *g, + struct virtio_gpu_resp_display_info *dpy_info) +{ + int i; + + for (i = 0; i < g->conf.max_outputs; i++) { + if (g->enabled_output_bitmask & (1 << i)) { + dpy_info->pmodes[i].enabled = 1; + dpy_info->pmodes[i].r.width = cpu_to_le32(g->req_state[i].width); + dpy_info->pmodes[i].r.height = cpu_to_le32(g->req_state[i].height); + } + } +} + +static void virtio_gpu_invalidate_display(void *opaque) +{ +} + +static void virtio_gpu_update_display(void *opaque) +{ +} + +static void virtio_gpu_text_update(void *opaque, console_ch_t *chardata) +{ +} + +static void virtio_gpu_notify_event(VirtIOGPUBase *g, uint32_t event_type) +{ + g->virtio_config.events_read |= event_type; + virtio_notify_config(&g->parent_obj); +} + +static int virtio_gpu_ui_info(void *opaque, uint32_t idx, QemuUIInfo *info) +{ + VirtIOGPUBase *g = opaque; + + if (idx >= g->conf.max_outputs) { + return -1; + } + + g->req_state[idx].x = info->xoff; + g->req_state[idx].y = info->yoff; + g->req_state[idx].width = info->width; + g->req_state[idx].height = info->height; + + if (info->width && info->height) { + g->enabled_output_bitmask |= (1 << idx); + } else { + g->enabled_output_bitmask &= ~(1 << idx); + } + + /* send event to guest */ + virtio_gpu_notify_event(g, VIRTIO_GPU_EVENT_DISPLAY); + return 0; +} + +static void +virtio_gpu_gl_block(void *opaque, bool block) +{ + VirtIOGPUBase *g = opaque; + VirtIOGPUBaseClass *vgc = VIRTIO_GPU_BASE_GET_CLASS(g); + + if (block) { + g->renderer_blocked++; + } else { + g->renderer_blocked--; + } + assert(g->renderer_blocked >= 0); + + if (g->renderer_blocked == 0) { + vgc->gl_unblock(g); + } +} + +const GraphicHwOps virtio_gpu_ops = { + .invalidate = virtio_gpu_invalidate_display, + .gfx_update = virtio_gpu_update_display, + .text_update = virtio_gpu_text_update, + .ui_info = virtio_gpu_ui_info, + .gl_block = virtio_gpu_gl_block, +}; + +bool +virtio_gpu_base_device_realize(DeviceState *qdev, + VirtIOHandleOutput ctrl_cb, + VirtIOHandleOutput cursor_cb, + Error **errp) +{ + VirtIODevice *vdev = VIRTIO_DEVICE(qdev); + VirtIOGPUBase *g = VIRTIO_GPU_BASE(qdev); + Error *local_err = NULL; + int i; + + if (g->conf.max_outputs > VIRTIO_GPU_MAX_SCANOUTS) { + error_setg(errp, "invalid max_outputs > %d", VIRTIO_GPU_MAX_SCANOUTS); + return false; + } + + g->use_virgl_renderer = false; + if (virtio_gpu_virgl_enabled(g->conf)) { + error_setg(&g->migration_blocker, "virgl is not yet migratable"); + migrate_add_blocker(g->migration_blocker, &local_err); + if (local_err) { + error_propagate(errp, local_err); + error_free(g->migration_blocker); + return false; + } + } + + g->virtio_config.num_scanouts = cpu_to_le32(g->conf.max_outputs); + virtio_init(VIRTIO_DEVICE(g), "virtio-gpu", VIRTIO_ID_GPU, + sizeof(struct virtio_gpu_config)); + + if (virtio_gpu_virgl_enabled(g->conf)) { + /* use larger control queue in 3d mode */ + virtio_add_queue(vdev, 256, ctrl_cb); + virtio_add_queue(vdev, 16, cursor_cb); + } else { + virtio_add_queue(vdev, 64, ctrl_cb); + virtio_add_queue(vdev, 16, cursor_cb); + } + + g->enabled_output_bitmask = 1; + + g->req_state[0].width = g->conf.xres; + g->req_state[0].height = g->conf.yres; + + for (i = 0; i < g->conf.max_outputs; i++) { + g->scanout[i].con = + graphic_console_init(DEVICE(g), i, &virtio_gpu_ops, g); + if (i > 0) { + dpy_gfx_replace_surface(g->scanout[i].con, NULL); + } + } + + return true; +} + +static uint64_t +virtio_gpu_base_get_features(VirtIODevice *vdev, uint64_t features, + Error **errp) +{ + VirtIOGPUBase *g = VIRTIO_GPU_BASE(vdev); + + if (virtio_gpu_virgl_enabled(g->conf)) { + features |= (1 << VIRTIO_GPU_F_VIRGL); + } + if (virtio_gpu_edid_enabled(g->conf)) { + features |= (1 << VIRTIO_GPU_F_EDID); + } + + return features; +} + +static void +virtio_gpu_base_set_features(VirtIODevice *vdev, uint64_t features) +{ + static const uint32_t virgl = (1 << VIRTIO_GPU_F_VIRGL); + VirtIOGPUBase *g = VIRTIO_GPU_BASE(vdev); + + g->use_virgl_renderer = ((features & virgl) == virgl); + trace_virtio_gpu_features(g->use_virgl_renderer); +} + +static void +virtio_gpu_base_device_unrealize(DeviceState *qdev, Error **errp) +{ + VirtIOGPUBase *g = VIRTIO_GPU_BASE(qdev); + + if (g->migration_blocker) { + migrate_del_blocker(g->migration_blocker); + error_free(g->migration_blocker); + } +} + +static void +virtio_gpu_base_class_init(ObjectClass *klass, void *data) +{ + DeviceClass *dc = DEVICE_CLASS(klass); + VirtioDeviceClass *vdc = VIRTIO_DEVICE_CLASS(klass); + + vdc->unrealize = virtio_gpu_base_device_unrealize; + vdc->get_features = virtio_gpu_base_get_features; + vdc->set_features = virtio_gpu_base_set_features; + + set_bit(DEVICE_CATEGORY_DISPLAY, dc->categories); + dc->hotpluggable = false; +} + +static const TypeInfo virtio_gpu_base_info = { + .name = TYPE_VIRTIO_GPU_BASE, + .parent = TYPE_VIRTIO_DEVICE, + .instance_size = sizeof(VirtIOGPUBase), + .class_size = sizeof(VirtIOGPUBaseClass), + .class_init = virtio_gpu_base_class_init, + .abstract = true +}; + +static void +virtio_register_types(void) +{ + type_register_static(&virtio_gpu_base_info); +} + +type_init(virtio_register_types) + +QEMU_BUILD_BUG_ON(sizeof(struct virtio_gpu_ctrl_hdr) != 24); +QEMU_BUILD_BUG_ON(sizeof(struct virtio_gpu_update_cursor) != 56); +QEMU_BUILD_BUG_ON(sizeof(struct virtio_gpu_resource_unref) != 32); +QEMU_BUILD_BUG_ON(sizeof(struct virtio_gpu_resource_create_2d) != 40); +QEMU_BUILD_BUG_ON(sizeof(struct virtio_gpu_set_scanout) != 48); +QEMU_BUILD_BUG_ON(sizeof(struct virtio_gpu_resource_flush) != 48); +QEMU_BUILD_BUG_ON(sizeof(struct virtio_gpu_transfer_to_host_2d) != 56); +QEMU_BUILD_BUG_ON(sizeof(struct virtio_gpu_mem_entry) != 16); +QEMU_BUILD_BUG_ON(sizeof(struct virtio_gpu_resource_attach_backing) != 32); +QEMU_BUILD_BUG_ON(sizeof(struct virtio_gpu_resource_detach_backing) != 32); +QEMU_BUILD_BUG_ON(sizeof(struct virtio_gpu_resp_display_info) != 408); + +QEMU_BUILD_BUG_ON(sizeof(struct virtio_gpu_transfer_host_3d) != 72); +QEMU_BUILD_BUG_ON(sizeof(struct virtio_gpu_resource_create_3d) != 72); +QEMU_BUILD_BUG_ON(sizeof(struct virtio_gpu_ctx_create) != 96); +QEMU_BUILD_BUG_ON(sizeof(struct virtio_gpu_ctx_destroy) != 24); +QEMU_BUILD_BUG_ON(sizeof(struct virtio_gpu_ctx_resource) != 32); +QEMU_BUILD_BUG_ON(sizeof(struct virtio_gpu_cmd_submit) != 32); +QEMU_BUILD_BUG_ON(sizeof(struct virtio_gpu_get_capset_info) != 32); +QEMU_BUILD_BUG_ON(sizeof(struct virtio_gpu_resp_capset_info) != 40); +QEMU_BUILD_BUG_ON(sizeof(struct virtio_gpu_get_capset) != 32); +QEMU_BUILD_BUG_ON(sizeof(struct virtio_gpu_resp_capset) != 24); diff --git a/hw/display/virtio-gpu-pci.c b/hw/display/virtio-gpu-pci.c index 0bc4d9d424..206870cd4c 100644 --- a/hw/display/virtio-gpu-pci.c +++ b/hw/display/virtio-gpu-pci.c @@ -16,33 +16,18 @@ #include "hw/pci/pci.h" #include "hw/virtio/virtio.h" #include "hw/virtio/virtio-bus.h" -#include "hw/virtio/virtio-pci.h" -#include "hw/virtio/virtio-gpu.h" +#include "hw/virtio/virtio-gpu-pci.h" -typedef struct VirtIOGPUPCI VirtIOGPUPCI; - -/* - * virtio-gpu-pci: This extends VirtioPCIProxy. - */ -#define TYPE_VIRTIO_GPU_PCI "virtio-gpu-pci" -#define VIRTIO_GPU_PCI(obj) \ - OBJECT_CHECK(VirtIOGPUPCI, (obj), TYPE_VIRTIO_GPU_PCI) - -struct VirtIOGPUPCI { - VirtIOPCIProxy parent_obj; - VirtIOGPU vdev; -}; - -static Property virtio_gpu_pci_properties[] = { +static Property virtio_gpu_pci_base_properties[] = { DEFINE_VIRTIO_GPU_PCI_PROPERTIES(VirtIOPCIProxy), DEFINE_PROP_END_OF_LIST(), }; -static void virtio_gpu_pci_realize(VirtIOPCIProxy *vpci_dev, Error **errp) +static void virtio_gpu_pci_base_realize(VirtIOPCIProxy *vpci_dev, Error **errp) { - VirtIOGPUPCI *vgpu = VIRTIO_GPU_PCI(vpci_dev); - VirtIOGPU *g = &vgpu->vdev; - DeviceState *vdev = DEVICE(&vgpu->vdev); + VirtIOGPUPCIBase *vgpu = VIRTIO_GPU_PCI_BASE(vpci_dev); + VirtIOGPUBase *g = vgpu->vgpu; + DeviceState *vdev = DEVICE(g); int i; Error *local_error = NULL; @@ -64,36 +49,56 @@ static void virtio_gpu_pci_realize(VirtIOPCIProxy *vpci_dev, Error **errp) } } -static void virtio_gpu_pci_class_init(ObjectClass *klass, void *data) +static void virtio_gpu_pci_base_class_init(ObjectClass *klass, void *data) { DeviceClass *dc = DEVICE_CLASS(klass); VirtioPCIClass *k = VIRTIO_PCI_CLASS(klass); PCIDeviceClass *pcidev_k = PCI_DEVICE_CLASS(klass); set_bit(DEVICE_CATEGORY_DISPLAY, dc->categories); - dc->props = virtio_gpu_pci_properties; + dc->props = virtio_gpu_pci_base_properties; dc->hotpluggable = false; - k->realize = virtio_gpu_pci_realize; + k->realize = virtio_gpu_pci_base_realize; pcidev_k->class_id = PCI_CLASS_DISPLAY_OTHER; } +static const TypeInfo virtio_gpu_pci_base_info = { + .name = TYPE_VIRTIO_GPU_PCI_BASE, + .parent = TYPE_VIRTIO_PCI, + .instance_size = sizeof(VirtIOGPUPCIBase), + .class_init = virtio_gpu_pci_base_class_init, + .abstract = true +}; + +#define TYPE_VIRTIO_GPU_PCI "virtio-gpu-pci" +#define VIRTIO_GPU_PCI(obj) \ + OBJECT_CHECK(VirtIOGPUPCI, (obj), TYPE_VIRTIO_GPU_PCI) + +typedef struct VirtIOGPUPCI { + VirtIOGPUPCIBase parent_obj; + VirtIOGPU vdev; +} VirtIOGPUPCI; + static void virtio_gpu_initfn(Object *obj) { VirtIOGPUPCI *dev = VIRTIO_GPU_PCI(obj); virtio_instance_init_common(obj, &dev->vdev, sizeof(dev->vdev), TYPE_VIRTIO_GPU); + VIRTIO_GPU_PCI_BASE(obj)->vgpu = VIRTIO_GPU_BASE(&dev->vdev); } static const VirtioPCIDeviceTypeInfo virtio_gpu_pci_info = { .generic_name = TYPE_VIRTIO_GPU_PCI, + .parent = TYPE_VIRTIO_GPU_PCI_BASE, .instance_size = sizeof(VirtIOGPUPCI), .instance_init = virtio_gpu_initfn, - .class_init = virtio_gpu_pci_class_init, }; static void virtio_gpu_pci_register_types(void) { + type_register_static(&virtio_gpu_pci_base_info); virtio_pci_types_register(&virtio_gpu_pci_info); } + type_init(virtio_gpu_pci_register_types) diff --git a/hw/display/virtio-gpu.c b/hw/display/virtio-gpu.c index 372b31ef0a..4a49da5ecb 100644 --- a/hw/display/virtio-gpu.c +++ b/hw/display/virtio-gpu.c @@ -20,11 +20,13 @@ #include "sysemu/dma.h" #include "hw/virtio/virtio.h" #include "hw/virtio/virtio-gpu.h" +#include "hw/virtio/virtio-gpu-bswap.h" +#include "hw/virtio/virtio-gpu-pixman.h" #include "hw/virtio/virtio-bus.h" #include "hw/display/edid.h" -#include "migration/blocker.h" #include "qemu/log.h" #include "qapi/error.h" +#include "qemu/error-report.h" #define VIRTIO_GPU_VM_VERSION 1 @@ -34,53 +36,11 @@ virtio_gpu_find_resource(VirtIOGPU *g, uint32_t resource_id); static void virtio_gpu_cleanup_mapping(VirtIOGPU *g, struct virtio_gpu_simple_resource *res); -static void -virtio_gpu_ctrl_hdr_bswap(struct virtio_gpu_ctrl_hdr *hdr) -{ - le32_to_cpus(&hdr->type); - le32_to_cpus(&hdr->flags); - le64_to_cpus(&hdr->fence_id); - le32_to_cpus(&hdr->ctx_id); - le32_to_cpus(&hdr->padding); -} - -static void virtio_gpu_bswap_32(void *ptr, - size_t size) -{ -#ifdef HOST_WORDS_BIGENDIAN - - size_t i; - struct virtio_gpu_ctrl_hdr *hdr = (struct virtio_gpu_ctrl_hdr *) ptr; - - virtio_gpu_ctrl_hdr_bswap(hdr); - - i = sizeof(struct virtio_gpu_ctrl_hdr); - while (i < size) { - le32_to_cpus((uint32_t *)(ptr + i)); - i = i + sizeof(uint32_t); - } - -#endif -} - -static void -virtio_gpu_t2d_bswap(struct virtio_gpu_transfer_to_host_2d *t2d) -{ - virtio_gpu_ctrl_hdr_bswap(&t2d->hdr); - le32_to_cpus(&t2d->r.x); - le32_to_cpus(&t2d->r.y); - le32_to_cpus(&t2d->r.width); - le32_to_cpus(&t2d->r.height); - le64_to_cpus(&t2d->offset); - le32_to_cpus(&t2d->resource_id); - le32_to_cpus(&t2d->padding); -} - #ifdef CONFIG_VIRGL #include <virglrenderer.h> #define VIRGL(_g, _virgl, _simple, ...) \ do { \ - if (_g->use_virgl_renderer) { \ + if (_g->parent_obj.use_virgl_renderer) { \ _virgl(__VA_ARGS__); \ } else { \ _simple(__VA_ARGS__); \ @@ -148,10 +108,10 @@ static void update_cursor(VirtIOGPU *g, struct virtio_gpu_update_cursor *cursor) struct virtio_gpu_scanout *s; bool move = cursor->hdr.type == VIRTIO_GPU_CMD_MOVE_CURSOR; - if (cursor->pos.scanout_id >= g->conf.max_outputs) { + if (cursor->pos.scanout_id >= g->parent_obj.conf.max_outputs) { return; } - s = &g->scanout[cursor->pos.scanout_id]; + s = &g->parent_obj.scanout[cursor->pos.scanout_id]; trace_virtio_gpu_update_cursor(cursor->pos.scanout_id, cursor->pos.x, @@ -182,53 +142,6 @@ static void update_cursor(VirtIOGPU *g, struct virtio_gpu_update_cursor *cursor) cursor->resource_id ? 1 : 0); } -static void virtio_gpu_get_config(VirtIODevice *vdev, uint8_t *config) -{ - VirtIOGPU *g = VIRTIO_GPU(vdev); - memcpy(config, &g->virtio_config, sizeof(g->virtio_config)); -} - -static void virtio_gpu_set_config(VirtIODevice *vdev, const uint8_t *config) -{ - VirtIOGPU *g = VIRTIO_GPU(vdev); - struct virtio_gpu_config vgconfig; - - memcpy(&vgconfig, config, sizeof(g->virtio_config)); - - if (vgconfig.events_clear) { - g->virtio_config.events_read &= ~vgconfig.events_clear; - } -} - -static uint64_t virtio_gpu_get_features(VirtIODevice *vdev, uint64_t features, - Error **errp) -{ - VirtIOGPU *g = VIRTIO_GPU(vdev); - - if (virtio_gpu_virgl_enabled(g->conf)) { - features |= (1 << VIRTIO_GPU_F_VIRGL); - } - if (virtio_gpu_edid_enabled(g->conf)) { - features |= (1 << VIRTIO_GPU_F_EDID); - } - return features; -} - -static void virtio_gpu_set_features(VirtIODevice *vdev, uint64_t features) -{ - static const uint32_t virgl = (1 << VIRTIO_GPU_F_VIRGL); - VirtIOGPU *g = VIRTIO_GPU(vdev); - - g->use_virgl_renderer = ((features & virgl) == virgl); - trace_virtio_gpu_features(g->use_virgl_renderer); -} - -static void virtio_gpu_notify_event(VirtIOGPU *g, uint32_t event_type) -{ - g->virtio_config.events_read |= event_type; - virtio_notify_config(&g->parent_obj); -} - static struct virtio_gpu_simple_resource * virtio_gpu_find_resource(VirtIOGPU *g, uint32_t resource_id) { @@ -277,21 +190,6 @@ void virtio_gpu_ctrl_response_nodata(VirtIOGPU *g, virtio_gpu_ctrl_response(g, cmd, &resp, sizeof(resp)); } -static void -virtio_gpu_fill_display_info(VirtIOGPU *g, - struct virtio_gpu_resp_display_info *dpy_info) -{ - int i; - - for (i = 0; i < g->conf.max_outputs; i++) { - if (g->enabled_output_bitmask & (1 << i)) { - dpy_info->pmodes[i].enabled = 1; - dpy_info->pmodes[i].r.width = cpu_to_le32(g->req_state[i].width); - dpy_info->pmodes[i].r.height = cpu_to_le32(g->req_state[i].height); - } - } -} - void virtio_gpu_get_display_info(VirtIOGPU *g, struct virtio_gpu_ctrl_command *cmd) { @@ -300,7 +198,7 @@ void virtio_gpu_get_display_info(VirtIOGPU *g, trace_virtio_gpu_cmd_get_display_info(); memset(&display_info, 0, sizeof(display_info)); display_info.hdr.type = VIRTIO_GPU_RESP_OK_DISPLAY_INFO; - virtio_gpu_fill_display_info(g, &display_info); + virtio_gpu_base_fill_display_info(VIRTIO_GPU_BASE(g), &display_info); virtio_gpu_ctrl_response(g, cmd, &display_info.hdr, sizeof(display_info)); } @@ -309,9 +207,10 @@ static void virtio_gpu_generate_edid(VirtIOGPU *g, int scanout, struct virtio_gpu_resp_edid *edid) { + VirtIOGPUBase *b = VIRTIO_GPU_BASE(g); qemu_edid_info info = { - .prefx = g->req_state[scanout].width, - .prefy = g->req_state[scanout].height, + .prefx = b->req_state[scanout].width, + .prefy = b->req_state[scanout].height, }; edid->size = cpu_to_le32(sizeof(edid->edid)); @@ -323,11 +222,12 @@ void virtio_gpu_get_edid(VirtIOGPU *g, { struct virtio_gpu_resp_edid edid; struct virtio_gpu_cmd_get_edid get_edid; + VirtIOGPUBase *b = VIRTIO_GPU_BASE(g); VIRTIO_GPU_FILL_CMD(get_edid); virtio_gpu_bswap_32(&get_edid, sizeof(get_edid)); - if (get_edid.scanout >= g->conf.max_outputs) { + if (get_edid.scanout >= b->conf.max_outputs) { cmd->error = VIRTIO_GPU_RESP_ERR_INVALID_PARAMETER; return; } @@ -339,30 +239,6 @@ void virtio_gpu_get_edid(VirtIOGPU *g, virtio_gpu_ctrl_response(g, cmd, &edid.hdr, sizeof(edid)); } -static pixman_format_code_t get_pixman_format(uint32_t virtio_gpu_format) -{ - switch (virtio_gpu_format) { - case VIRTIO_GPU_FORMAT_B8G8R8X8_UNORM: - return PIXMAN_BE_b8g8r8x8; - case VIRTIO_GPU_FORMAT_B8G8R8A8_UNORM: - return PIXMAN_BE_b8g8r8a8; - case VIRTIO_GPU_FORMAT_X8R8G8B8_UNORM: - return PIXMAN_BE_x8r8g8b8; - case VIRTIO_GPU_FORMAT_A8R8G8B8_UNORM: - return PIXMAN_BE_a8r8g8b8; - case VIRTIO_GPU_FORMAT_R8G8B8X8_UNORM: - return PIXMAN_BE_r8g8b8x8; - case VIRTIO_GPU_FORMAT_R8G8B8A8_UNORM: - return PIXMAN_BE_r8g8b8a8; - case VIRTIO_GPU_FORMAT_X8B8G8R8_UNORM: - return PIXMAN_BE_x8b8g8r8; - case VIRTIO_GPU_FORMAT_A8B8G8R8_UNORM: - return PIXMAN_BE_a8b8g8r8; - default: - return 0; - } -} - static uint32_t calc_image_hostmem(pixman_format_code_t pformat, uint32_t width, uint32_t height) { @@ -409,7 +285,7 @@ static void virtio_gpu_resource_create_2d(VirtIOGPU *g, res->format = c2d.format; res->resource_id = c2d.resource_id; - pformat = get_pixman_format(c2d.format); + pformat = virtio_gpu_get_pixman_format(c2d.format); if (!pformat) { qemu_log_mask(LOG_GUEST_ERROR, "%s: host couldn't handle guest format %d\n", @@ -420,7 +296,7 @@ static void virtio_gpu_resource_create_2d(VirtIOGPU *g, } res->hostmem = calc_image_hostmem(pformat, c2d.width, c2d.height); - if (res->hostmem + g->hostmem < g->conf.max_hostmem) { + if (res->hostmem + g->hostmem < g->conf_max_hostmem) { res->image = pixman_image_create_bits(pformat, c2d.width, c2d.height, @@ -442,7 +318,7 @@ static void virtio_gpu_resource_create_2d(VirtIOGPU *g, static void virtio_gpu_disable_scanout(VirtIOGPU *g, int scanout_id) { - struct virtio_gpu_scanout *scanout = &g->scanout[scanout_id]; + struct virtio_gpu_scanout *scanout = &g->parent_obj.scanout[scanout_id]; struct virtio_gpu_simple_resource *res; DisplaySurface *ds = NULL; @@ -474,7 +350,7 @@ static void virtio_gpu_resource_destroy(VirtIOGPU *g, int i; if (res->scanout_bitmask) { - for (i = 0; i < g->conf.max_outputs; i++) { + for (i = 0; i < g->parent_obj.conf.max_outputs; i++) { if (res->scanout_bitmask & (1 << i)) { virtio_gpu_disable_scanout(g, i); } @@ -604,7 +480,7 @@ static void virtio_gpu_resource_flush(VirtIOGPU *g, pixman_region_init_rect(&flush_region, rf.r.x, rf.r.y, rf.r.width, rf.r.height); - for (i = 0; i < g->conf.max_outputs; i++) { + for (i = 0; i < g->parent_obj.conf.max_outputs; i++) { struct virtio_gpu_scanout *scanout; pixman_region16_t region, finalregion; pixman_box16_t *extents; @@ -612,7 +488,7 @@ static void virtio_gpu_resource_flush(VirtIOGPU *g, if (!(res->scanout_bitmask & (1 << i))) { continue; } - scanout = &g->scanout[i]; + scanout = &g->parent_obj.scanout[i]; pixman_region_init(&finalregion); pixman_region_init_rect(®ion, scanout->x, scanout->y, @@ -622,7 +498,7 @@ static void virtio_gpu_resource_flush(VirtIOGPU *g, pixman_region_translate(&finalregion, -scanout->x, -scanout->y); extents = pixman_region_extents(&finalregion); /* work out the area we need to update for each console */ - dpy_gfx_update(g->scanout[i].con, + dpy_gfx_update(g->parent_obj.scanout[i].con, extents->x1, extents->y1, extents->x2 - extents->x1, extents->y2 - extents->y1); @@ -653,14 +529,14 @@ static void virtio_gpu_set_scanout(VirtIOGPU *g, trace_virtio_gpu_cmd_set_scanout(ss.scanout_id, ss.resource_id, ss.r.width, ss.r.height, ss.r.x, ss.r.y); - if (ss.scanout_id >= g->conf.max_outputs) { + if (ss.scanout_id >= g->parent_obj.conf.max_outputs) { qemu_log_mask(LOG_GUEST_ERROR, "%s: illegal scanout id specified %d", __func__, ss.scanout_id); cmd->error = VIRTIO_GPU_RESP_ERR_INVALID_SCANOUT_ID; return; } - g->enable = 1; + g->parent_obj.enable = 1; if (ss.resource_id == 0) { virtio_gpu_disable_scanout(g, ss.scanout_id); return; @@ -691,7 +567,7 @@ static void virtio_gpu_set_scanout(VirtIOGPU *g, return; } - scanout = &g->scanout[ss.scanout_id]; + scanout = &g->parent_obj.scanout[ss.scanout_id]; format = pixman_image_get_format(res->image); bpp = DIV_ROUND_UP(PIXMAN_FORMAT_BPP(format), 8); @@ -714,7 +590,8 @@ static void virtio_gpu_set_scanout(VirtIOGPU *g, return; } pixman_image_unref(rect); - dpy_gfx_replace_surface(g->scanout[ss.scanout_id].con, scanout->ds); + dpy_gfx_replace_surface(g->parent_obj.scanout[ss.scanout_id].con, + scanout->ds); } ores = virtio_gpu_find_resource(g, scanout->resource_id); @@ -932,7 +809,7 @@ void virtio_gpu_process_cmdq(VirtIOGPU *g) while (!QTAILQ_EMPTY(&g->cmdq)) { cmd = QTAILQ_FIRST(&g->cmdq); - if (g->renderer_blocked) { + if (g->parent_obj.renderer_blocked) { break; } @@ -941,14 +818,14 @@ void virtio_gpu_process_cmdq(VirtIOGPU *g) g, cmd); QTAILQ_REMOVE(&g->cmdq, cmd, next); - if (virtio_gpu_stats_enabled(g->conf)) { + if (virtio_gpu_stats_enabled(g->parent_obj.conf)) { g->stats.requests++; } if (!cmd->finished) { QTAILQ_INSERT_TAIL(&g->fenceq, cmd, next); g->inflight++; - if (virtio_gpu_stats_enabled(g->conf)) { + if (virtio_gpu_stats_enabled(g->parent_obj.conf)) { if (g->stats.max_inflight < g->inflight) { g->stats.max_inflight = g->inflight; } @@ -960,6 +837,19 @@ void virtio_gpu_process_cmdq(VirtIOGPU *g) } } +static void virtio_gpu_gl_unblock(VirtIOGPUBase *b) +{ + VirtIOGPU *g = VIRTIO_GPU(b); + +#ifdef CONFIG_VIRGL + if (g->renderer_reset) { + g->renderer_reset = false; + virtio_gpu_virgl_reset(g); + } +#endif + virtio_gpu_process_cmdq(g); +} + static void virtio_gpu_handle_ctrl(VirtIODevice *vdev, VirtQueue *vq) { VirtIOGPU *g = VIRTIO_GPU(vdev); @@ -970,7 +860,7 @@ static void virtio_gpu_handle_ctrl(VirtIODevice *vdev, VirtQueue *vq) } #ifdef CONFIG_VIRGL - if (!g->renderer_inited && g->use_virgl_renderer) { + if (!g->renderer_inited && g->parent_obj.use_virgl_renderer) { virtio_gpu_virgl_init(g); g->renderer_inited = true; } @@ -988,7 +878,7 @@ static void virtio_gpu_handle_ctrl(VirtIODevice *vdev, VirtQueue *vq) virtio_gpu_process_cmdq(g); #ifdef CONFIG_VIRGL - if (g->use_virgl_renderer) { + if (g->parent_obj.use_virgl_renderer) { virtio_gpu_virgl_fence_poll(g); } #endif @@ -997,7 +887,7 @@ static void virtio_gpu_handle_ctrl(VirtIODevice *vdev, VirtQueue *vq) static void virtio_gpu_ctrl_bh(void *opaque) { VirtIOGPU *g = opaque; - virtio_gpu_handle_ctrl(&g->parent_obj, g->ctrl_vq); + virtio_gpu_handle_ctrl(&g->parent_obj.parent_obj, g->ctrl_vq); } static void virtio_gpu_handle_cursor(VirtIODevice *vdev, VirtQueue *vq) @@ -1035,75 +925,9 @@ static void virtio_gpu_handle_cursor(VirtIODevice *vdev, VirtQueue *vq) static void virtio_gpu_cursor_bh(void *opaque) { VirtIOGPU *g = opaque; - virtio_gpu_handle_cursor(&g->parent_obj, g->cursor_vq); + virtio_gpu_handle_cursor(&g->parent_obj.parent_obj, g->cursor_vq); } -static void virtio_gpu_invalidate_display(void *opaque) -{ -} - -static void virtio_gpu_update_display(void *opaque) -{ -} - -static void virtio_gpu_text_update(void *opaque, console_ch_t *chardata) -{ -} - -static int virtio_gpu_ui_info(void *opaque, uint32_t idx, QemuUIInfo *info) -{ - VirtIOGPU *g = opaque; - - if (idx >= g->conf.max_outputs) { - return -1; - } - - g->req_state[idx].x = info->xoff; - g->req_state[idx].y = info->yoff; - g->req_state[idx].width = info->width; - g->req_state[idx].height = info->height; - - if (info->width && info->height) { - g->enabled_output_bitmask |= (1 << idx); - } else { - g->enabled_output_bitmask &= ~(1 << idx); - } - - /* send event to guest */ - virtio_gpu_notify_event(g, VIRTIO_GPU_EVENT_DISPLAY); - return 0; -} - -static void virtio_gpu_gl_block(void *opaque, bool block) -{ - VirtIOGPU *g = opaque; - - if (block) { - g->renderer_blocked++; - } else { - g->renderer_blocked--; - } - assert(g->renderer_blocked >= 0); - - if (g->renderer_blocked == 0) { -#ifdef CONFIG_VIRGL - if (g->renderer_reset) { - g->renderer_reset = false; - virtio_gpu_virgl_reset(g); - } -#endif - virtio_gpu_process_cmdq(g); - } -} - -const GraphicHwOps virtio_gpu_ops = { - .invalidate = virtio_gpu_invalidate_display, - .gfx_update = virtio_gpu_update_display, - .text_update = virtio_gpu_text_update, - .ui_info = virtio_gpu_ui_info, - .gl_block = virtio_gpu_gl_block, -}; - static const VMStateDescription vmstate_virtio_gpu_scanout = { .name = "virtio-gpu-one-scanout", .version_id = 1, @@ -1126,10 +950,11 @@ static const VMStateDescription vmstate_virtio_gpu_scanouts = { .name = "virtio-gpu-scanouts", .version_id = 1, .fields = (VMStateField[]) { - VMSTATE_INT32(enable, struct VirtIOGPU), - VMSTATE_UINT32_EQUAL(conf.max_outputs, struct VirtIOGPU, NULL), - VMSTATE_STRUCT_VARRAY_UINT32(scanout, struct VirtIOGPU, - conf.max_outputs, 1, + VMSTATE_INT32(parent_obj.enable, struct VirtIOGPU), + VMSTATE_UINT32_EQUAL(parent_obj.conf.max_outputs, + struct VirtIOGPU, NULL), + VMSTATE_STRUCT_VARRAY_UINT32(parent_obj.scanout, struct VirtIOGPU, + parent_obj.conf.max_outputs, 1, vmstate_virtio_gpu_scanout, struct virtio_gpu_scanout), VMSTATE_END_OF_LIST() @@ -1185,7 +1010,7 @@ static int virtio_gpu_load(QEMUFile *f, void *opaque, size_t size, res->iov_cnt = qemu_get_be32(f); /* allocate */ - pformat = get_pixman_format(res->format); + pformat = virtio_gpu_get_pixman_format(res->format); if (!pformat) { g_free(res); return -EINVAL; @@ -1244,8 +1069,8 @@ static int virtio_gpu_load(QEMUFile *f, void *opaque, size_t size, /* load & apply scanout state */ vmstate_load_state(f, &vmstate_virtio_gpu_scanouts, g, 1); - for (i = 0; i < g->conf.max_outputs; i++) { - scanout = &g->scanout[i]; + for (i = 0; i < g->parent_obj.conf.max_outputs; i++) { + scanout = &g->parent_obj.scanout[i]; if (!scanout->resource_id) { continue; } @@ -1274,84 +1099,35 @@ static void virtio_gpu_device_realize(DeviceState *qdev, Error **errp) VirtIODevice *vdev = VIRTIO_DEVICE(qdev); VirtIOGPU *g = VIRTIO_GPU(qdev); bool have_virgl; - Error *local_err = NULL; - int i; - - if (g->conf.max_outputs > VIRTIO_GPU_MAX_SCANOUTS) { - error_setg(errp, "invalid max_outputs > %d", VIRTIO_GPU_MAX_SCANOUTS); - return; - } - g->use_virgl_renderer = false; #if !defined(CONFIG_VIRGL) || defined(HOST_WORDS_BIGENDIAN) have_virgl = false; #else have_virgl = display_opengl; #endif if (!have_virgl) { - g->conf.flags &= ~(1 << VIRTIO_GPU_FLAG_VIRGL_ENABLED); - } - - if (virtio_gpu_virgl_enabled(g->conf)) { - error_setg(&g->migration_blocker, "virgl is not yet migratable"); - migrate_add_blocker(g->migration_blocker, &local_err); - if (local_err) { - error_propagate(errp, local_err); - error_free(g->migration_blocker); - return; - } - } - - g->virtio_config.num_scanouts = cpu_to_le32(g->conf.max_outputs); - virtio_init(VIRTIO_DEVICE(g), "virtio-gpu", VIRTIO_ID_GPU, - sizeof(struct virtio_gpu_config)); - - g->req_state[0].width = g->conf.xres; - g->req_state[0].height = g->conf.yres; - - if (virtio_gpu_virgl_enabled(g->conf)) { - /* use larger control queue in 3d mode */ - g->ctrl_vq = virtio_add_queue(vdev, 256, virtio_gpu_handle_ctrl_cb); - g->cursor_vq = virtio_add_queue(vdev, 16, virtio_gpu_handle_cursor_cb); - + g->parent_obj.conf.flags &= ~(1 << VIRTIO_GPU_FLAG_VIRGL_ENABLED); + } else { #if defined(CONFIG_VIRGL) - g->virtio_config.num_capsets = virtio_gpu_virgl_get_num_capsets(g); -#else - g->virtio_config.num_capsets = 0; + VIRTIO_GPU_BASE(g)->virtio_config.num_capsets = + virtio_gpu_virgl_get_num_capsets(g); #endif - } else { - g->ctrl_vq = virtio_add_queue(vdev, 64, virtio_gpu_handle_ctrl_cb); - g->cursor_vq = virtio_add_queue(vdev, 16, virtio_gpu_handle_cursor_cb); } + if (!virtio_gpu_base_device_realize(qdev, + virtio_gpu_handle_ctrl_cb, + virtio_gpu_handle_cursor_cb, + errp)) { + return; + } + + g->ctrl_vq = virtio_get_queue(vdev, 0); + g->cursor_vq = virtio_get_queue(vdev, 1); g->ctrl_bh = qemu_bh_new(virtio_gpu_ctrl_bh, g); g->cursor_bh = qemu_bh_new(virtio_gpu_cursor_bh, g); QTAILQ_INIT(&g->reslist); QTAILQ_INIT(&g->cmdq); QTAILQ_INIT(&g->fenceq); - - g->enabled_output_bitmask = 1; - - for (i = 0; i < g->conf.max_outputs; i++) { - g->scanout[i].con = - graphic_console_init(DEVICE(g), i, &virtio_gpu_ops, g); - if (i > 0) { - dpy_gfx_replace_surface(g->scanout[i].con, NULL); - } - } -} - -static void virtio_gpu_device_unrealize(DeviceState *qdev, Error **errp) -{ - VirtIOGPU *g = VIRTIO_GPU(qdev); - if (g->migration_blocker) { - migrate_del_blocker(g->migration_blocker); - error_free(g->migration_blocker); - } -} - -static void virtio_gpu_instance_init(Object *obj) -{ } static void virtio_gpu_reset(VirtIODevice *vdev) @@ -1359,21 +1135,16 @@ static void virtio_gpu_reset(VirtIODevice *vdev) VirtIOGPU *g = VIRTIO_GPU(vdev); struct virtio_gpu_simple_resource *res, *tmp; struct virtio_gpu_ctrl_command *cmd; - int i; - g->enable = 0; +#ifdef CONFIG_VIRGL + if (g->parent_obj.use_virgl_renderer) { + virtio_gpu_virgl_reset(g); + } +#endif QTAILQ_FOREACH_SAFE(res, &g->reslist, next, tmp) { virtio_gpu_resource_destroy(g, res); } - for (i = 0; i < g->conf.max_outputs; i++) { - g->scanout[i].resource_id = 0; - g->scanout[i].width = 0; - g->scanout[i].height = 0; - g->scanout[i].x = 0; - g->scanout[i].y = 0; - g->scanout[i].ds = NULL; - } while (!QTAILQ_EMPTY(&g->cmdq)) { cmd = QTAILQ_FIRST(&g->cmdq); @@ -1389,15 +1160,37 @@ static void virtio_gpu_reset(VirtIODevice *vdev) } #ifdef CONFIG_VIRGL - if (g->use_virgl_renderer) { - if (g->renderer_blocked) { + if (g->parent_obj.use_virgl_renderer) { + if (g->parent_obj.renderer_blocked) { g->renderer_reset = true; } else { virtio_gpu_virgl_reset(g); } - g->use_virgl_renderer = 0; + g->parent_obj.use_virgl_renderer = false; } #endif + + virtio_gpu_base_reset(VIRTIO_GPU_BASE(vdev)); +} + +static void +virtio_gpu_get_config(VirtIODevice *vdev, uint8_t *config) +{ + VirtIOGPUBase *g = VIRTIO_GPU_BASE(vdev); + + memcpy(config, &g->virtio_config, sizeof(g->virtio_config)); +} + +static void +virtio_gpu_set_config(VirtIODevice *vdev, const uint8_t *config) +{ + VirtIOGPUBase *g = VIRTIO_GPU_BASE(vdev); + const struct virtio_gpu_config *vgconfig = + (const struct virtio_gpu_config *)config; + + if (vgconfig->events_clear) { + g->virtio_config.events_read &= ~vgconfig->events_clear; + } } /* @@ -1428,18 +1221,15 @@ static const VMStateDescription vmstate_virtio_gpu = { }; static Property virtio_gpu_properties[] = { - DEFINE_PROP_UINT32("max_outputs", VirtIOGPU, conf.max_outputs, 1), - DEFINE_PROP_SIZE("max_hostmem", VirtIOGPU, conf.max_hostmem, 256 * MiB), + VIRTIO_GPU_BASE_PROPERTIES(VirtIOGPU, parent_obj.conf), + DEFINE_PROP_SIZE("max_hostmem", VirtIOGPU, conf_max_hostmem, + 256 * MiB), #ifdef CONFIG_VIRGL - DEFINE_PROP_BIT("virgl", VirtIOGPU, conf.flags, + DEFINE_PROP_BIT("virgl", VirtIOGPU, parent_obj.conf.flags, VIRTIO_GPU_FLAG_VIRGL_ENABLED, true), - DEFINE_PROP_BIT("stats", VirtIOGPU, conf.flags, + DEFINE_PROP_BIT("stats", VirtIOGPU, parent_obj.conf.flags, VIRTIO_GPU_FLAG_STATS_ENABLED, false), #endif - DEFINE_PROP_BIT("edid", VirtIOGPU, conf.flags, - VIRTIO_GPU_FLAG_EDID_ENABLED, false), - DEFINE_PROP_UINT32("xres", VirtIOGPU, conf.xres, 1024), - DEFINE_PROP_UINT32("yres", VirtIOGPU, conf.yres, 768), DEFINE_PROP_END_OF_LIST(), }; @@ -1447,27 +1237,22 @@ static void virtio_gpu_class_init(ObjectClass *klass, void *data) { DeviceClass *dc = DEVICE_CLASS(klass); VirtioDeviceClass *vdc = VIRTIO_DEVICE_CLASS(klass); + VirtIOGPUBaseClass *vgc = VIRTIO_GPU_BASE_CLASS(klass); + vgc->gl_unblock = virtio_gpu_gl_unblock; vdc->realize = virtio_gpu_device_realize; - vdc->unrealize = virtio_gpu_device_unrealize; + vdc->reset = virtio_gpu_reset; vdc->get_config = virtio_gpu_get_config; vdc->set_config = virtio_gpu_set_config; - vdc->get_features = virtio_gpu_get_features; - vdc->set_features = virtio_gpu_set_features; - vdc->reset = virtio_gpu_reset; - - set_bit(DEVICE_CATEGORY_DISPLAY, dc->categories); - dc->props = virtio_gpu_properties; dc->vmsd = &vmstate_virtio_gpu; - dc->hotpluggable = false; + dc->props = virtio_gpu_properties; } static const TypeInfo virtio_gpu_info = { .name = TYPE_VIRTIO_GPU, - .parent = TYPE_VIRTIO_DEVICE, + .parent = TYPE_VIRTIO_GPU_BASE, .instance_size = sizeof(VirtIOGPU), - .instance_init = virtio_gpu_instance_init, .class_init = virtio_gpu_class_init, }; @@ -1477,26 +1262,3 @@ static void virtio_register_types(void) } type_init(virtio_register_types) - -QEMU_BUILD_BUG_ON(sizeof(struct virtio_gpu_ctrl_hdr) != 24); -QEMU_BUILD_BUG_ON(sizeof(struct virtio_gpu_update_cursor) != 56); -QEMU_BUILD_BUG_ON(sizeof(struct virtio_gpu_resource_unref) != 32); -QEMU_BUILD_BUG_ON(sizeof(struct virtio_gpu_resource_create_2d) != 40); -QEMU_BUILD_BUG_ON(sizeof(struct virtio_gpu_set_scanout) != 48); -QEMU_BUILD_BUG_ON(sizeof(struct virtio_gpu_resource_flush) != 48); -QEMU_BUILD_BUG_ON(sizeof(struct virtio_gpu_transfer_to_host_2d) != 56); -QEMU_BUILD_BUG_ON(sizeof(struct virtio_gpu_mem_entry) != 16); -QEMU_BUILD_BUG_ON(sizeof(struct virtio_gpu_resource_attach_backing) != 32); -QEMU_BUILD_BUG_ON(sizeof(struct virtio_gpu_resource_detach_backing) != 32); -QEMU_BUILD_BUG_ON(sizeof(struct virtio_gpu_resp_display_info) != 408); - -QEMU_BUILD_BUG_ON(sizeof(struct virtio_gpu_transfer_host_3d) != 72); -QEMU_BUILD_BUG_ON(sizeof(struct virtio_gpu_resource_create_3d) != 72); -QEMU_BUILD_BUG_ON(sizeof(struct virtio_gpu_ctx_create) != 96); -QEMU_BUILD_BUG_ON(sizeof(struct virtio_gpu_ctx_destroy) != 24); -QEMU_BUILD_BUG_ON(sizeof(struct virtio_gpu_ctx_resource) != 32); -QEMU_BUILD_BUG_ON(sizeof(struct virtio_gpu_cmd_submit) != 32); -QEMU_BUILD_BUG_ON(sizeof(struct virtio_gpu_get_capset_info) != 32); -QEMU_BUILD_BUG_ON(sizeof(struct virtio_gpu_resp_capset_info) != 40); -QEMU_BUILD_BUG_ON(sizeof(struct virtio_gpu_get_capset) != 32); -QEMU_BUILD_BUG_ON(sizeof(struct virtio_gpu_resp_capset) != 24); diff --git a/hw/display/virtio-vga.c b/hw/display/virtio-vga.c index 5d57bf5b0c..67e34935c2 100644 --- a/hw/display/virtio-vga.c +++ b/hw/display/virtio-vga.c @@ -1,63 +1,42 @@ #include "qemu/osdep.h" #include "hw/hw.h" #include "hw/pci/pci.h" -#include "vga_int.h" -#include "hw/virtio/virtio-pci.h" #include "hw/virtio/virtio-gpu.h" #include "qapi/error.h" +#include "virtio-vga.h" -/* - * virtio-vga: This extends VirtioPCIProxy. - */ -#define TYPE_VIRTIO_VGA "virtio-vga" -#define VIRTIO_VGA(obj) \ - OBJECT_CHECK(VirtIOVGA, (obj), TYPE_VIRTIO_VGA) -#define VIRTIO_VGA_GET_CLASS(obj) \ - OBJECT_GET_CLASS(VirtIOVGAClass, obj, TYPE_VIRTIO_VGA) -#define VIRTIO_VGA_CLASS(klass) \ - OBJECT_CLASS_CHECK(VirtIOVGAClass, klass, TYPE_VIRTIO_VGA) - -typedef struct VirtIOVGA { - VirtIOPCIProxy parent_obj; - VirtIOGPU vdev; - VGACommonState vga; - MemoryRegion vga_mrs[3]; -} VirtIOVGA; - -typedef struct VirtIOVGAClass { - VirtioPCIClass parent_class; - DeviceReset parent_reset; -} VirtIOVGAClass; - -static void virtio_vga_invalidate_display(void *opaque) +static void virtio_vga_base_invalidate_display(void *opaque) { - VirtIOVGA *vvga = opaque; + VirtIOVGABase *vvga = opaque; + VirtIOGPUBase *g = vvga->vgpu; - if (vvga->vdev.enable) { - virtio_gpu_ops.invalidate(&vvga->vdev); + if (g->enable) { + virtio_gpu_ops.invalidate(g); } else { vvga->vga.hw_ops->invalidate(&vvga->vga); } } -static void virtio_vga_update_display(void *opaque) +static void virtio_vga_base_update_display(void *opaque) { - VirtIOVGA *vvga = opaque; + VirtIOVGABase *vvga = opaque; + VirtIOGPUBase *g = vvga->vgpu; - if (vvga->vdev.enable) { - virtio_gpu_ops.gfx_update(&vvga->vdev); + if (g->enable) { + virtio_gpu_ops.gfx_update(g); } else { vvga->vga.hw_ops->gfx_update(&vvga->vga); } } -static void virtio_vga_text_update(void *opaque, console_ch_t *chardata) +static void virtio_vga_base_text_update(void *opaque, console_ch_t *chardata) { - VirtIOVGA *vvga = opaque; + VirtIOVGABase *vvga = opaque; + VirtIOGPUBase *g = vvga->vgpu; - if (vvga->vdev.enable) { + if (g->enable) { if (virtio_gpu_ops.text_update) { - virtio_gpu_ops.text_update(&vvga->vdev, chardata); + virtio_gpu_ops.text_update(g, chardata); } } else { if (vvga->vga.hw_ops->text_update) { @@ -66,49 +45,52 @@ static void virtio_vga_text_update(void *opaque, console_ch_t *chardata) } } -static int virtio_vga_ui_info(void *opaque, uint32_t idx, QemuUIInfo *info) +static int virtio_vga_base_ui_info(void *opaque, uint32_t idx, QemuUIInfo *info) { - VirtIOVGA *vvga = opaque; + VirtIOVGABase *vvga = opaque; + VirtIOGPUBase *g = vvga->vgpu; if (virtio_gpu_ops.ui_info) { - return virtio_gpu_ops.ui_info(&vvga->vdev, idx, info); + return virtio_gpu_ops.ui_info(g, idx, info); } return -1; } -static void virtio_vga_gl_block(void *opaque, bool block) +static void virtio_vga_base_gl_block(void *opaque, bool block) { - VirtIOVGA *vvga = opaque; + VirtIOVGABase *vvga = opaque; + VirtIOGPUBase *g = vvga->vgpu; if (virtio_gpu_ops.gl_block) { - virtio_gpu_ops.gl_block(&vvga->vdev, block); + virtio_gpu_ops.gl_block(g, block); } } -static const GraphicHwOps virtio_vga_ops = { - .invalidate = virtio_vga_invalidate_display, - .gfx_update = virtio_vga_update_display, - .text_update = virtio_vga_text_update, - .ui_info = virtio_vga_ui_info, - .gl_block = virtio_vga_gl_block, +static const GraphicHwOps virtio_vga_base_ops = { + .invalidate = virtio_vga_base_invalidate_display, + .gfx_update = virtio_vga_base_update_display, + .text_update = virtio_vga_base_text_update, + .ui_info = virtio_vga_base_ui_info, + .gl_block = virtio_vga_base_gl_block, }; -static const VMStateDescription vmstate_virtio_vga = { +static const VMStateDescription vmstate_virtio_vga_base = { .name = "virtio-vga", .version_id = 2, .minimum_version_id = 2, .fields = (VMStateField[]) { /* no pci stuff here, saving the virtio device will handle that */ - VMSTATE_STRUCT(vga, VirtIOVGA, 0, vmstate_vga_common, VGACommonState), + VMSTATE_STRUCT(vga, VirtIOVGABase, 0, + vmstate_vga_common, VGACommonState), VMSTATE_END_OF_LIST() } }; /* VGA device wrapper around PCI device around virtio GPU */ -static void virtio_vga_realize(VirtIOPCIProxy *vpci_dev, Error **errp) +static void virtio_vga_base_realize(VirtIOPCIProxy *vpci_dev, Error **errp) { - VirtIOVGA *vvga = VIRTIO_VGA(vpci_dev); - VirtIOGPU *g = &vvga->vdev; + VirtIOVGABase *vvga = VIRTIO_VGA_BASE(vpci_dev); + VirtIOGPUBase *g = vvga->vgpu; VGACommonState *vga = &vvga->vga; Error *err = NULL; uint32_t offset; @@ -168,7 +150,7 @@ static void virtio_vga_realize(VirtIOPCIProxy *vpci_dev, Error **errp) vvga->vga_mrs, true, false); vga->con = g->scanout[0].con; - graphic_console_set_hwops(vga->con, &virtio_vga_ops, vvga); + graphic_console_set_hwops(vga->con, &virtio_vga_base_ops, vvga); for (i = 0; i < g->conf.max_outputs; i++) { object_property_set_link(OBJECT(g->scanout[i].con), @@ -177,10 +159,10 @@ static void virtio_vga_realize(VirtIOPCIProxy *vpci_dev, Error **errp) } } -static void virtio_vga_reset(DeviceState *dev) +static void virtio_vga_base_reset(DeviceState *dev) { - VirtIOVGAClass *klass = VIRTIO_VGA_GET_CLASS(dev); - VirtIOVGA *vvga = VIRTIO_VGA(dev); + VirtIOVGABaseClass *klass = VIRTIO_VGA_BASE_GET_CLASS(dev); + VirtIOVGABase *vvga = VIRTIO_VGA_BASE(dev); /* reset virtio-gpu */ klass->parent_reset(dev); @@ -190,48 +172,70 @@ static void virtio_vga_reset(DeviceState *dev) vga_dirty_log_start(&vvga->vga); } -static Property virtio_vga_properties[] = { +static Property virtio_vga_base_properties[] = { DEFINE_VIRTIO_GPU_PCI_PROPERTIES(VirtIOPCIProxy), DEFINE_PROP_END_OF_LIST(), }; -static void virtio_vga_class_init(ObjectClass *klass, void *data) +static void virtio_vga_base_class_init(ObjectClass *klass, void *data) { DeviceClass *dc = DEVICE_CLASS(klass); VirtioPCIClass *k = VIRTIO_PCI_CLASS(klass); - VirtIOVGAClass *v = VIRTIO_VGA_CLASS(klass); + VirtIOVGABaseClass *v = VIRTIO_VGA_BASE_CLASS(klass); PCIDeviceClass *pcidev_k = PCI_DEVICE_CLASS(klass); set_bit(DEVICE_CATEGORY_DISPLAY, dc->categories); - dc->props = virtio_vga_properties; - dc->vmsd = &vmstate_virtio_vga; + dc->props = virtio_vga_base_properties; + dc->vmsd = &vmstate_virtio_vga_base; dc->hotpluggable = false; - device_class_set_parent_reset(dc, virtio_vga_reset, + device_class_set_parent_reset(dc, virtio_vga_base_reset, &v->parent_reset); - k->realize = virtio_vga_realize; + k->realize = virtio_vga_base_realize; pcidev_k->romfile = "vgabios-virtio.bin"; pcidev_k->class_id = PCI_CLASS_DISPLAY_VGA; } +static TypeInfo virtio_vga_base_info = { + .name = TYPE_VIRTIO_VGA_BASE, + .parent = TYPE_VIRTIO_PCI, + .instance_size = sizeof(struct VirtIOVGABase), + .class_size = sizeof(struct VirtIOVGABaseClass), + .class_init = virtio_vga_base_class_init, + .abstract = true, +}; + +#define TYPE_VIRTIO_VGA "virtio-vga" + +#define VIRTIO_VGA(obj) \ + OBJECT_CHECK(VirtIOVGA, (obj), TYPE_VIRTIO_VGA) + +typedef struct VirtIOVGA { + VirtIOVGABase parent_obj; + + VirtIOGPU vdev; +} VirtIOVGA; + static void virtio_vga_inst_initfn(Object *obj) { VirtIOVGA *dev = VIRTIO_VGA(obj); virtio_instance_init_common(obj, &dev->vdev, sizeof(dev->vdev), TYPE_VIRTIO_GPU); + VIRTIO_VGA_BASE(dev)->vgpu = VIRTIO_GPU_BASE(&dev->vdev); } + static VirtioPCIDeviceTypeInfo virtio_vga_info = { .generic_name = TYPE_VIRTIO_VGA, + .parent = TYPE_VIRTIO_VGA_BASE, .instance_size = sizeof(struct VirtIOVGA), .instance_init = virtio_vga_inst_initfn, - .class_size = sizeof(struct VirtIOVGAClass), - .class_init = virtio_vga_class_init, }; static void virtio_vga_register_types(void) { + type_register_static(&virtio_vga_base_info); virtio_pci_types_register(&virtio_vga_info); } diff --git a/hw/display/virtio-vga.h b/hw/display/virtio-vga.h new file mode 100644 index 0000000000..c10bf390aa --- /dev/null +++ b/hw/display/virtio-vga.h @@ -0,0 +1,32 @@ +#ifndef VIRTIO_VGA_H_ +#define VIRTIO_VGA_H_ + +#include "hw/virtio/virtio-gpu-pci.h" +#include "vga_int.h" + +/* + * virtio-vga-base: This extends VirtioPCIProxy. + */ +#define TYPE_VIRTIO_VGA_BASE "virtio-vga-base" +#define VIRTIO_VGA_BASE(obj) \ + OBJECT_CHECK(VirtIOVGABase, (obj), TYPE_VIRTIO_VGA_BASE) +#define VIRTIO_VGA_BASE_GET_CLASS(obj) \ + OBJECT_GET_CLASS(VirtIOVGABaseClass, obj, TYPE_VIRTIO_VGA_BASE) +#define VIRTIO_VGA_BASE_CLASS(klass) \ + OBJECT_CLASS_CHECK(VirtIOVGABaseClass, klass, TYPE_VIRTIO_VGA_BASE) + +typedef struct VirtIOVGABase { + VirtIOPCIProxy parent_obj; + + VirtIOGPUBase *vgpu; + VGACommonState vga; + MemoryRegion vga_mrs[3]; +} VirtIOVGABase; + +typedef struct VirtIOVGABaseClass { + VirtioPCIClass parent_class; + + DeviceReset parent_reset; +} VirtIOVGABaseClass; + +#endif /* VIRTIO_VGA_H_ */ diff --git a/hw/i386/acpi-build.c b/hw/i386/acpi-build.c index 0d78d73894..85dc1640bc 100644 --- a/hw/i386/acpi-build.c +++ b/hw/i386/acpi-build.c @@ -2405,22 +2405,6 @@ build_srat(GArray *table_data, BIOSLinker *linker, MachineState *machine) table_data->len - srat_start, 1, NULL, NULL); } -static void -build_mcfg_q35(GArray *table_data, BIOSLinker *linker, AcpiMcfgInfo *info) -{ - AcpiTableMcfg *mcfg; - int len = sizeof(*mcfg) + 1 * sizeof(mcfg->allocation[0]); - - mcfg = acpi_data_push(table_data, len); - mcfg->allocation[0].address = cpu_to_le64(info->base); - /* Only a single allocation so no need to play with segments */ - mcfg->allocation[0].pci_segment = cpu_to_le16(0); - mcfg->allocation[0].start_bus_number = 0; - mcfg->allocation[0].end_bus_number = PCIE_MMCFG_BUS(info->size - 1); - - build_header(linker, table_data, (void *)mcfg, "MCFG", len, 1, NULL, NULL); -} - /* * VT-d spec 8.1 DMA Remapping Reporting Structure * (version Oct. 2014 or later) @@ -2690,7 +2674,7 @@ void acpi_build(AcpiBuildTables *tables, MachineState *machine) } if (acpi_get_mcfg(&mcfg)) { acpi_add_table(table_offsets, tables_blob); - build_mcfg_q35(tables_blob, tables->linker, &mcfg); + build_mcfg(tables_blob, tables->linker, &mcfg); } if (x86_iommu_get_default()) { IommuType IOMMUType = x86_iommu_get_type(); diff --git a/hw/i386/pc.c b/hw/i386/pc.c index 2632b73f80..edc240bcbf 100644 --- a/hw/i386/pc.c +++ b/hw/i386/pc.c @@ -110,6 +110,9 @@ struct hpet_fw_config hpet_cfg = {.count = UINT8_MAX}; /* Physical Address of PVH entry point read from kernel ELF NOTE */ static size_t pvh_start_addr; +GlobalProperty pc_compat_4_0_1[] = {}; +const size_t pc_compat_4_0_1_len = G_N_ELEMENTS(pc_compat_4_0_1); + GlobalProperty pc_compat_4_0[] = {}; const size_t pc_compat_4_0_len = G_N_ELEMENTS(pc_compat_4_0); diff --git a/hw/i386/pc_q35.c b/hw/i386/pc_q35.c index 37dd350511..dcddc64662 100644 --- a/hw/i386/pc_q35.c +++ b/hw/i386/pc_q35.c @@ -357,7 +357,7 @@ static void pc_q35_machine_options(MachineClass *m) m->units_per_default_bus = 1; m->default_machine_opts = "firmware=bios-256k.bin"; m->default_display = "std"; - m->default_kernel_irqchip_split = true; + m->default_kernel_irqchip_split = false; m->no_floppy = 1; machine_class_allow_dynamic_sysbus_dev(m, TYPE_AMD_IOMMU_DEVICE); machine_class_allow_dynamic_sysbus_dev(m, TYPE_INTEL_IOMMU_DEVICE); @@ -374,10 +374,22 @@ static void pc_q35_4_1_machine_options(MachineClass *m) DEFINE_Q35_MACHINE(v4_1, "pc-q35-4.1", NULL, pc_q35_4_1_machine_options); -static void pc_q35_4_0_machine_options(MachineClass *m) +static void pc_q35_4_0_1_machine_options(MachineClass *m) { pc_q35_4_1_machine_options(m); m->alias = NULL; + compat_props_add(m->compat_props, hw_compat_4_0_1, hw_compat_4_0_1_len); + compat_props_add(m->compat_props, pc_compat_4_0_1, pc_compat_4_0_1_len); +} + +DEFINE_Q35_MACHINE(v4_0_1, "pc-q35-4.0.1", NULL, + pc_q35_4_0_1_machine_options); + +static void pc_q35_4_0_machine_options(MachineClass *m) +{ + pc_q35_4_0_1_machine_options(m); + m->default_kernel_irqchip_split = true; + m->alias = NULL; compat_props_add(m->compat_props, hw_compat_4_0, hw_compat_4_0_len); compat_props_add(m->compat_props, pc_compat_4_0, pc_compat_4_0_len); } diff --git a/hw/ide/qdev.c b/hw/ide/qdev.c index 573b022e1e..360cd20bd8 100644 --- a/hw/ide/qdev.c +++ b/hw/ide/qdev.c @@ -168,7 +168,7 @@ static void ide_dev_initfn(IDEDevice *dev, IDEDriveKind kind, Error **errp) return; } else { /* Anonymous BlockBackend for an empty drive */ - dev->conf.blk = blk_new(0, BLK_PERM_ALL); + dev->conf.blk = blk_new(qemu_get_aio_context(), 0, BLK_PERM_ALL); ret = blk_attach_dev(dev->conf.blk, &dev->qdev); assert(ret == 0); } diff --git a/hw/intc/Makefile.objs b/hw/intc/Makefile.objs index df712c3e6c..03019b9a03 100644 --- a/hw/intc/Makefile.objs +++ b/hw/intc/Makefile.objs @@ -39,6 +39,7 @@ obj-$(CONFIG_XICS_SPAPR) += xics_spapr.o obj-$(CONFIG_XICS_KVM) += xics_kvm.o obj-$(CONFIG_XIVE) += xive.o obj-$(CONFIG_XIVE_SPAPR) += spapr_xive.o +obj-$(CONFIG_XIVE_KVM) += spapr_xive_kvm.o obj-$(CONFIG_POWERNV) += xics_pnv.o pnv_xive.o obj-$(CONFIG_ALLWINNER_A10_PIC) += allwinner-a10-pic.o obj-$(CONFIG_S390_FLIC) += s390_flic.o diff --git a/hw/intc/armv7m_nvic.c b/hw/intc/armv7m_nvic.c index 815e720cfa..dc2c206d9a 100644 --- a/hw/intc/armv7m_nvic.c +++ b/hw/intc/armv7m_nvic.c @@ -2595,9 +2595,9 @@ static void armv7m_nvic_realize(DeviceState *dev, Error **errp) * as we didn't know then if the CPU had the security extensions; * so we have to do it here. */ - object_initialize(&s->systick[M_REG_S], sizeof(s->systick[M_REG_S]), - TYPE_SYSTICK); - qdev_set_parent_bus(DEVICE(&s->systick[M_REG_S]), sysbus_get_default()); + sysbus_init_child_obj(OBJECT(dev), "systick-reg-s", + &s->systick[M_REG_S], + sizeof(s->systick[M_REG_S]), TYPE_SYSTICK); object_property_set_bool(OBJECT(&s->systick[M_REG_S]), true, "realized", &err); diff --git a/hw/intc/spapr_xive.c b/hw/intc/spapr_xive.c index 097f88d460..62e0ef8fa5 100644 --- a/hw/intc/spapr_xive.c +++ b/hw/intc/spapr_xive.c @@ -41,13 +41,6 @@ #define SPAPR_XIVE_NVT_BASE 0x400 /* - * The sPAPR machine has a unique XIVE IC device. Assign a fixed value - * to the controller block id value. It can nevertheless be changed - * for testing purpose. - */ -#define SPAPR_XIVE_BLOCK_ID 0x0 - -/* * sPAPR NVT and END indexing helpers */ static uint32_t spapr_xive_nvt_to_target(uint8_t nvt_blk, uint32_t nvt_idx) @@ -86,6 +79,22 @@ static int spapr_xive_target_to_nvt(uint32_t target, * sPAPR END indexing uses a simple mapping of the CPU vcpu_id, 8 * priorities per CPU */ +int spapr_xive_end_to_target(uint8_t end_blk, uint32_t end_idx, + uint32_t *out_server, uint8_t *out_prio) +{ + + assert(end_blk == SPAPR_XIVE_BLOCK_ID); + + if (out_server) { + *out_server = end_idx >> 3; + } + + if (out_prio) { + *out_prio = end_idx & 0x7; + } + return 0; +} + static void spapr_xive_cpu_to_end(PowerPCCPU *cpu, uint8_t prio, uint8_t *out_end_blk, uint32_t *out_end_idx) { @@ -120,6 +129,7 @@ static int spapr_xive_target_to_end(uint32_t target, uint8_t prio, static void spapr_xive_end_pic_print_info(SpaprXive *xive, XiveEND *end, Monitor *mon) { + uint64_t qaddr_base = xive_end_qaddr(end); uint32_t qindex = xive_get_field32(END_W1_PAGE_OFF, end->w1); uint32_t qgen = xive_get_field32(END_W1_GENERATION, end->w1); uint32_t qsize = xive_get_field32(END_W0_QSIZE, end->w0); @@ -127,9 +137,9 @@ static void spapr_xive_end_pic_print_info(SpaprXive *xive, XiveEND *end, uint32_t nvt = xive_get_field32(END_W6_NVT_INDEX, end->w6); uint8_t priority = xive_get_field32(END_W7_F0_PRIORITY, end->w7); - monitor_printf(mon, "%3d/%d % 6d/%5d ^%d", + monitor_printf(mon, "%3d/%d % 6d/%5d @%"PRIx64" ^%d", spapr_xive_nvt_to_target(0, nvt), - priority, qindex, qentries, qgen); + priority, qindex, qentries, qaddr_base, qgen); xive_end_queue_pic_print_info(end, 6, mon); monitor_printf(mon, "]"); @@ -140,7 +150,17 @@ void spapr_xive_pic_print_info(SpaprXive *xive, Monitor *mon) XiveSource *xsrc = &xive->source; int i; - monitor_printf(mon, " LSIN PQ EISN CPU/PRIO EQ\n"); + if (kvm_irqchip_in_kernel()) { + Error *local_err = NULL; + + kvmppc_xive_synchronize_state(xive, &local_err); + if (local_err) { + error_report_err(local_err); + return; + } + } + + monitor_printf(mon, " LISN PQ EISN CPU/PRIO EQ\n"); for (i = 0; i < xive->nr_irqs; i++) { uint8_t pq = xive_source_esb_get(xsrc, i); @@ -173,7 +193,7 @@ void spapr_xive_pic_print_info(SpaprXive *xive, Monitor *mon) } } -static void spapr_xive_map_mmio(SpaprXive *xive) +void spapr_xive_map_mmio(SpaprXive *xive) { sysbus_mmio_map(SYS_BUS_DEVICE(xive), 0, xive->vc_base); sysbus_mmio_map(SYS_BUS_DEVICE(xive), 1, xive->end_base); @@ -250,6 +270,9 @@ static void spapr_xive_instance_init(Object *obj) object_initialize_child(obj, "end_source", &xive->end_source, sizeof(xive->end_source), TYPE_XIVE_END_SOURCE, &error_abort, NULL); + + /* Not connected to the KVM XIVE device */ + xive->fd = -1; } static void spapr_xive_realize(DeviceState *dev, Error **errp) @@ -304,22 +327,36 @@ static void spapr_xive_realize(DeviceState *dev, Error **errp) xive->eat = g_new0(XiveEAS, xive->nr_irqs); xive->endt = g_new0(XiveEND, xive->nr_ends); - /* TIMA initialization */ - memory_region_init_io(&xive->tm_mmio, OBJECT(xive), &xive_tm_ops, xive, - "xive.tima", 4ull << TM_SHIFT); + xive->nodename = g_strdup_printf("interrupt-controller@%" PRIx64, + xive->tm_base + XIVE_TM_USER_PAGE * (1 << TM_SHIFT)); + + qemu_register_reset(spapr_xive_reset, dev); /* Define all XIVE MMIO regions on SysBus */ sysbus_init_mmio(SYS_BUS_DEVICE(xive), &xsrc->esb_mmio); sysbus_init_mmio(SYS_BUS_DEVICE(xive), &end_xsrc->esb_mmio); sysbus_init_mmio(SYS_BUS_DEVICE(xive), &xive->tm_mmio); +} - /* Map all regions */ - spapr_xive_map_mmio(xive); +void spapr_xive_init(SpaprXive *xive, Error **errp) +{ + XiveSource *xsrc = &xive->source; - xive->nodename = g_strdup_printf("interrupt-controller@%" PRIx64, - xive->tm_base + XIVE_TM_USER_PAGE * (1 << TM_SHIFT)); + /* + * The emulated XIVE device can only be initialized once. If the + * ESB memory region has been already mapped, it means we have been + * through there. + */ + if (memory_region_is_mapped(&xsrc->esb_mmio)) { + return; + } - qemu_register_reset(spapr_xive_reset, dev); + /* TIMA initialization */ + memory_region_init_io(&xive->tm_mmio, OBJECT(xive), &xive_tm_ops, xive, + "xive.tima", 4ull << TM_SHIFT); + + /* Map all regions */ + spapr_xive_map_mmio(xive); } static int spapr_xive_get_eas(XiveRouter *xrtr, uint8_t eas_blk, @@ -427,10 +464,34 @@ static const VMStateDescription vmstate_spapr_xive_eas = { }, }; +static int vmstate_spapr_xive_pre_save(void *opaque) +{ + if (kvm_irqchip_in_kernel()) { + return kvmppc_xive_pre_save(SPAPR_XIVE(opaque)); + } + + return 0; +} + +/* + * Called by the sPAPR IRQ backend 'post_load' method at the machine + * level. + */ +int spapr_xive_post_load(SpaprXive *xive, int version_id) +{ + if (kvm_irqchip_in_kernel()) { + return kvmppc_xive_post_load(xive, version_id); + } + + return 0; +} + static const VMStateDescription vmstate_spapr_xive = { .name = TYPE_SPAPR_XIVE, .version_id = 1, .minimum_version_id = 1, + .pre_save = vmstate_spapr_xive_pre_save, + .post_load = NULL, /* handled at the machine level */ .fields = (VMStateField[]) { VMSTATE_UINT32_EQUAL(nr_irqs, SpaprXive, NULL), VMSTATE_STRUCT_VARRAY_POINTER_UINT32(eat, SpaprXive, nr_irqs, @@ -494,6 +555,17 @@ bool spapr_xive_irq_claim(SpaprXive *xive, uint32_t lisn, bool lsi) if (lsi) { xive_source_irq_set_lsi(xsrc, lisn); } + + if (kvm_irqchip_in_kernel()) { + Error *local_err = NULL; + + kvmppc_xive_source_reset_one(xsrc, lisn, &local_err); + if (local_err) { + error_report_err(local_err); + return false; + } + } + return true; } @@ -755,6 +827,16 @@ static target_ulong h_int_set_source_config(PowerPCCPU *cpu, new_eas.w = xive_set_field64(EAS_END_DATA, new_eas.w, eisn); } + if (kvm_irqchip_in_kernel()) { + Error *local_err = NULL; + + kvmppc_xive_set_source_config(xive, lisn, &new_eas, &local_err); + if (local_err) { + error_report_err(local_err); + return H_HARDWARE; + } + } + out: xive->eat[lisn] = new_eas; return H_SUCCESS; @@ -993,6 +1075,12 @@ static target_ulong h_int_set_queue_config(PowerPCCPU *cpu, case 16: case 21: case 24: + if (!QEMU_IS_ALIGNED(qpage, 1ul << qsize)) { + qemu_log_mask(LOG_GUEST_ERROR, "XIVE: EQ @0x%" HWADDR_PRIx + " is not naturally aligned with %" HWADDR_PRIx "\n", + qpage, (hwaddr)1 << qsize); + return H_P4; + } end.w2 = cpu_to_be32((qpage >> 32) & 0x0fffffff); end.w3 = cpu_to_be32(qpage & 0xffffffff); end.w0 |= cpu_to_be32(END_W0_ENQUEUE); @@ -1060,6 +1148,16 @@ static target_ulong h_int_set_queue_config(PowerPCCPU *cpu, */ out: + if (kvm_irqchip_in_kernel()) { + Error *local_err = NULL; + + kvmppc_xive_set_queue_config(xive, end_blk, end_idx, &end, &local_err); + if (local_err) { + error_report_err(local_err); + return H_HARDWARE; + } + } + /* Update END */ memcpy(&xive->endt[end_idx], &end, sizeof(XiveEND)); return H_SUCCESS; @@ -1144,14 +1242,23 @@ static target_ulong h_int_get_queue_config(PowerPCCPU *cpu, } if (xive_end_is_enqueue(end)) { - args[1] = (uint64_t) be32_to_cpu(end->w2 & 0x0fffffff) << 32 - | be32_to_cpu(end->w3); + args[1] = xive_end_qaddr(end); args[2] = xive_get_field32(END_W0_QSIZE, end->w0) + 12; } else { args[1] = 0; args[2] = 0; } + if (kvm_irqchip_in_kernel()) { + Error *local_err = NULL; + + kvmppc_xive_get_queue_config(xive, end_blk, end_idx, end, &local_err); + if (local_err) { + error_report_err(local_err); + return H_HARDWARE; + } + } + /* TODO: do we need any locking on the END ? */ if (flags & SPAPR_XIVE_END_DEBUG) { /* Load the event queue generation number into the return flags */ @@ -1304,15 +1411,20 @@ static target_ulong h_int_esb(PowerPCCPU *cpu, return H_P3; } - mmio_addr = xive->vc_base + xive_source_esb_mgmt(xsrc, lisn) + offset; + if (kvm_irqchip_in_kernel()) { + args[0] = kvmppc_xive_esb_rw(xsrc, lisn, offset, data, + flags & SPAPR_XIVE_ESB_STORE); + } else { + mmio_addr = xive->vc_base + xive_source_esb_mgmt(xsrc, lisn) + offset; - if (dma_memory_rw(&address_space_memory, mmio_addr, &data, 8, - (flags & SPAPR_XIVE_ESB_STORE))) { - qemu_log_mask(LOG_GUEST_ERROR, "XIVE: failed to access ESB @0x%" - HWADDR_PRIx "\n", mmio_addr); - return H_HARDWARE; + if (dma_memory_rw(&address_space_memory, mmio_addr, &data, 8, + (flags & SPAPR_XIVE_ESB_STORE))) { + qemu_log_mask(LOG_GUEST_ERROR, "XIVE: failed to access ESB @0x%" + HWADDR_PRIx "\n", mmio_addr); + return H_HARDWARE; + } + args[0] = (flags & SPAPR_XIVE_ESB_STORE) ? -1 : data; } - args[0] = (flags & SPAPR_XIVE_ESB_STORE) ? -1 : data; return H_SUCCESS; } @@ -1369,7 +1481,20 @@ static target_ulong h_int_sync(PowerPCCPU *cpu, * This is not needed when running the emulation under QEMU */ - /* This is not real hardware. Nothing to be done */ + /* + * This is not real hardware. Nothing to be done unless when + * under KVM + */ + + if (kvm_irqchip_in_kernel()) { + Error *local_err = NULL; + + kvmppc_xive_sync_source(xive, lisn, &local_err); + if (local_err) { + error_report_err(local_err); + return H_HARDWARE; + } + } return H_SUCCESS; } @@ -1404,6 +1529,16 @@ static target_ulong h_int_reset(PowerPCCPU *cpu, } device_reset(DEVICE(xive)); + + if (kvm_irqchip_in_kernel()) { + Error *local_err = NULL; + + kvmppc_xive_reset(xive, &local_err); + if (local_err) { + error_report_err(local_err); + return H_HARDWARE; + } + } return H_SUCCESS; } diff --git a/hw/intc/spapr_xive_kvm.c b/hw/intc/spapr_xive_kvm.c new file mode 100644 index 0000000000..b48f135838 --- /dev/null +++ b/hw/intc/spapr_xive_kvm.c @@ -0,0 +1,823 @@ +/* + * QEMU PowerPC sPAPR XIVE interrupt controller model + * + * Copyright (c) 2017-2019, IBM Corporation. + * + * This code is licensed under the GPL version 2 or later. See the + * COPYING file in the top-level directory. + */ + +#include "qemu/osdep.h" +#include "qemu/log.h" +#include "qemu/error-report.h" +#include "qapi/error.h" +#include "target/ppc/cpu.h" +#include "sysemu/cpus.h" +#include "sysemu/kvm.h" +#include "hw/ppc/spapr.h" +#include "hw/ppc/spapr_cpu_core.h" +#include "hw/ppc/spapr_xive.h" +#include "hw/ppc/xive.h" +#include "kvm_ppc.h" + +#include <sys/ioctl.h> + +/* + * Helpers for CPU hotplug + * + * TODO: make a common KVMEnabledCPU layer for XICS and XIVE + */ +typedef struct KVMEnabledCPU { + unsigned long vcpu_id; + QLIST_ENTRY(KVMEnabledCPU) node; +} KVMEnabledCPU; + +static QLIST_HEAD(, KVMEnabledCPU) + kvm_enabled_cpus = QLIST_HEAD_INITIALIZER(&kvm_enabled_cpus); + +static bool kvm_cpu_is_enabled(CPUState *cs) +{ + KVMEnabledCPU *enabled_cpu; + unsigned long vcpu_id = kvm_arch_vcpu_id(cs); + + QLIST_FOREACH(enabled_cpu, &kvm_enabled_cpus, node) { + if (enabled_cpu->vcpu_id == vcpu_id) { + return true; + } + } + return false; +} + +static void kvm_cpu_enable(CPUState *cs) +{ + KVMEnabledCPU *enabled_cpu; + unsigned long vcpu_id = kvm_arch_vcpu_id(cs); + + enabled_cpu = g_malloc(sizeof(*enabled_cpu)); + enabled_cpu->vcpu_id = vcpu_id; + QLIST_INSERT_HEAD(&kvm_enabled_cpus, enabled_cpu, node); +} + +static void kvm_cpu_disable_all(void) +{ + KVMEnabledCPU *enabled_cpu, *next; + + QLIST_FOREACH_SAFE(enabled_cpu, &kvm_enabled_cpus, node, next) { + QLIST_REMOVE(enabled_cpu, node); + g_free(enabled_cpu); + } +} + +/* + * XIVE Thread Interrupt Management context (KVM) + */ + +static void kvmppc_xive_cpu_set_state(XiveTCTX *tctx, Error **errp) +{ + uint64_t state[2]; + int ret; + + /* word0 and word1 of the OS ring. */ + state[0] = *((uint64_t *) &tctx->regs[TM_QW1_OS]); + + ret = kvm_set_one_reg(tctx->cs, KVM_REG_PPC_VP_STATE, state); + if (ret != 0) { + error_setg_errno(errp, errno, + "XIVE: could not restore KVM state of CPU %ld", + kvm_arch_vcpu_id(tctx->cs)); + } +} + +void kvmppc_xive_cpu_get_state(XiveTCTX *tctx, Error **errp) +{ + SpaprXive *xive = SPAPR_MACHINE(qdev_get_machine())->xive; + uint64_t state[2] = { 0 }; + int ret; + + /* The KVM XIVE device is not in use */ + if (xive->fd == -1) { + return; + } + + ret = kvm_get_one_reg(tctx->cs, KVM_REG_PPC_VP_STATE, state); + if (ret != 0) { + error_setg_errno(errp, errno, + "XIVE: could not capture KVM state of CPU %ld", + kvm_arch_vcpu_id(tctx->cs)); + return; + } + + /* word0 and word1 of the OS ring. */ + *((uint64_t *) &tctx->regs[TM_QW1_OS]) = state[0]; +} + +typedef struct { + XiveTCTX *tctx; + Error *err; +} XiveCpuGetState; + +static void kvmppc_xive_cpu_do_synchronize_state(CPUState *cpu, + run_on_cpu_data arg) +{ + XiveCpuGetState *s = arg.host_ptr; + + kvmppc_xive_cpu_get_state(s->tctx, &s->err); +} + +void kvmppc_xive_cpu_synchronize_state(XiveTCTX *tctx, Error **errp) +{ + XiveCpuGetState s = { + .tctx = tctx, + .err = NULL, + }; + + /* + * Kick the vCPU to make sure they are available for the KVM ioctl. + */ + run_on_cpu(tctx->cs, kvmppc_xive_cpu_do_synchronize_state, + RUN_ON_CPU_HOST_PTR(&s)); + + if (s.err) { + error_propagate(errp, s.err); + return; + } +} + +void kvmppc_xive_cpu_connect(XiveTCTX *tctx, Error **errp) +{ + SpaprXive *xive = SPAPR_MACHINE(qdev_get_machine())->xive; + unsigned long vcpu_id; + int ret; + + /* The KVM XIVE device is not in use */ + if (xive->fd == -1) { + return; + } + + /* Check if CPU was hot unplugged and replugged. */ + if (kvm_cpu_is_enabled(tctx->cs)) { + return; + } + + vcpu_id = kvm_arch_vcpu_id(tctx->cs); + + ret = kvm_vcpu_enable_cap(tctx->cs, KVM_CAP_PPC_IRQ_XIVE, 0, xive->fd, + vcpu_id, 0); + if (ret < 0) { + error_setg(errp, "XIVE: unable to connect CPU%ld to KVM device: %s", + vcpu_id, strerror(errno)); + return; + } + + kvm_cpu_enable(tctx->cs); +} + +/* + * XIVE Interrupt Source (KVM) + */ + +void kvmppc_xive_set_source_config(SpaprXive *xive, uint32_t lisn, XiveEAS *eas, + Error **errp) +{ + uint32_t end_idx; + uint32_t end_blk; + uint8_t priority; + uint32_t server; + bool masked; + uint32_t eisn; + uint64_t kvm_src; + Error *local_err = NULL; + + assert(xive_eas_is_valid(eas)); + + end_idx = xive_get_field64(EAS_END_INDEX, eas->w); + end_blk = xive_get_field64(EAS_END_BLOCK, eas->w); + eisn = xive_get_field64(EAS_END_DATA, eas->w); + masked = xive_eas_is_masked(eas); + + spapr_xive_end_to_target(end_blk, end_idx, &server, &priority); + + kvm_src = priority << KVM_XIVE_SOURCE_PRIORITY_SHIFT & + KVM_XIVE_SOURCE_PRIORITY_MASK; + kvm_src |= server << KVM_XIVE_SOURCE_SERVER_SHIFT & + KVM_XIVE_SOURCE_SERVER_MASK; + kvm_src |= ((uint64_t) masked << KVM_XIVE_SOURCE_MASKED_SHIFT) & + KVM_XIVE_SOURCE_MASKED_MASK; + kvm_src |= ((uint64_t)eisn << KVM_XIVE_SOURCE_EISN_SHIFT) & + KVM_XIVE_SOURCE_EISN_MASK; + + kvm_device_access(xive->fd, KVM_DEV_XIVE_GRP_SOURCE_CONFIG, lisn, + &kvm_src, true, &local_err); + if (local_err) { + error_propagate(errp, local_err); + return; + } +} + +void kvmppc_xive_sync_source(SpaprXive *xive, uint32_t lisn, Error **errp) +{ + kvm_device_access(xive->fd, KVM_DEV_XIVE_GRP_SOURCE_SYNC, lisn, + NULL, true, errp); +} + +/* + * At reset, the interrupt sources are simply created and MASKED. We + * only need to inform the KVM XIVE device about their type: LSI or + * MSI. + */ +void kvmppc_xive_source_reset_one(XiveSource *xsrc, int srcno, Error **errp) +{ + SpaprXive *xive = SPAPR_XIVE(xsrc->xive); + uint64_t state = 0; + + /* The KVM XIVE device is not in use */ + if (xive->fd == -1) { + return; + } + + if (xive_source_irq_is_lsi(xsrc, srcno)) { + state |= KVM_XIVE_LEVEL_SENSITIVE; + if (xsrc->status[srcno] & XIVE_STATUS_ASSERTED) { + state |= KVM_XIVE_LEVEL_ASSERTED; + } + } + + kvm_device_access(xive->fd, KVM_DEV_XIVE_GRP_SOURCE, srcno, &state, + true, errp); +} + +static void kvmppc_xive_source_reset(XiveSource *xsrc, Error **errp) +{ + int i; + + for (i = 0; i < xsrc->nr_irqs; i++) { + Error *local_err = NULL; + + kvmppc_xive_source_reset_one(xsrc, i, &local_err); + if (local_err) { + error_propagate(errp, local_err); + return; + } + } +} + +/* + * This is used to perform the magic loads on the ESB pages, described + * in xive.h. + * + * Memory barriers should not be needed for loads (no store for now). + */ +static uint64_t xive_esb_rw(XiveSource *xsrc, int srcno, uint32_t offset, + uint64_t data, bool write) +{ + uint64_t *addr = xsrc->esb_mmap + xive_source_esb_mgmt(xsrc, srcno) + + offset; + + if (write) { + *addr = cpu_to_be64(data); + return -1; + } else { + /* Prevent the compiler from optimizing away the load */ + volatile uint64_t value = be64_to_cpu(*addr); + return value; + } +} + +static uint8_t xive_esb_read(XiveSource *xsrc, int srcno, uint32_t offset) +{ + return xive_esb_rw(xsrc, srcno, offset, 0, 0) & 0x3; +} + +static void xive_esb_trigger(XiveSource *xsrc, int srcno) +{ + uint64_t *addr = xsrc->esb_mmap + xive_source_esb_page(xsrc, srcno); + + *addr = 0x0; +} + +uint64_t kvmppc_xive_esb_rw(XiveSource *xsrc, int srcno, uint32_t offset, + uint64_t data, bool write) +{ + if (write) { + return xive_esb_rw(xsrc, srcno, offset, data, 1); + } + + /* + * Special Load EOI handling for LSI sources. Q bit is never set + * and the interrupt should be re-triggered if the level is still + * asserted. + */ + if (xive_source_irq_is_lsi(xsrc, srcno) && + offset == XIVE_ESB_LOAD_EOI) { + xive_esb_read(xsrc, srcno, XIVE_ESB_SET_PQ_00); + if (xsrc->status[srcno] & XIVE_STATUS_ASSERTED) { + xive_esb_trigger(xsrc, srcno); + } + return 0; + } else { + return xive_esb_rw(xsrc, srcno, offset, 0, 0); + } +} + +static void kvmppc_xive_source_get_state(XiveSource *xsrc) +{ + int i; + + for (i = 0; i < xsrc->nr_irqs; i++) { + /* Perform a load without side effect to retrieve the PQ bits */ + uint8_t pq = xive_esb_read(xsrc, i, XIVE_ESB_GET); + + /* and save PQ locally */ + xive_source_esb_set(xsrc, i, pq); + } +} + +void kvmppc_xive_source_set_irq(void *opaque, int srcno, int val) +{ + XiveSource *xsrc = opaque; + SpaprXive *xive = SPAPR_XIVE(xsrc->xive); + struct kvm_irq_level args; + int rc; + + /* The KVM XIVE device should be in use */ + assert(xive->fd != -1); + + args.irq = srcno; + if (!xive_source_irq_is_lsi(xsrc, srcno)) { + if (!val) { + return; + } + args.level = KVM_INTERRUPT_SET; + } else { + if (val) { + xsrc->status[srcno] |= XIVE_STATUS_ASSERTED; + args.level = KVM_INTERRUPT_SET_LEVEL; + } else { + xsrc->status[srcno] &= ~XIVE_STATUS_ASSERTED; + args.level = KVM_INTERRUPT_UNSET; + } + } + rc = kvm_vm_ioctl(kvm_state, KVM_IRQ_LINE, &args); + if (rc < 0) { + error_report("XIVE: kvm_irq_line() failed : %s", strerror(errno)); + } +} + +/* + * sPAPR XIVE interrupt controller (KVM) + */ +void kvmppc_xive_get_queue_config(SpaprXive *xive, uint8_t end_blk, + uint32_t end_idx, XiveEND *end, + Error **errp) +{ + struct kvm_ppc_xive_eq kvm_eq = { 0 }; + uint64_t kvm_eq_idx; + uint8_t priority; + uint32_t server; + Error *local_err = NULL; + + assert(xive_end_is_valid(end)); + + /* Encode the tuple (server, prio) as a KVM EQ index */ + spapr_xive_end_to_target(end_blk, end_idx, &server, &priority); + + kvm_eq_idx = priority << KVM_XIVE_EQ_PRIORITY_SHIFT & + KVM_XIVE_EQ_PRIORITY_MASK; + kvm_eq_idx |= server << KVM_XIVE_EQ_SERVER_SHIFT & + KVM_XIVE_EQ_SERVER_MASK; + + kvm_device_access(xive->fd, KVM_DEV_XIVE_GRP_EQ_CONFIG, kvm_eq_idx, + &kvm_eq, false, &local_err); + if (local_err) { + error_propagate(errp, local_err); + return; + } + + /* + * The EQ index and toggle bit are updated by HW. These are the + * only fields from KVM we want to update QEMU with. The other END + * fields should already be in the QEMU END table. + */ + end->w1 = xive_set_field32(END_W1_GENERATION, 0ul, kvm_eq.qtoggle) | + xive_set_field32(END_W1_PAGE_OFF, 0ul, kvm_eq.qindex); +} + +void kvmppc_xive_set_queue_config(SpaprXive *xive, uint8_t end_blk, + uint32_t end_idx, XiveEND *end, + Error **errp) +{ + struct kvm_ppc_xive_eq kvm_eq = { 0 }; + uint64_t kvm_eq_idx; + uint8_t priority; + uint32_t server; + Error *local_err = NULL; + + /* + * Build the KVM state from the local END structure. + */ + + kvm_eq.flags = 0; + if (xive_get_field32(END_W0_UCOND_NOTIFY, end->w0)) { + kvm_eq.flags |= KVM_XIVE_EQ_ALWAYS_NOTIFY; + } + + /* + * If the hcall is disabling the EQ, set the size and page address + * to zero. When migrating, only valid ENDs are taken into + * account. + */ + if (xive_end_is_valid(end)) { + kvm_eq.qshift = xive_get_field32(END_W0_QSIZE, end->w0) + 12; + kvm_eq.qaddr = xive_end_qaddr(end); + /* + * The EQ toggle bit and index should only be relevant when + * restoring the EQ state + */ + kvm_eq.qtoggle = xive_get_field32(END_W1_GENERATION, end->w1); + kvm_eq.qindex = xive_get_field32(END_W1_PAGE_OFF, end->w1); + } else { + kvm_eq.qshift = 0; + kvm_eq.qaddr = 0; + } + + /* Encode the tuple (server, prio) as a KVM EQ index */ + spapr_xive_end_to_target(end_blk, end_idx, &server, &priority); + + kvm_eq_idx = priority << KVM_XIVE_EQ_PRIORITY_SHIFT & + KVM_XIVE_EQ_PRIORITY_MASK; + kvm_eq_idx |= server << KVM_XIVE_EQ_SERVER_SHIFT & + KVM_XIVE_EQ_SERVER_MASK; + + kvm_device_access(xive->fd, KVM_DEV_XIVE_GRP_EQ_CONFIG, kvm_eq_idx, + &kvm_eq, true, &local_err); + if (local_err) { + error_propagate(errp, local_err); + return; + } +} + +void kvmppc_xive_reset(SpaprXive *xive, Error **errp) +{ + kvm_device_access(xive->fd, KVM_DEV_XIVE_GRP_CTRL, KVM_DEV_XIVE_RESET, + NULL, true, errp); +} + +static void kvmppc_xive_get_queues(SpaprXive *xive, Error **errp) +{ + Error *local_err = NULL; + int i; + + for (i = 0; i < xive->nr_ends; i++) { + if (!xive_end_is_valid(&xive->endt[i])) { + continue; + } + + kvmppc_xive_get_queue_config(xive, SPAPR_XIVE_BLOCK_ID, i, + &xive->endt[i], &local_err); + if (local_err) { + error_propagate(errp, local_err); + return; + } + } +} + +/* + * The primary goal of the XIVE VM change handler is to mark the EQ + * pages dirty when all XIVE event notifications have stopped. + * + * Whenever the VM is stopped, the VM change handler sets the source + * PQs to PENDING to stop the flow of events and to possibly catch a + * triggered interrupt occuring while the VM is stopped. The previous + * state is saved in anticipation of a migration. The XIVE controller + * is then synced through KVM to flush any in-flight event + * notification and stabilize the EQs. + * + * At this stage, we can mark the EQ page dirty and let a migration + * sequence transfer the EQ pages to the destination, which is done + * just after the stop state. + * + * The previous configuration of the sources is restored when the VM + * runs again. If an interrupt was queued while the VM was stopped, + * simply generate a trigger. + */ +static void kvmppc_xive_change_state_handler(void *opaque, int running, + RunState state) +{ + SpaprXive *xive = opaque; + XiveSource *xsrc = &xive->source; + Error *local_err = NULL; + int i; + + /* + * Restore the sources to their initial state. This is called when + * the VM resumes after a stop or a migration. + */ + if (running) { + for (i = 0; i < xsrc->nr_irqs; i++) { + uint8_t pq = xive_source_esb_get(xsrc, i); + uint8_t old_pq; + + old_pq = xive_esb_read(xsrc, i, XIVE_ESB_SET_PQ_00 + (pq << 8)); + + /* + * An interrupt was queued while the VM was stopped, + * generate a trigger. + */ + if (pq == XIVE_ESB_RESET && old_pq == XIVE_ESB_QUEUED) { + xive_esb_trigger(xsrc, i); + } + } + + return; + } + + /* + * Mask the sources, to stop the flow of event notifications, and + * save the PQs locally in the XiveSource object. The XiveSource + * state will be collected later on by its vmstate handler if a + * migration is in progress. + */ + for (i = 0; i < xsrc->nr_irqs; i++) { + uint8_t pq = xive_esb_read(xsrc, i, XIVE_ESB_GET); + + /* + * PQ is set to PENDING to possibly catch a triggered + * interrupt occuring while the VM is stopped (hotplug event + * for instance) . + */ + if (pq != XIVE_ESB_OFF) { + pq = xive_esb_read(xsrc, i, XIVE_ESB_SET_PQ_10); + } + xive_source_esb_set(xsrc, i, pq); + } + + /* + * Sync the XIVE controller in KVM, to flush in-flight event + * notification that should be enqueued in the EQs and mark the + * XIVE EQ pages dirty to collect all updates. + */ + kvm_device_access(xive->fd, KVM_DEV_XIVE_GRP_CTRL, + KVM_DEV_XIVE_EQ_SYNC, NULL, true, &local_err); + if (local_err) { + error_report_err(local_err); + return; + } +} + +void kvmppc_xive_synchronize_state(SpaprXive *xive, Error **errp) +{ + /* The KVM XIVE device is not in use */ + if (xive->fd == -1) { + return; + } + + /* + * When the VM is stopped, the sources are masked and the previous + * state is saved in anticipation of a migration. We should not + * synchronize the source state in that case else we will override + * the saved state. + */ + if (runstate_is_running()) { + kvmppc_xive_source_get_state(&xive->source); + } + + /* EAT: there is no extra state to query from KVM */ + + /* ENDT */ + kvmppc_xive_get_queues(xive, errp); +} + +/* + * The SpaprXive 'pre_save' method is called by the vmstate handler of + * the SpaprXive model, after the XIVE controller is synced in the VM + * change handler. + */ +int kvmppc_xive_pre_save(SpaprXive *xive) +{ + Error *local_err = NULL; + + /* The KVM XIVE device is not in use */ + if (xive->fd == -1) { + return 0; + } + + /* EAT: there is no extra state to query from KVM */ + + /* ENDT */ + kvmppc_xive_get_queues(xive, &local_err); + if (local_err) { + error_report_err(local_err); + return -1; + } + + return 0; +} + +/* + * The SpaprXive 'post_load' method is not called by a vmstate + * handler. It is called at the sPAPR machine level at the end of the + * migration sequence by the sPAPR IRQ backend 'post_load' method, + * when all XIVE states have been transferred and loaded. + */ +int kvmppc_xive_post_load(SpaprXive *xive, int version_id) +{ + Error *local_err = NULL; + CPUState *cs; + int i; + + /* The KVM XIVE device should be in use */ + assert(xive->fd != -1); + + /* Restore the ENDT first. The targetting depends on it. */ + for (i = 0; i < xive->nr_ends; i++) { + if (!xive_end_is_valid(&xive->endt[i])) { + continue; + } + + kvmppc_xive_set_queue_config(xive, SPAPR_XIVE_BLOCK_ID, i, + &xive->endt[i], &local_err); + if (local_err) { + error_report_err(local_err); + return -1; + } + } + + /* Restore the EAT */ + for (i = 0; i < xive->nr_irqs; i++) { + if (!xive_eas_is_valid(&xive->eat[i])) { + continue; + } + + kvmppc_xive_set_source_config(xive, i, &xive->eat[i], &local_err); + if (local_err) { + error_report_err(local_err); + return -1; + } + } + + /* Restore the thread interrupt contexts */ + CPU_FOREACH(cs) { + PowerPCCPU *cpu = POWERPC_CPU(cs); + + kvmppc_xive_cpu_set_state(spapr_cpu_state(cpu)->tctx, &local_err); + if (local_err) { + error_report_err(local_err); + return -1; + } + } + + /* The source states will be restored when the machine starts running */ + return 0; +} + +static void *kvmppc_xive_mmap(SpaprXive *xive, int pgoff, size_t len, + Error **errp) +{ + void *addr; + uint32_t page_shift = 16; /* TODO: fix page_shift */ + + addr = mmap(NULL, len, PROT_WRITE | PROT_READ, MAP_SHARED, xive->fd, + pgoff << page_shift); + if (addr == MAP_FAILED) { + error_setg_errno(errp, errno, "XIVE: unable to set memory mapping"); + return NULL; + } + + return addr; +} + +/* + * All the XIVE memory regions are now backed by mappings from the KVM + * XIVE device. + */ +void kvmppc_xive_connect(SpaprXive *xive, Error **errp) +{ + XiveSource *xsrc = &xive->source; + Error *local_err = NULL; + size_t esb_len = (1ull << xsrc->esb_shift) * xsrc->nr_irqs; + size_t tima_len = 4ull << TM_SHIFT; + CPUState *cs; + + /* + * The KVM XIVE device already in use. This is the case when + * rebooting under the XIVE-only interrupt mode. + */ + if (xive->fd != -1) { + return; + } + + if (!kvmppc_has_cap_xive()) { + error_setg(errp, "IRQ_XIVE capability must be present for KVM"); + return; + } + + /* First, create the KVM XIVE device */ + xive->fd = kvm_create_device(kvm_state, KVM_DEV_TYPE_XIVE, false); + if (xive->fd < 0) { + error_setg_errno(errp, -xive->fd, "XIVE: error creating KVM device"); + return; + } + + /* + * 1. Source ESB pages - KVM mapping + */ + xsrc->esb_mmap = kvmppc_xive_mmap(xive, KVM_XIVE_ESB_PAGE_OFFSET, esb_len, + &local_err); + if (local_err) { + error_propagate(errp, local_err); + return; + } + + memory_region_init_ram_device_ptr(&xsrc->esb_mmio, OBJECT(xsrc), + "xive.esb", esb_len, xsrc->esb_mmap); + + /* + * 2. END ESB pages (No KVM support yet) + */ + + /* + * 3. TIMA pages - KVM mapping + */ + xive->tm_mmap = kvmppc_xive_mmap(xive, KVM_XIVE_TIMA_PAGE_OFFSET, tima_len, + &local_err); + if (local_err) { + error_propagate(errp, local_err); + return; + } + memory_region_init_ram_device_ptr(&xive->tm_mmio, OBJECT(xive), + "xive.tima", tima_len, xive->tm_mmap); + + xive->change = qemu_add_vm_change_state_handler( + kvmppc_xive_change_state_handler, xive); + + /* Connect the presenters to the initial VCPUs of the machine */ + CPU_FOREACH(cs) { + PowerPCCPU *cpu = POWERPC_CPU(cs); + + kvmppc_xive_cpu_connect(spapr_cpu_state(cpu)->tctx, &local_err); + if (local_err) { + error_propagate(errp, local_err); + return; + } + } + + /* Update the KVM sources */ + kvmppc_xive_source_reset(xsrc, &local_err); + if (local_err) { + error_propagate(errp, local_err); + return; + } + + kvm_kernel_irqchip = true; + kvm_msi_via_irqfd_allowed = true; + kvm_gsi_direct_mapping = true; + + /* Map all regions */ + spapr_xive_map_mmio(xive); +} + +void kvmppc_xive_disconnect(SpaprXive *xive, Error **errp) +{ + XiveSource *xsrc; + size_t esb_len; + + /* The KVM XIVE device is not in use */ + if (!xive || xive->fd == -1) { + return; + } + + if (!kvmppc_has_cap_xive()) { + error_setg(errp, "IRQ_XIVE capability must be present for KVM"); + return; + } + + /* Clear the KVM mapping */ + xsrc = &xive->source; + esb_len = (1ull << xsrc->esb_shift) * xsrc->nr_irqs; + + sysbus_mmio_unmap(SYS_BUS_DEVICE(xive), 0); + munmap(xsrc->esb_mmap, esb_len); + + sysbus_mmio_unmap(SYS_BUS_DEVICE(xive), 1); + + sysbus_mmio_unmap(SYS_BUS_DEVICE(xive), 2); + munmap(xive->tm_mmap, 4ull << TM_SHIFT); + + /* + * When the KVM device fd is closed, the KVM device is destroyed + * and removed from the list of devices of the VM. The VCPU + * presenters are also detached from the device. + */ + close(xive->fd); + xive->fd = -1; + + kvm_kernel_irqchip = false; + kvm_msi_via_irqfd_allowed = false; + kvm_gsi_direct_mapping = false; + + /* Clear the local list of presenter (hotplug) */ + kvm_cpu_disable_all(); + + /* VM Change state handler is not needed anymore */ + qemu_del_vm_change_state_handler(xive->change); +} diff --git a/hw/intc/xics.c b/hw/intc/xics.c index af7dc709ab..79f5a8a916 100644 --- a/hw/intc/xics.c +++ b/hw/intc/xics.c @@ -610,6 +610,12 @@ static const TypeInfo ics_simple_info = { .class_size = sizeof(ICSStateClass), }; +static void ics_reset_irq(ICSIRQState *irq) +{ + irq->priority = 0xff; + irq->saved_priority = 0xff; +} + static void ics_base_reset(DeviceState *dev) { ICSState *ics = ICS_BASE(dev); @@ -623,8 +629,7 @@ static void ics_base_reset(DeviceState *dev) memset(ics->irqs, 0, sizeof(ICSIRQState) * ics->nr_irqs); for (i = 0; i < ics->nr_irqs; i++) { - ics->irqs[i].priority = 0xff; - ics->irqs[i].saved_priority = 0xff; + ics_reset_irq(ics->irqs + i); ics->irqs[i].flags = flags[i]; } } @@ -760,6 +765,7 @@ void ics_set_irq_type(ICSState *ics, int srcno, bool lsi) lsi ? XICS_FLAGS_IRQ_LSI : XICS_FLAGS_IRQ_MSI; if (kvm_irqchip_in_kernel()) { + ics_reset_irq(ics->irqs + srcno); ics_set_kvm_state_one(ics, srcno); } } diff --git a/hw/intc/xics_kvm.c b/hw/intc/xics_kvm.c index 78a252e6df..5ba5b77561 100644 --- a/hw/intc/xics_kvm.c +++ b/hw/intc/xics_kvm.c @@ -33,6 +33,7 @@ #include "trace.h" #include "sysemu/kvm.h" #include "hw/ppc/spapr.h" +#include "hw/ppc/spapr_cpu_core.h" #include "hw/ppc/xics.h" #include "hw/ppc/xics_spapr.h" #include "kvm_ppc.h" @@ -51,6 +52,16 @@ typedef struct KVMEnabledICP { static QLIST_HEAD(, KVMEnabledICP) kvm_enabled_icps = QLIST_HEAD_INITIALIZER(&kvm_enabled_icps); +static void kvm_disable_icps(void) +{ + KVMEnabledICP *enabled_icp, *next; + + QLIST_FOREACH_SAFE(enabled_icp, &kvm_enabled_icps, node, next) { + QLIST_REMOVE(enabled_icp, node); + g_free(enabled_icp); + } +} + /* * ICP-KVM */ @@ -59,6 +70,11 @@ void icp_get_kvm_state(ICPState *icp) uint64_t state; int ret; + /* The KVM XICS device is not in use */ + if (kernel_xics_fd == -1) { + return; + } + /* ICP for this CPU thread is not in use, exiting */ if (!icp->cs) { return; @@ -95,6 +111,11 @@ int icp_set_kvm_state(ICPState *icp) uint64_t state; int ret; + /* The KVM XICS device is not in use */ + if (kernel_xics_fd == -1) { + return 0; + } + /* ICP for this CPU thread is not in use, exiting */ if (!icp->cs) { return 0; @@ -123,8 +144,9 @@ void icp_kvm_realize(DeviceState *dev, Error **errp) unsigned long vcpu_id; int ret; + /* The KVM XICS device is not in use */ if (kernel_xics_fd == -1) { - abort(); + return; } cs = icp->cs; @@ -160,6 +182,11 @@ void ics_get_kvm_state(ICSState *ics) uint64_t state; int i; + /* The KVM XICS device is not in use */ + if (kernel_xics_fd == -1) { + return; + } + for (i = 0; i < ics->nr_irqs; i++) { ICSIRQState *irq = &ics->irqs[i]; @@ -220,6 +247,11 @@ int ics_set_kvm_state_one(ICSState *ics, int srcno) ICSIRQState *irq = &ics->irqs[srcno]; int ret; + /* The KVM XICS device is not in use */ + if (kernel_xics_fd == -1) { + return 0; + } + state = irq->server; state |= (uint64_t)(irq->saved_priority & KVM_XICS_PRIORITY_MASK) << KVM_XICS_PRIORITY_SHIFT; @@ -259,6 +291,11 @@ int ics_set_kvm_state(ICSState *ics) { int i; + /* The KVM XICS device is not in use */ + if (kernel_xics_fd == -1) { + return 0; + } + for (i = 0; i < ics->nr_irqs; i++) { int ret; @@ -276,6 +313,9 @@ void ics_kvm_set_irq(ICSState *ics, int srcno, int val) struct kvm_irq_level args; int rc; + /* The KVM XICS device should be in use */ + assert(kernel_xics_fd != -1); + args.irq = srcno + ics->offset; if (ics->irqs[srcno].flags & XICS_FLAGS_IRQ_MSI) { if (!val) { @@ -303,6 +343,16 @@ static void rtas_dummy(PowerPCCPU *cpu, SpaprMachineState *spapr, int xics_kvm_init(SpaprMachineState *spapr, Error **errp) { int rc; + CPUState *cs; + Error *local_err = NULL; + + /* + * The KVM XICS device already in use. This is the case when + * rebooting under the XICS-only interrupt mode. + */ + if (kernel_xics_fd != -1) { + return 0; + } if (!kvm_enabled() || !kvm_check_extension(kvm_state, KVM_CAP_IRQ_XICS)) { error_setg(errp, @@ -351,6 +401,26 @@ int xics_kvm_init(SpaprMachineState *spapr, Error **errp) kvm_msi_via_irqfd_allowed = true; kvm_gsi_direct_mapping = true; + /* Create the presenters */ + CPU_FOREACH(cs) { + PowerPCCPU *cpu = POWERPC_CPU(cs); + + icp_kvm_realize(DEVICE(spapr_cpu_state(cpu)->icp), &local_err); + if (local_err) { + error_propagate(errp, local_err); + goto fail; + } + } + + /* Update the KVM sources */ + ics_set_kvm_state(spapr->ics); + + /* Connect the presenters to the initial VCPUs of the machine */ + CPU_FOREACH(cs) { + PowerPCCPU *cpu = POWERPC_CPU(cs); + icp_set_kvm_state(spapr_cpu_state(cpu)->icp); + } + return 0; fail: @@ -360,3 +430,44 @@ fail: kvmppc_define_rtas_kernel_token(0, "ibm,int-off"); return -1; } + +void xics_kvm_disconnect(SpaprMachineState *spapr, Error **errp) +{ + /* The KVM XICS device is not in use */ + if (kernel_xics_fd == -1) { + return; + } + + if (!kvm_enabled() || !kvm_check_extension(kvm_state, KVM_CAP_IRQ_XICS)) { + error_setg(errp, + "KVM and IRQ_XICS capability must be present for KVM XICS device"); + return; + } + + /* + * Only on P9 using the XICS-on XIVE KVM device: + * + * When the KVM device fd is closed, the device is destroyed and + * removed from the list of devices of the VM. The VCPU presenters + * are also detached from the device. + */ + close(kernel_xics_fd); + kernel_xics_fd = -1; + + spapr_rtas_unregister(RTAS_IBM_SET_XIVE); + spapr_rtas_unregister(RTAS_IBM_GET_XIVE); + spapr_rtas_unregister(RTAS_IBM_INT_OFF); + spapr_rtas_unregister(RTAS_IBM_INT_ON); + + kvmppc_define_rtas_kernel_token(0, "ibm,set-xive"); + kvmppc_define_rtas_kernel_token(0, "ibm,get-xive"); + kvmppc_define_rtas_kernel_token(0, "ibm,int-on"); + kvmppc_define_rtas_kernel_token(0, "ibm,int-off"); + + kvm_kernel_irqchip = false; + kvm_msi_via_irqfd_allowed = false; + kvm_gsi_direct_mapping = false; + + /* Clear the presenter from the VCPUs */ + kvm_disable_icps(); +} diff --git a/hw/intc/xics_spapr.c b/hw/intc/xics_spapr.c index 9d2b8adef7..5a1835e8b1 100644 --- a/hw/intc/xics_spapr.c +++ b/hw/intc/xics_spapr.c @@ -239,6 +239,13 @@ static void rtas_int_on(PowerPCCPU *cpu, SpaprMachineState *spapr, void xics_spapr_init(SpaprMachineState *spapr) { + /* Emulated mode can only be initialized once. */ + if (spapr->ics->init) { + return; + } + + spapr->ics->init = true; + /* Registration of global state belongs into realize */ spapr_rtas_register(RTAS_IBM_SET_XIVE, "ibm,set-xive", rtas_set_xive); spapr_rtas_register(RTAS_IBM_GET_XIVE, "ibm,get-xive", rtas_get_xive); diff --git a/hw/intc/xive.c b/hw/intc/xive.c index a0b87001da..0c74e47aa4 100644 --- a/hw/intc/xive.c +++ b/hw/intc/xive.c @@ -493,6 +493,16 @@ void xive_tctx_pic_print_info(XiveTCTX *tctx, Monitor *mon) int cpu_index = tctx->cs ? tctx->cs->cpu_index : -1; int i; + if (kvm_irqchip_in_kernel()) { + Error *local_err = NULL; + + kvmppc_xive_cpu_synchronize_state(tctx, &local_err); + if (local_err) { + error_report_err(local_err); + return; + } + } + monitor_printf(mon, "CPU[%04x]: QW NSR CPPR IPB LSMFB ACK# INC AGE PIPR" " W2\n", cpu_index); @@ -555,6 +565,15 @@ static void xive_tctx_realize(DeviceState *dev, Error **errp) return; } + /* Connect the presenter to the VCPU (required for CPU hotplug) */ + if (kvm_irqchip_in_kernel()) { + kvmppc_xive_cpu_connect(tctx, &local_err); + if (local_err) { + error_propagate(errp, local_err); + return; + } + } + qemu_register_reset(xive_tctx_reset, dev); } @@ -563,10 +582,27 @@ static void xive_tctx_unrealize(DeviceState *dev, Error **errp) qemu_unregister_reset(xive_tctx_reset, dev); } +static int vmstate_xive_tctx_pre_save(void *opaque) +{ + Error *local_err = NULL; + + if (kvm_irqchip_in_kernel()) { + kvmppc_xive_cpu_get_state(XIVE_TCTX(opaque), &local_err); + if (local_err) { + error_report_err(local_err); + return -1; + } + } + + return 0; +} + static const VMStateDescription vmstate_xive_tctx = { .name = TYPE_XIVE_TCTX, .version_id = 1, .minimum_version_id = 1, + .pre_save = vmstate_xive_tctx_pre_save, + .post_load = NULL, /* handled by the sPAPRxive model */ .fields = (VMStateField[]) { VMSTATE_BUFFER(regs, XiveTCTX), VMSTATE_END_OF_LIST() @@ -990,9 +1026,11 @@ static void xive_source_realize(DeviceState *dev, Error **errp) xsrc->status = g_malloc0(xsrc->nr_irqs); xsrc->lsi_map = bitmap_new(xsrc->nr_irqs); - memory_region_init_io(&xsrc->esb_mmio, OBJECT(xsrc), - &xive_source_esb_ops, xsrc, "xive.esb", - (1ull << xsrc->esb_shift) * xsrc->nr_irqs); + if (!kvm_irqchip_in_kernel()) { + memory_region_init_io(&xsrc->esb_mmio, OBJECT(xsrc), + &xive_source_esb_ops, xsrc, "xive.esb", + (1ull << xsrc->esb_shift) * xsrc->nr_irqs); + } qemu_register_reset(xive_source_reset, dev); } @@ -1042,8 +1080,7 @@ static const TypeInfo xive_source_info = { void xive_end_queue_pic_print_info(XiveEND *end, uint32_t width, Monitor *mon) { - uint64_t qaddr_base = (uint64_t) be32_to_cpu(end->w2 & 0x0fffffff) << 32 - | be32_to_cpu(end->w3); + uint64_t qaddr_base = xive_end_qaddr(end); uint32_t qsize = xive_get_field32(END_W0_QSIZE, end->w0); uint32_t qindex = xive_get_field32(END_W1_PAGE_OFF, end->w1); uint32_t qentries = 1 << (qsize + 10); @@ -1072,8 +1109,7 @@ void xive_end_queue_pic_print_info(XiveEND *end, uint32_t width, Monitor *mon) void xive_end_pic_print_info(XiveEND *end, uint32_t end_idx, Monitor *mon) { - uint64_t qaddr_base = (uint64_t) be32_to_cpu(end->w2 & 0x0fffffff) << 32 - | be32_to_cpu(end->w3); + uint64_t qaddr_base = xive_end_qaddr(end); uint32_t qindex = xive_get_field32(END_W1_PAGE_OFF, end->w1); uint32_t qgen = xive_get_field32(END_W1_GENERATION, end->w1); uint32_t qsize = xive_get_field32(END_W0_QSIZE, end->w0); @@ -1101,8 +1137,7 @@ void xive_end_pic_print_info(XiveEND *end, uint32_t end_idx, Monitor *mon) static void xive_end_enqueue(XiveEND *end, uint32_t data) { - uint64_t qaddr_base = (uint64_t) be32_to_cpu(end->w2 & 0x0fffffff) << 32 - | be32_to_cpu(end->w3); + uint64_t qaddr_base = xive_end_qaddr(end); uint32_t qsize = xive_get_field32(END_W0_QSIZE, end->w0); uint32_t qindex = xive_get_field32(END_W1_PAGE_OFF, end->w1); uint32_t qgen = xive_get_field32(END_W1_GENERATION, end->w1); diff --git a/hw/isa/i82378.c b/hw/isa/i82378.c index a5d67bc6d7..c08970b24a 100644 --- a/hw/isa/i82378.c +++ b/hw/isa/i82378.c @@ -21,7 +21,6 @@ #include "hw/pci/pci.h" #include "hw/i386/pc.h" #include "hw/timer/i8254.h" -#include "hw/timer/mc146818rtc.h" #include "hw/audio/pcspk.h" #define TYPE_I82378 "i82378" @@ -105,9 +104,6 @@ static void i82378_realize(PCIDevice *pci, Error **errp) /* 2 82C37 (dma) */ isa = isa_create_simple(isabus, "i82374"); - - /* timer */ - isa_create_simple(isabus, TYPE_MC146818_RTC); } static void i82378_init(Object *obj) diff --git a/hw/isa/lpc_ich9.c b/hw/isa/lpc_ich9.c index 031ee9cd93..35d17246e9 100644 --- a/hw/isa/lpc_ich9.c +++ b/hw/isa/lpc_ich9.c @@ -412,7 +412,7 @@ void ich9_lpc_pm_init(PCIDevice *lpc_pci, bool smm_enabled) true); } - ich9_lpc_reset(&lpc->d.qdev); + ich9_lpc_reset(DEVICE(lpc)); } /* APM */ diff --git a/hw/isa/vt82c686.c b/hw/isa/vt82c686.c index 85d0532dd5..d46754f61c 100644 --- a/hw/isa/vt82c686.c +++ b/hw/isa/vt82c686.c @@ -369,7 +369,7 @@ static void vt82c686b_pm_realize(PCIDevice *dev, Error **errp) pci_conf[0x90] = s->smb_io_base | 1; pci_conf[0x91] = s->smb_io_base >> 8; pci_conf[0xd2] = 0x90; - pm_smbus_init(&s->dev.qdev, &s->smb, false); + pm_smbus_init(DEVICE(s), &s->smb, false); memory_region_add_subregion(get_system_io(), s->smb_io_base, &s->smb.io); apm_init(dev, &s->apm, NULL, s); diff --git a/hw/microblaze/xlnx-zynqmp-pmu.c b/hw/microblaze/xlnx-zynqmp-pmu.c index 57dc1ccd42..df6c0048aa 100644 --- a/hw/microblaze/xlnx-zynqmp-pmu.c +++ b/hw/microblaze/xlnx-zynqmp-pmu.c @@ -55,6 +55,7 @@ typedef struct XlnxZynqMPPMUSoCState { /*< public >*/ MicroBlazeCPU cpu; XlnxPMUIOIntc intc; + XlnxZynqMPIPI ipi[XLNX_ZYNQMP_PMU_NUM_IPIS]; } XlnxZynqMPPMUSoCState; @@ -67,6 +68,14 @@ static void xlnx_zynqmp_pmu_soc_init(Object *obj) sysbus_init_child_obj(obj, "intc", &s->intc, sizeof(s->intc), TYPE_XLNX_PMU_IO_INTC); + + /* Create the IPI device */ + for (int i = 0; i < XLNX_ZYNQMP_PMU_NUM_IPIS; i++) { + char *name = g_strdup_printf("ipi%d", i); + sysbus_init_child_obj(obj, name, &s->ipi[i], + sizeof(XlnxZynqMPIPI), TYPE_XLNX_ZYNQMP_IPI); + g_free(name); + } } static void xlnx_zynqmp_pmu_soc_realize(DeviceState *dev, Error **errp) @@ -112,6 +121,15 @@ static void xlnx_zynqmp_pmu_soc_realize(DeviceState *dev, Error **errp) sysbus_mmio_map(SYS_BUS_DEVICE(&s->intc), 0, XLNX_ZYNQMP_PMU_INTC_ADDR); sysbus_connect_irq(SYS_BUS_DEVICE(&s->intc), 0, qdev_get_gpio_in(DEVICE(&s->cpu), MB_CPU_IRQ)); + + /* Connect the IPI device */ + for (int i = 0; i < XLNX_ZYNQMP_PMU_NUM_IPIS; i++) { + object_property_set_bool(OBJECT(&s->ipi[i]), true, "realized", + &error_abort); + sysbus_mmio_map(SYS_BUS_DEVICE(&s->ipi[i]), 0, ipi_addr[i]); + sysbus_connect_irq(SYS_BUS_DEVICE(&s->ipi[i]), 0, + qdev_get_gpio_in(DEVICE(&s->intc), ipi_irq[i])); + } } static void xlnx_zynqmp_pmu_soc_class_init(ObjectClass *oc, void *data) @@ -144,9 +162,6 @@ static void xlnx_zynqmp_pmu_init(MachineState *machine) MemoryRegion *address_space_mem = get_system_memory(); MemoryRegion *pmu_rom = g_new(MemoryRegion, 1); MemoryRegion *pmu_ram = g_new(MemoryRegion, 1); - XlnxZynqMPIPI *ipi[XLNX_ZYNQMP_PMU_NUM_IPIS]; - qemu_irq irq[32]; - int i; /* Create the ROM */ memory_region_init_rom(pmu_rom, NULL, "xlnx-zynqmp-pmu.rom", @@ -161,29 +176,11 @@ static void xlnx_zynqmp_pmu_init(MachineState *machine) pmu_ram); /* Create the PMU device */ - object_initialize(pmu, sizeof(XlnxZynqMPPMUSoCState), TYPE_XLNX_ZYNQMP_PMU_SOC); - object_property_add_child(OBJECT(machine), "pmu", OBJECT(pmu), - &error_abort); + object_initialize_child(OBJECT(machine), "pmu", pmu, + sizeof(XlnxZynqMPPMUSoCState), + TYPE_XLNX_ZYNQMP_PMU_SOC, &error_abort, NULL); object_property_set_bool(OBJECT(pmu), true, "realized", &error_fatal); - for (i = 0; i < 32; i++) { - irq[i] = qdev_get_gpio_in(DEVICE(&pmu->intc), i); - } - - /* Create and connect the IPI device */ - for (i = 0; i < XLNX_ZYNQMP_PMU_NUM_IPIS; i++) { - ipi[i] = g_new0(XlnxZynqMPIPI, 1); - object_initialize(ipi[i], sizeof(XlnxZynqMPIPI), TYPE_XLNX_ZYNQMP_IPI); - qdev_set_parent_bus(DEVICE(ipi[i]), sysbus_get_default()); - } - - for (i = 0; i < XLNX_ZYNQMP_PMU_NUM_IPIS; i++) { - object_property_set_bool(OBJECT(ipi[i]), true, "realized", - &error_abort); - sysbus_mmio_map(SYS_BUS_DEVICE(ipi[i]), 0, ipi_addr[i]); - sysbus_connect_irq(SYS_BUS_DEVICE(ipi[i]), 0, irq[ipi_irq[i]]); - } - /* Load the kernel */ microblaze_load_kernel(&pmu->cpu, XLNX_ZYNQMP_PMU_RAM_ADDR, machine->ram_size, diff --git a/hw/mips/boston.c b/hw/mips/boston.c index a8b29f62f5..1ffccc8da9 100644 --- a/hw/mips/boston.c +++ b/hw/mips/boston.c @@ -49,7 +49,7 @@ typedef struct { SysBusDevice parent_obj; MachineState *mach; - MIPSCPSState *cps; + MIPSCPSState cps; SerialState *uart; CharBackend lcd_display; @@ -188,7 +188,7 @@ static uint64_t boston_platreg_read(void *opaque, hwaddr addr, case PLAT_DDR3_STATUS: return PLAT_DDR3_STATUS_LOCKED | PLAT_DDR3_STATUS_CALIBRATED; case PLAT_MMCM_DIV: - gic_freq = mips_gictimer_get_freq(s->cps->gic.gic_timer) / 1000000; + gic_freq = mips_gictimer_get_freq(s->cps.gic.gic_timer) / 1000000; val = gic_freq << PLAT_MMCM_DIV_INPUT_SHIFT; val |= 1 << PLAT_MMCM_DIV_MUL_SHIFT; val |= 1 << PLAT_MMCM_DIV_CLK0DIV_SHIFT; @@ -455,20 +455,19 @@ static void boston_mach_init(MachineState *machine) is_64b = cpu_supports_isa(machine->cpu_type, ISA_MIPS64); - s->cps = MIPS_CPS(object_new(TYPE_MIPS_CPS)); - qdev_set_parent_bus(DEVICE(s->cps), sysbus_get_default()); - - object_property_set_str(OBJECT(s->cps), machine->cpu_type, "cpu-type", + sysbus_init_child_obj(OBJECT(machine), "cps", OBJECT(&s->cps), + sizeof(s->cps), TYPE_MIPS_CPS); + object_property_set_str(OBJECT(&s->cps), machine->cpu_type, "cpu-type", &err); - object_property_set_int(OBJECT(s->cps), smp_cpus, "num-vp", &err); - object_property_set_bool(OBJECT(s->cps), true, "realized", &err); + object_property_set_int(OBJECT(&s->cps), smp_cpus, "num-vp", &err); + object_property_set_bool(OBJECT(&s->cps), true, "realized", &err); if (err != NULL) { error_report("%s", error_get_pretty(err)); exit(1); } - sysbus_mmio_map_overlap(SYS_BUS_DEVICE(s->cps), 0, 0, 1); + sysbus_mmio_map_overlap(SYS_BUS_DEVICE(&s->cps), 0, 0, 1); flash = g_new(MemoryRegion, 1); memory_region_init_rom(flash, NULL, "boston.flash", 128 * MiB, &err); @@ -487,17 +486,17 @@ static void boston_mach_init(MachineState *machine) xilinx_pcie_init(sys_mem, 0, 0x10000000, 32 * MiB, 0x40000000, 1 * GiB, - get_cps_irq(s->cps, 2), false); + get_cps_irq(&s->cps, 2), false); xilinx_pcie_init(sys_mem, 1, 0x12000000, 32 * MiB, 0x20000000, 512 * MiB, - get_cps_irq(s->cps, 1), false); + get_cps_irq(&s->cps, 1), false); pcie2 = xilinx_pcie_init(sys_mem, 2, 0x14000000, 32 * MiB, 0x16000000, 1 * MiB, - get_cps_irq(s->cps, 0), true); + get_cps_irq(&s->cps, 0), true); platreg = g_new(MemoryRegion, 1); memory_region_init_io(platreg, NULL, &boston_platreg_ops, s, @@ -505,7 +504,7 @@ static void boston_mach_init(MachineState *machine) memory_region_add_subregion_overlap(sys_mem, 0x17ffd000, platreg, 0); s->uart = serial_mm_init(sys_mem, 0x17ffe000, 2, - get_cps_irq(s->cps, 3), 10000000, + get_cps_irq(&s->cps, 3), 10000000, serial_hd(0), DEVICE_NATIVE_ENDIAN); lcd = g_new(MemoryRegion, 1); diff --git a/hw/mips/cps.c b/hw/mips/cps.c index fc97f59af4..649b35a76c 100644 --- a/hw/mips/cps.c +++ b/hw/mips/cps.c @@ -94,9 +94,8 @@ static void mips_cps_realize(DeviceState *dev, Error **errp) /* Inter-Thread Communication Unit */ if (itu_present) { - object_initialize(&s->itu, sizeof(s->itu), TYPE_MIPS_ITU); - qdev_set_parent_bus(DEVICE(&s->itu), sysbus_get_default()); - + sysbus_init_child_obj(OBJECT(dev), "itu", &s->itu, sizeof(s->itu), + TYPE_MIPS_ITU); object_property_set_int(OBJECT(&s->itu), 16, "num-fifo", &err); object_property_set_int(OBJECT(&s->itu), 16, "num-semaphores", &err); object_property_set_bool(OBJECT(&s->itu), saar_present, "saar-present", @@ -115,9 +114,8 @@ static void mips_cps_realize(DeviceState *dev, Error **errp) } /* Cluster Power Controller */ - object_initialize(&s->cpc, sizeof(s->cpc), TYPE_MIPS_CPC); - qdev_set_parent_bus(DEVICE(&s->cpc), sysbus_get_default()); - + sysbus_init_child_obj(OBJECT(dev), "cpc", &s->cpc, sizeof(s->cpc), + TYPE_MIPS_CPC); object_property_set_int(OBJECT(&s->cpc), s->num_vp, "num-vp", &err); object_property_set_int(OBJECT(&s->cpc), 1, "vp-start-running", &err); object_property_set_bool(OBJECT(&s->cpc), true, "realized", &err); @@ -130,9 +128,8 @@ static void mips_cps_realize(DeviceState *dev, Error **errp) sysbus_mmio_get_region(SYS_BUS_DEVICE(&s->cpc), 0)); /* Global Interrupt Controller */ - object_initialize(&s->gic, sizeof(s->gic), TYPE_MIPS_GIC); - qdev_set_parent_bus(DEVICE(&s->gic), sysbus_get_default()); - + sysbus_init_child_obj(OBJECT(dev), "gic", &s->gic, sizeof(s->gic), + TYPE_MIPS_GIC); object_property_set_int(OBJECT(&s->gic), s->num_vp, "num-vp", &err); object_property_set_int(OBJECT(&s->gic), 128, "num-irq", &err); object_property_set_bool(OBJECT(&s->gic), true, "realized", &err); @@ -147,9 +144,8 @@ static void mips_cps_realize(DeviceState *dev, Error **errp) /* Global Configuration Registers */ gcr_base = env->CP0_CMGCRBase << 4; - object_initialize(&s->gcr, sizeof(s->gcr), TYPE_MIPS_GCR); - qdev_set_parent_bus(DEVICE(&s->gcr), sysbus_get_default()); - + sysbus_init_child_obj(OBJECT(dev), "gcr", &s->gcr, sizeof(s->gcr), + TYPE_MIPS_GCR); object_property_set_int(OBJECT(&s->gcr), s->num_vp, "num-vp", &err); object_property_set_int(OBJECT(&s->gcr), 0x800, "gcr-rev", &err); object_property_set_int(OBJECT(&s->gcr), gcr_base, "gcr-base", &err); diff --git a/hw/mips/mips_malta.c b/hw/mips/mips_malta.c index 439665ab45..37ec89b07e 100644 --- a/hw/mips/mips_malta.c +++ b/hw/mips/mips_malta.c @@ -55,7 +55,7 @@ #include "qemu/error-report.h" #include "hw/empty_slot.h" #include "sysemu/kvm.h" -#include "exec/semihost.h" +#include "hw/semihosting/semihost.h" #include "hw/mips/cps.h" #define ENVP_ADDR 0x80002000l @@ -94,7 +94,7 @@ typedef struct { typedef struct { SysBusDevice parent_obj; - MIPSCPSState *cps; + MIPSCPSState cps; qemu_irq *i8259; } MaltaState; @@ -1151,20 +1151,19 @@ static void create_cps(MaltaState *s, const char *cpu_type, { Error *err = NULL; - s->cps = MIPS_CPS(object_new(TYPE_MIPS_CPS)); - qdev_set_parent_bus(DEVICE(s->cps), sysbus_get_default()); - - object_property_set_str(OBJECT(s->cps), cpu_type, "cpu-type", &err); - object_property_set_int(OBJECT(s->cps), smp_cpus, "num-vp", &err); - object_property_set_bool(OBJECT(s->cps), true, "realized", &err); + sysbus_init_child_obj(OBJECT(s), "cps", OBJECT(&s->cps), sizeof(s->cps), + TYPE_MIPS_CPS); + object_property_set_str(OBJECT(&s->cps), cpu_type, "cpu-type", &err); + object_property_set_int(OBJECT(&s->cps), smp_cpus, "num-vp", &err); + object_property_set_bool(OBJECT(&s->cps), true, "realized", &err); if (err != NULL) { error_report("%s", error_get_pretty(err)); exit(1); } - sysbus_mmio_map_overlap(SYS_BUS_DEVICE(s->cps), 0, 0, 1); + sysbus_mmio_map_overlap(SYS_BUS_DEVICE(&s->cps), 0, 0, 1); - *i8259_irq = get_cps_irq(s->cps, 3); + *i8259_irq = get_cps_irq(&s->cps, 3); *cbus_irq = NULL; } diff --git a/hw/misc/edu.c b/hw/misc/edu.c index 91af452c9e..19e5545e2c 100644 --- a/hw/misc/edu.c +++ b/hw/misc/edu.c @@ -98,23 +98,24 @@ static void edu_lower_irq(EduState *edu, uint32_t val) } } -static bool within(uint32_t addr, uint32_t start, uint32_t end) +static bool within(uint64_t addr, uint64_t start, uint64_t end) { return start <= addr && addr < end; } -static void edu_check_range(uint32_t addr, uint32_t size1, uint32_t start, - uint32_t size2) +static void edu_check_range(uint64_t addr, uint64_t size1, uint64_t start, + uint64_t size2) { - uint32_t end1 = addr + size1; - uint32_t end2 = start + size2; + uint64_t end1 = addr + size1; + uint64_t end2 = start + size2; if (within(addr, start, end2) && end1 > addr && within(end1, start, end2)) { return; } - hw_error("EDU: DMA range 0x%.8x-0x%.8x out of bounds (0x%.8x-0x%.8x)!", + hw_error("EDU: DMA range 0x%016"PRIx64"-0x%016"PRIx64 + " out of bounds (0x%016"PRIx64"-0x%016"PRIx64")!", addr, end1 - 1, start, end2 - 1); } @@ -139,13 +140,13 @@ static void edu_dma_timer(void *opaque) } if (EDU_DMA_DIR(edu->dma.cmd) == EDU_DMA_FROM_PCI) { - uint32_t dst = edu->dma.dst; + uint64_t dst = edu->dma.dst; edu_check_range(dst, edu->dma.cnt, DMA_START, DMA_SIZE); dst -= DMA_START; pci_dma_read(&edu->pdev, edu_clamp_addr(edu, edu->dma.src), edu->dma_buf + dst, edu->dma.cnt); } else { - uint32_t src = edu->dma.src; + uint64_t src = edu->dma.src; edu_check_range(src, edu->dma.cnt, DMA_START, DMA_SIZE); src -= DMA_START; pci_dma_write(&edu->pdev, edu_clamp_addr(edu, edu->dma.dst), @@ -185,7 +186,11 @@ static uint64_t edu_mmio_read(void *opaque, hwaddr addr, unsigned size) EduState *edu = opaque; uint64_t val = ~0ULL; - if (size != 4) { + if (addr < 0x80 && size != 4) { + return val; + } + + if (addr >= 0x80 && size != 4 && size != 8) { return val; } @@ -289,6 +294,15 @@ static const MemoryRegionOps edu_mmio_ops = { .read = edu_mmio_read, .write = edu_mmio_write, .endianness = DEVICE_NATIVE_ENDIAN, + .valid = { + .min_access_size = 4, + .max_access_size = 8, + }, + .impl = { + .min_access_size = 4, + .max_access_size = 8, + }, + }; /* diff --git a/hw/misc/macio/macio.c b/hw/misc/macio/macio.c index 94da85c8d7..b726c73022 100644 --- a/hw/misc/macio/macio.c +++ b/hw/misc/macio/macio.c @@ -346,12 +346,12 @@ static void macio_newworld_realize(PCIDevice *d, Error **errp) object_property_set_bool(OBJECT(&ns->gpio), true, "realized", &err); /* PMU */ - object_initialize(&s->pmu, sizeof(s->pmu), TYPE_VIA_PMU); + object_initialize_child(OBJECT(s), "pmu", &s->pmu, sizeof(s->pmu), + TYPE_VIA_PMU, &error_abort, NULL); object_property_set_link(OBJECT(&s->pmu), OBJECT(sysbus_dev), "gpio", &error_abort); qdev_prop_set_bit(DEVICE(&s->pmu), "has-adb", ns->has_adb); qdev_set_parent_bus(DEVICE(&s->pmu), BUS(&s->macio_bus)); - object_property_add_child(OBJECT(s), "pmu", OBJECT(&s->pmu), NULL); object_property_set_bool(OBJECT(&s->pmu), true, "realized", &err); if (err) { @@ -365,9 +365,9 @@ static void macio_newworld_realize(PCIDevice *d, Error **errp) sysbus_mmio_get_region(sysbus_dev, 0)); } else { /* CUDA */ - object_initialize(&s->cuda, sizeof(s->cuda), TYPE_CUDA); + object_initialize_child(OBJECT(s), "cuda", &s->cuda, sizeof(s->cuda), + TYPE_CUDA, &error_abort, NULL); qdev_set_parent_bus(DEVICE(&s->cuda), BUS(&s->macio_bus)); - object_property_add_child(OBJECT(s), "cuda", OBJECT(&s->cuda), NULL); qdev_prop_set_uint64(DEVICE(&s->cuda), "timebase-frequency", s->frequency); diff --git a/hw/pci-bridge/dec.c b/hw/pci-bridge/dec.c index 8484bfd434..ca40253730 100644 --- a/hw/pci-bridge/dec.c +++ b/hw/pci-bridge/dec.c @@ -68,7 +68,7 @@ static void dec_21154_pci_bridge_class_init(ObjectClass *klass, void *data) k->vendor_id = PCI_VENDOR_ID_DEC; k->device_id = PCI_DEVICE_ID_DEC_21154; k->config_write = pci_bridge_write_config; - k->is_bridge = 1; + k->is_bridge = true; dc->desc = "DEC 21154 PCI-PCI bridge"; dc->reset = pci_bridge_reset; dc->vmsd = &vmstate_pci_device; @@ -129,7 +129,7 @@ static void dec_21154_pci_host_class_init(ObjectClass *klass, void *data) k->device_id = PCI_DEVICE_ID_DEC_21154; k->revision = 0x02; k->class_id = PCI_CLASS_BRIDGE_PCI; - k->is_bridge = 1; + k->is_bridge = true; /* * PCI-facing part of the host bridge, not usable without the * host-facing part, which can't be device_add'ed, yet. diff --git a/hw/pci-bridge/i82801b11.c b/hw/pci-bridge/i82801b11.c index 10e590e5c6..6d8b0f54a7 100644 --- a/hw/pci-bridge/i82801b11.c +++ b/hw/pci-bridge/i82801b11.c @@ -90,7 +90,7 @@ static void i82801b11_bridge_class_init(ObjectClass *klass, void *data) PCIDeviceClass *k = PCI_DEVICE_CLASS(klass); DeviceClass *dc = DEVICE_CLASS(klass); - k->is_bridge = 1; + k->is_bridge = true; k->vendor_id = PCI_VENDOR_ID_INTEL; k->device_id = PCI_DEVICE_ID_INTEL_82801BA_11; k->revision = ICH9_D2P_A2_REVISION; diff --git a/hw/pci-bridge/pci_bridge_dev.c b/hw/pci-bridge/pci_bridge_dev.c index ff6b8323da..c56ed1f52f 100644 --- a/hw/pci-bridge/pci_bridge_dev.c +++ b/hw/pci-bridge/pci_bridge_dev.c @@ -253,7 +253,7 @@ static void pci_bridge_dev_class_init(ObjectClass *klass, void *data) k->vendor_id = PCI_VENDOR_ID_REDHAT; k->device_id = PCI_DEVICE_ID_REDHAT_BRIDGE; k->class_id = PCI_CLASS_BRIDGE_PCI; - k->is_bridge = 1, + k->is_bridge = true; dc->desc = "Standard PCI Bridge"; dc->reset = qdev_pci_bridge_dev_reset; dc->props = pci_bridge_dev_properties; diff --git a/hw/pci-bridge/pcie_pci_bridge.c b/hw/pci-bridge/pcie_pci_bridge.c index d491b40d04..9a4fba413a 100644 --- a/hw/pci-bridge/pcie_pci_bridge.c +++ b/hw/pci-bridge/pcie_pci_bridge.c @@ -143,7 +143,7 @@ static void pcie_pci_bridge_class_init(ObjectClass *klass, void *data) DeviceClass *dc = DEVICE_CLASS(klass); HotplugHandlerClass *hc = HOTPLUG_HANDLER_CLASS(klass); - k->is_bridge = 1; + k->is_bridge = true; k->vendor_id = PCI_VENDOR_ID_REDHAT; k->device_id = PCI_DEVICE_ID_REDHAT_PCIE_BRIDGE; k->realize = pcie_pci_bridge_realize; diff --git a/hw/pci-bridge/pcie_root_port.c b/hw/pci-bridge/pcie_root_port.c index e94d918b6d..be3f4d5e03 100644 --- a/hw/pci-bridge/pcie_root_port.c +++ b/hw/pci-bridge/pcie_root_port.c @@ -162,7 +162,7 @@ static void rp_class_init(ObjectClass *klass, void *data) DeviceClass *dc = DEVICE_CLASS(klass); PCIDeviceClass *k = PCI_DEVICE_CLASS(klass); - k->is_bridge = 1; + k->is_bridge = true; k->config_write = rp_write_config; k->realize = rp_realize; k->exit = rp_exit; diff --git a/hw/pci-bridge/simba.c b/hw/pci-bridge/simba.c index dea4c8c5e7..7cf0d6e047 100644 --- a/hw/pci-bridge/simba.c +++ b/hw/pci-bridge/simba.c @@ -76,7 +76,7 @@ static void simba_pci_bridge_class_init(ObjectClass *klass, void *data) k->device_id = PCI_DEVICE_ID_SUN_SIMBA; k->revision = 0x11; k->config_write = pci_bridge_write_config; - k->is_bridge = 1; + k->is_bridge = true; set_bit(DEVICE_CATEGORY_BRIDGE, dc->categories); dc->reset = pci_bridge_reset; dc->vmsd = &vmstate_pci_device; diff --git a/hw/pci-bridge/xio3130_downstream.c b/hw/pci-bridge/xio3130_downstream.c index 467bbabe4c..ab2a51e15d 100644 --- a/hw/pci-bridge/xio3130_downstream.c +++ b/hw/pci-bridge/xio3130_downstream.c @@ -152,7 +152,7 @@ static void xio3130_downstream_class_init(ObjectClass *klass, void *data) DeviceClass *dc = DEVICE_CLASS(klass); PCIDeviceClass *k = PCI_DEVICE_CLASS(klass); - k->is_bridge = 1; + k->is_bridge = true; k->config_write = xio3130_downstream_write_config; k->realize = xio3130_downstream_realize; k->exit = xio3130_downstream_exitfn; diff --git a/hw/pci-bridge/xio3130_upstream.c b/hw/pci-bridge/xio3130_upstream.c index b524908cf1..1d41a49ab0 100644 --- a/hw/pci-bridge/xio3130_upstream.c +++ b/hw/pci-bridge/xio3130_upstream.c @@ -126,7 +126,7 @@ static void xio3130_upstream_class_init(ObjectClass *klass, void *data) DeviceClass *dc = DEVICE_CLASS(klass); PCIDeviceClass *k = PCI_DEVICE_CLASS(klass); - k->is_bridge = 1; + k->is_bridge = true; k->config_write = xio3130_upstream_write_config; k->realize = xio3130_upstream_realize; k->exit = xio3130_upstream_exitfn; diff --git a/hw/pci/pci.c b/hw/pci/pci.c index b386777045..d3893bdfe1 100644 --- a/hw/pci/pci.c +++ b/hw/pci/pci.c @@ -120,6 +120,27 @@ static void pci_bus_realize(BusState *qbus, Error **errp) vmstate_register(NULL, -1, &vmstate_pcibus, bus); } +static void pcie_bus_realize(BusState *qbus, Error **errp) +{ + PCIBus *bus = PCI_BUS(qbus); + + pci_bus_realize(qbus, errp); + + /* + * A PCI-E bus can support extended config space if it's the root + * bus, or if the bus/bridge above it does as well + */ + if (pci_bus_is_root(bus)) { + bus->flags |= PCI_BUS_EXTENDED_CONFIG_SPACE; + } else { + PCIBus *parent_bus = pci_get_bus(bus->parent_dev); + + if (pci_bus_allows_extended_config_space(parent_bus)) { + bus->flags |= PCI_BUS_EXTENDED_CONFIG_SPACE; + } + } +} + static void pci_bus_unrealize(BusState *qbus, Error **errp) { PCIBus *bus = PCI_BUS(qbus); @@ -142,11 +163,6 @@ static uint16_t pcibus_numa_node(PCIBus *bus) return NUMA_NODE_UNASSIGNED; } -static bool pcibus_allows_extended_config_space(PCIBus *bus) -{ - return false; -} - static void pci_bus_class_init(ObjectClass *klass, void *data) { BusClass *k = BUS_CLASS(klass); @@ -161,7 +177,6 @@ static void pci_bus_class_init(ObjectClass *klass, void *data) pbc->bus_num = pcibus_num; pbc->numa_node = pcibus_numa_node; - pbc->allows_extended_config_space = pcibus_allows_extended_config_space; } static const TypeInfo pci_bus_info = { @@ -182,16 +197,11 @@ static const TypeInfo conventional_pci_interface_info = { .parent = TYPE_INTERFACE, }; -static bool pciebus_allows_extended_config_space(PCIBus *bus) -{ - return true; -} - static void pcie_bus_class_init(ObjectClass *klass, void *data) { - PCIBusClass *pbc = PCI_BUS_CLASS(klass); + BusClass *k = BUS_CLASS(klass); - pbc->allows_extended_config_space = pciebus_allows_extended_config_space; + k->realize = pcie_bus_realize; } static const TypeInfo pcie_bus_info = { @@ -410,11 +420,6 @@ bool pci_bus_is_express(PCIBus *bus) return object_dynamic_cast(OBJECT(bus), TYPE_PCIE_BUS); } -bool pci_bus_allows_extended_config_space(PCIBus *bus) -{ - return PCI_BUS_GET_CLASS(bus)->allows_extended_config_space(bus); -} - void pci_root_bus_new_inplace(PCIBus *bus, size_t bus_size, DeviceState *parent, const char *name, MemoryRegion *address_space_mem, @@ -718,37 +723,6 @@ static int pci_parse_devaddr(const char *addr, int *domp, int *busp, return 0; } -static PCIBus *pci_get_bus_devfn(int *devfnp, PCIBus *root, - const char *devaddr) -{ - int dom, bus; - unsigned slot; - - if (!root) { - fprintf(stderr, "No primary PCI bus\n"); - return NULL; - } - - assert(!root->parent_dev); - - if (!devaddr) { - *devfnp = -1; - return pci_find_bus_nr(root, 0); - } - - if (pci_parse_devaddr(devaddr, &dom, &bus, &slot, NULL) < 0) { - return NULL; - } - - if (dom != 0) { - fprintf(stderr, "No support for non-zero PCI domains\n"); - return NULL; - } - - *devfnp = PCI_DEVFN(slot, 0); - return pci_find_bus_nr(root, bus); -} - static void pci_init_cmask(PCIDevice *dev) { pci_set_word(dev->cmask + PCI_VENDOR_ID, 0xffff); @@ -1890,6 +1864,8 @@ PCIDevice *pci_nic_init_nofail(NICInfo *nd, PCIBus *rootbus, DeviceState *dev; int devfn; int i; + int dom, busnr; + unsigned slot; if (nd->model && !strcmp(nd->model, "virtio")) { g_free(nd->model); @@ -1923,7 +1899,32 @@ PCIDevice *pci_nic_init_nofail(NICInfo *nd, PCIBus *rootbus, exit(1); } - bus = pci_get_bus_devfn(&devfn, rootbus, devaddr); + if (!rootbus) { + error_report("No primary PCI bus"); + exit(1); + } + + assert(!rootbus->parent_dev); + + if (!devaddr) { + devfn = -1; + busnr = 0; + } else { + if (pci_parse_devaddr(devaddr, &dom, &busnr, &slot, NULL) < 0) { + error_report("Invalid PCI device address %s for device %s", + devaddr, nd->model); + exit(1); + } + + if (dom != 0) { + error_report("No support for non-zero PCI domains"); + exit(1); + } + + devfn = PCI_DEVFN(slot, 0); + } + + bus = pci_find_bus_nr(rootbus, busnr); if (!bus) { error_report("Invalid PCI device address %s for device %s", devaddr, nd->model); diff --git a/hw/pci/pci_bridge.c b/hw/pci/pci_bridge.c index c6d9ded320..8d954885c0 100644 --- a/hw/pci/pci_bridge.c +++ b/hw/pci/pci_bridge.c @@ -273,7 +273,7 @@ void pci_bridge_write_config(PCIDevice *d, newctl = pci_get_word(d->config + PCI_BRIDGE_CONTROL); if (~oldctl & newctl & PCI_BRIDGE_CTL_BUS_RESET) { /* Trigger hot reset on 0->1 transition. */ - qbus_reset_all(&s->sec_bus.qbus); + qbus_reset_all(BUS(&s->sec_bus)); } } diff --git a/hw/pci/pci_host.c b/hw/pci/pci_host.c index 9d64b2e12f..5f3497256c 100644 --- a/hw/pci/pci_host.c +++ b/hw/pci/pci_host.c @@ -53,16 +53,9 @@ static inline PCIDevice *pci_dev_find_by_addr(PCIBus *bus, uint32_t addr) static void pci_adjust_config_limit(PCIBus *bus, uint32_t *limit) { - if (*limit > PCI_CONFIG_SPACE_SIZE) { - if (!pci_bus_allows_extended_config_space(bus)) { - *limit = PCI_CONFIG_SPACE_SIZE; - return; - } - - if (!pci_bus_is_root(bus)) { - PCIDevice *bridge = pci_bridge_get_device(bus); - pci_adjust_config_limit(pci_get_bus(bridge), limit); - } + if ((*limit > PCI_CONFIG_SPACE_SIZE) && + !pci_bus_allows_extended_config_space(bus)) { + *limit = PCI_CONFIG_SPACE_SIZE; } } diff --git a/hw/ppc/Kconfig b/hw/ppc/Kconfig index a3465155f0..f927ec9c74 100644 --- a/hw/ppc/Kconfig +++ b/hw/ppc/Kconfig @@ -122,3 +122,8 @@ config XIVE_SPAPR default y depends on PSERIES select XIVE + +config XIVE_KVM + bool + default y + depends on XIVE_SPAPR && KVM diff --git a/hw/ppc/pnv.c b/hw/ppc/pnv.c index dfb4ea5742..046f0a83c8 100644 --- a/hw/ppc/pnv.c +++ b/hw/ppc/pnv.c @@ -450,7 +450,8 @@ static void pnv_dt_power_mgt(void *fdt) static void *pnv_dt_create(MachineState *machine) { - const char plat_compat[] = "qemu,powernv\0ibm,powernv"; + const char plat_compat8[] = "qemu,powernv8\0qemu,powernv\0ibm,powernv"; + const char plat_compat9[] = "qemu,powernv9\0ibm,powernv"; PnvMachineState *pnv = PNV_MACHINE(machine); void *fdt; char *buf; @@ -465,8 +466,14 @@ static void *pnv_dt_create(MachineState *machine) _FDT((fdt_setprop_cell(fdt, 0, "#size-cells", 0x2))); _FDT((fdt_setprop_string(fdt, 0, "model", "IBM PowerNV (emulated by qemu)"))); - _FDT((fdt_setprop(fdt, 0, "compatible", plat_compat, - sizeof(plat_compat)))); + if (pnv_is_power9(pnv)) { + _FDT((fdt_setprop(fdt, 0, "compatible", plat_compat9, + sizeof(plat_compat9)))); + } else { + _FDT((fdt_setprop(fdt, 0, "compatible", plat_compat8, + sizeof(plat_compat8)))); + } + buf = qemu_uuid_unparse_strdup(&qemu_uuid); _FDT((fdt_setprop_string(fdt, 0, "vm,uuid", buf))); @@ -994,14 +1001,12 @@ static void pnv_chip_quad_realize(Pnv9Chip *chip9, Error **errp) PnvCore *pnv_core = PNV_CORE(chip->cores + (i * 4) * typesize); int core_id = CPU_CORE(pnv_core)->core_id; - object_initialize(eq, sizeof(*eq), TYPE_PNV_QUAD); snprintf(eq_name, sizeof(eq_name), "eq[%d]", core_id); + object_initialize_child(OBJECT(chip), eq_name, eq, sizeof(*eq), + TYPE_PNV_QUAD, &error_fatal, NULL); - object_property_add_child(OBJECT(chip), eq_name, OBJECT(eq), - &error_fatal); object_property_set_int(OBJECT(eq), core_id, "id", &error_fatal); object_property_set_bool(OBJECT(eq), true, "realized", &error_fatal); - object_unref(OBJECT(eq)); pnv_xscom_add_subregion(chip, PNV9_XSCOM_EQ_BASE(eq->id), &eq->xscom_regs); @@ -1165,10 +1170,9 @@ static void pnv_chip_core_realize(PnvChip *chip, Error **errp) continue; } - object_initialize(pnv_core, typesize, typename); snprintf(core_name, sizeof(core_name), "core[%d]", core_hwid); - object_property_add_child(OBJECT(chip), core_name, OBJECT(pnv_core), - &error_fatal); + object_initialize_child(OBJECT(chip), core_name, pnv_core, typesize, + typename, &error_fatal, NULL); object_property_set_int(OBJECT(pnv_core), smp_threads, "nr-threads", &error_fatal); object_property_set_int(OBJECT(pnv_core), core_hwid, @@ -1180,7 +1184,6 @@ static void pnv_chip_core_realize(PnvChip *chip, Error **errp) OBJECT(chip), &error_fatal); object_property_set_bool(OBJECT(pnv_core), true, "realized", &error_fatal); - object_unref(OBJECT(pnv_core)); /* Each core has an XSCOM MMIO region */ if (!pnv_chip_is_power9(chip)) { diff --git a/hw/ppc/pnv_xscom.c b/hw/ppc/pnv_xscom.c index c285ef514e..f53a6d7a94 100644 --- a/hw/ppc/pnv_xscom.c +++ b/hw/ppc/pnv_xscom.c @@ -29,6 +29,12 @@ #include <libfdt.h> +/* PRD registers */ +#define PRD_P8_IPOLL_REG_MASK 0x01020013 +#define PRD_P8_IPOLL_REG_STATUS 0x01020014 +#define PRD_P9_IPOLL_REG_MASK 0x000F0033 +#define PRD_P9_IPOLL_REG_STATUS 0x000F0034 + static void xscom_complete(CPUState *cs, uint64_t hmer_bits) { /* @@ -70,6 +76,12 @@ static uint64_t xscom_read_default(PnvChip *chip, uint32_t pcba) case 0x1010c00: /* PIBAM FIR */ case 0x1010c03: /* PIBAM FIR MASK */ + /* PRD registers */ + case PRD_P8_IPOLL_REG_MASK: + case PRD_P8_IPOLL_REG_STATUS: + case PRD_P9_IPOLL_REG_MASK: + case PRD_P9_IPOLL_REG_STATUS: + /* P9 xscom reset */ case 0x0090018: /* Receive status reg */ case 0x0090012: /* log register */ @@ -124,6 +136,12 @@ static bool xscom_write_default(PnvChip *chip, uint32_t pcba, uint64_t val) case 0x201302a: /* CAPP stuff */ case 0x2013801: /* CAPP stuff */ case 0x2013802: /* CAPP stuff */ + + /* P8 PRD registers */ + case PRD_P8_IPOLL_REG_MASK: + case PRD_P8_IPOLL_REG_STATUS: + case PRD_P9_IPOLL_REG_MASK: + case PRD_P9_IPOLL_REG_STATUS: return true; default: return false; diff --git a/hw/ppc/prep.c b/hw/ppc/prep.c index b7f459d475..2a8009e20b 100644 --- a/hw/ppc/prep.c +++ b/hw/ppc/prep.c @@ -601,7 +601,7 @@ static int prep_set_cmos_checksum(DeviceState *dev, void *opaque) uint16_t checksum = *(uint16_t *)opaque; ISADevice *rtc; - if (object_dynamic_cast(OBJECT(dev), "mc146818rtc")) { + if (object_dynamic_cast(OBJECT(dev), TYPE_MC146818_RTC)) { rtc = ISA_DEVICE(dev); rtc_set_memory(rtc, 0x2e, checksum & 0xff); rtc_set_memory(rtc, 0x3e, checksum & 0xff); @@ -675,6 +675,11 @@ static void ibm_40p_init(MachineState *machine) qdev_prop_set_uint32(dev, "ram-size", machine->ram_size); qdev_init_nofail(dev); + /* RTC */ + dev = DEVICE(isa_create(isa_bus, TYPE_MC146818_RTC)); + qdev_prop_set_int32(dev, "base_year", 1900); + qdev_init_nofail(dev); + /* initialize CMOS checksums */ cmos_checksum = 0x6aa9; qbus_walk_children(BUS(isa_bus), prep_set_cmos_checksum, NULL, NULL, NULL, diff --git a/hw/ppc/spapr.c b/hw/ppc/spapr.c index 2ef3ce4362..e2b33e5890 100644 --- a/hw/ppc/spapr.c +++ b/hw/ppc/spapr.c @@ -500,7 +500,10 @@ static void spapr_populate_cpu_dt(CPUState *cs, void *fdt, int offset, _FDT((fdt_setprop(fdt, offset, "64-bit", NULL, 0))); if (env->spr_cb[SPR_PURR].oea_read) { - _FDT((fdt_setprop(fdt, offset, "ibm,purr", NULL, 0))); + _FDT((fdt_setprop_cell(fdt, offset, "ibm,purr", 1))); + } + if (env->spr_cb[SPR_SPURR].oea_read) { + _FDT((fdt_setprop_cell(fdt, offset, "ibm,spurr", 1))); } if (ppc_hash64_has(cpu, PPC_HASH64_1TSEG)) { @@ -2122,6 +2125,7 @@ static const VMStateDescription vmstate_spapr = { &vmstate_spapr_cap_cfpc, &vmstate_spapr_cap_sbbc, &vmstate_spapr_cap_ibs, + &vmstate_spapr_cap_hpt_maxpagesize, &vmstate_spapr_irq_map, &vmstate_spapr_cap_nested_kvm_hv, &vmstate_spapr_dtb, @@ -4348,7 +4352,7 @@ static void spapr_machine_class_init(ObjectClass *oc, void *data) smc->default_caps.caps[SPAPR_CAP_LARGE_DECREMENTER] = SPAPR_CAP_ON; smc->default_caps.caps[SPAPR_CAP_CCF_ASSIST] = SPAPR_CAP_OFF; spapr_caps_add_properties(smc, &error_abort); - smc->irq = &spapr_irq_xics; + smc->irq = &spapr_irq_dual; smc->dr_phb_enabled = true; } @@ -4407,18 +4411,7 @@ DEFINE_SPAPR_MACHINE(4_1, "4.1", true); /* * pseries-4.0 */ -static void spapr_machine_4_0_class_options(MachineClass *mc) -{ - spapr_machine_4_1_class_options(mc); - compat_props_add(mc->compat_props, hw_compat_4_0, hw_compat_4_0_len); -} - -DEFINE_SPAPR_MACHINE(4_0, "4.0", false); - -/* - * pseries-3.1 - */ -static void phb_placement_3_1(SpaprMachineState *spapr, uint32_t index, +static void phb_placement_4_0(SpaprMachineState *spapr, uint32_t index, uint64_t *buid, hwaddr *pio, hwaddr *mmio32, hwaddr *mmio64, unsigned n_dma, uint32_t *liobns, @@ -4430,6 +4423,22 @@ static void phb_placement_3_1(SpaprMachineState *spapr, uint32_t index, *nv2atsd = 0; } +static void spapr_machine_4_0_class_options(MachineClass *mc) +{ + SpaprMachineClass *smc = SPAPR_MACHINE_CLASS(mc); + + spapr_machine_4_1_class_options(mc); + compat_props_add(mc->compat_props, hw_compat_4_0, hw_compat_4_0_len); + smc->phb_placement = phb_placement_4_0; + smc->irq = &spapr_irq_xics; + smc->pre_4_1_migration = true; +} + +DEFINE_SPAPR_MACHINE(4_0, "4.0", false); + +/* + * pseries-3.1 + */ static void spapr_machine_3_1_class_options(MachineClass *mc) { SpaprMachineClass *smc = SPAPR_MACHINE_CLASS(mc); @@ -4445,7 +4454,6 @@ static void spapr_machine_3_1_class_options(MachineClass *mc) smc->default_caps.caps[SPAPR_CAP_SBBC] = SPAPR_CAP_BROKEN; smc->default_caps.caps[SPAPR_CAP_IBS] = SPAPR_CAP_BROKEN; smc->default_caps.caps[SPAPR_CAP_LARGE_DECREMENTER] = SPAPR_CAP_OFF; - smc->phb_placement = phb_placement_3_1; } DEFINE_SPAPR_MACHINE(3_1, "3.1", false); diff --git a/hw/ppc/spapr_caps.c b/hw/ppc/spapr_caps.c index 9b1c10baa6..31b4661399 100644 --- a/hw/ppc/spapr_caps.c +++ b/hw/ppc/spapr_caps.c @@ -64,6 +64,7 @@ typedef struct SpaprCapabilityInfo { void (*apply)(SpaprMachineState *spapr, uint8_t val, Error **errp); void (*cpu_apply)(SpaprMachineState *spapr, PowerPCCPU *cpu, uint8_t val, Error **errp); + bool (*migrate_needed)(void *opaque); } SpaprCapabilityInfo; static void spapr_cap_get_bool(Object *obj, Visitor *v, const char *name, @@ -350,6 +351,11 @@ static void cap_hpt_maxpagesize_apply(SpaprMachineState *spapr, spapr_check_pagesize(spapr, qemu_minrampagesize(), errp); } +static bool cap_hpt_maxpagesize_migrate_needed(void *opaque) +{ + return !SPAPR_MACHINE_GET_CLASS(opaque)->pre_4_1_migration; +} + static bool spapr_pagesize_cb(void *opaque, uint32_t seg_pshift, uint32_t pshift) { @@ -542,6 +548,7 @@ SpaprCapabilityInfo capability_table[SPAPR_CAP_NUM] = { .type = "int", .apply = cap_hpt_maxpagesize_apply, .cpu_apply = cap_hpt_maxpagesize_cpu_apply, + .migrate_needed = cap_hpt_maxpagesize_migrate_needed, }, [SPAPR_CAP_NESTED_KVM_HV] = { .name = "nested-hv", @@ -679,8 +686,11 @@ int spapr_caps_post_migration(SpaprMachineState *spapr) static bool spapr_cap_##sname##_needed(void *opaque) \ { \ SpaprMachineState *spapr = opaque; \ + bool (*needed)(void *opaque) = \ + capability_table[cap].migrate_needed; \ \ - return spapr->cmd_line_caps[cap] && \ + return needed ? needed(opaque) : true && \ + spapr->cmd_line_caps[cap] && \ (spapr->eff.caps[cap] != \ spapr->def.caps[cap]); \ } \ @@ -703,6 +713,7 @@ SPAPR_CAP_MIG_STATE(dfp, SPAPR_CAP_DFP); SPAPR_CAP_MIG_STATE(cfpc, SPAPR_CAP_CFPC); SPAPR_CAP_MIG_STATE(sbbc, SPAPR_CAP_SBBC); SPAPR_CAP_MIG_STATE(ibs, SPAPR_CAP_IBS); +SPAPR_CAP_MIG_STATE(hpt_maxpagesize, SPAPR_CAP_HPT_MAXPAGESIZE); SPAPR_CAP_MIG_STATE(nested_kvm_hv, SPAPR_CAP_NESTED_KVM_HV); SPAPR_CAP_MIG_STATE(large_decr, SPAPR_CAP_LARGE_DECREMENTER); SPAPR_CAP_MIG_STATE(ccf_assist, SPAPR_CAP_CCF_ASSIST); diff --git a/hw/ppc/spapr_cpu_core.c b/hw/ppc/spapr_cpu_core.c index f04e06cdf6..5621fb9a3d 100644 --- a/hw/ppc/spapr_cpu_core.c +++ b/hw/ppc/spapr_cpu_core.c @@ -58,9 +58,11 @@ static void spapr_cpu_reset(void *opaque) * * Disable Power-saving mode Exit Cause exceptions for the CPU, so * we don't get spurious wakups before an RTAS start-cpu call. + * For the same reason, set PSSCR_EC. */ lpcr &= ~(LPCR_VPM0 | LPCR_VPM1 | LPCR_ISL | LPCR_KBV | pcc->lpcr_pm); lpcr |= LPCR_LPES0 | LPCR_LPES1; + env->spr[SPR_PSSCR] |= PSSCR_EC; /* Set RMLS to the max (ie, 16G) */ lpcr &= ~LPCR_RMLS; diff --git a/hw/ppc/spapr_hcall.c b/hw/ppc/spapr_hcall.c index 6c16d2b120..0a050ad3d8 100644 --- a/hw/ppc/spapr_hcall.c +++ b/hw/ppc/spapr_hcall.c @@ -1513,6 +1513,7 @@ static target_ulong h_client_architecture_support(PowerPCCPU *cpu, bool guest_radix; Error *local_err = NULL; bool raw_mode_supported = false; + bool guest_xive; cas_pvr = cas_check_pvr(spapr, cpu, &addr, &raw_mode_supported, &local_err); if (local_err) { @@ -1545,10 +1546,17 @@ static target_ulong h_client_architecture_support(PowerPCCPU *cpu, error_report("guest requested hash and radix MMU, which is invalid."); exit(EXIT_FAILURE); } + if (spapr_ovec_test(ov5_guest, OV5_XIVE_BOTH)) { + error_report("guest requested an invalid interrupt mode"); + exit(EXIT_FAILURE); + } + /* The radix/hash bit in byte 24 requires special handling: */ guest_radix = spapr_ovec_test(ov5_guest, OV5_MMU_RADIX_300); spapr_ovec_clear(ov5_guest, OV5_MMU_RADIX_300); + guest_xive = spapr_ovec_test(ov5_guest, OV5_XIVE_EXPLOIT); + /* * HPT resizing is a bit of a special case, because when enabled * we assume an HPT guest will support it until it says it @@ -1633,6 +1641,24 @@ static target_ulong h_client_architecture_support(PowerPCCPU *cpu, } /* + * Ensure the guest asks for an interrupt mode we support; otherwise + * terminate the boot. + */ + if (guest_xive) { + if (spapr->irq->ov5 == SPAPR_OV5_XIVE_LEGACY) { + error_report( +"Guest requested unavailable interrupt mode (XIVE), try the ic-mode=xive or ic-mode=dual machine property"); + exit(EXIT_FAILURE); + } + } else { + if (spapr->irq->ov5 == SPAPR_OV5_XIVE_EXPLOIT) { + error_report( +"Guest requested unavailable interrupt mode (XICS), either don't set the ic-mode machine property or try ic-mode=xics or ic-mode=dual"); + exit(EXIT_FAILURE); + } + } + + /* * Generate a machine reset when we have an update of the * interrupt mode. Only required when the machine supports both * modes. diff --git a/hw/ppc/spapr_irq.c b/hw/ppc/spapr_irq.c index b1f79ea9de..3156daf093 100644 --- a/hw/ppc/spapr_irq.c +++ b/hw/ppc/spapr_irq.c @@ -62,38 +62,46 @@ void spapr_irq_msi_reset(SpaprMachineState *spapr) bitmap_clear(spapr->irq_map, 0, spapr->irq_map_nr); } - -/* - * XICS IRQ backend. - */ - -static void spapr_irq_init_xics(SpaprMachineState *spapr, int nr_irqs, - Error **errp) +static void spapr_irq_init_device(SpaprMachineState *spapr, + SpaprIrq *irq, Error **errp) { MachineState *machine = MACHINE(spapr); - Object *obj; Error *local_err = NULL; - bool xics_kvm = false; - if (kvm_enabled()) { - if (machine_kernel_irqchip_allowed(machine) && - !xics_kvm_init(spapr, &local_err)) { - xics_kvm = true; - } - if (machine_kernel_irqchip_required(machine) && !xics_kvm) { + if (kvm_enabled() && machine_kernel_irqchip_allowed(machine)) { + irq->init_kvm(spapr, &local_err); + if (local_err && machine_kernel_irqchip_required(machine)) { error_prepend(&local_err, "kernel_irqchip requested but unavailable: "); error_propagate(errp, local_err); return; } - error_free(local_err); - local_err = NULL; - } - if (!xics_kvm) { - xics_spapr_init(spapr); + if (!local_err) { + return; + } + + /* + * We failed to initialize the KVM device, fallback to + * emulated mode + */ + error_prepend(&local_err, "kernel_irqchip allowed but unavailable: "); + warn_report_err(local_err); } + irq->init_emu(spapr, errp); +} + +/* + * XICS IRQ backend. + */ + +static void spapr_irq_init_xics(SpaprMachineState *spapr, int nr_irqs, + Error **errp) +{ + Object *obj; + Error *local_err = NULL; + obj = object_new(TYPE_ICS_SIMPLE); object_property_add_child(OBJECT(spapr), "ics", obj, &error_abort); object_property_add_const_link(obj, ICS_PROP_XICS, OBJECT(spapr), @@ -212,7 +220,13 @@ static void spapr_irq_set_irq_xics(void *opaque, int srcno, int val) static void spapr_irq_reset_xics(SpaprMachineState *spapr, Error **errp) { - /* TODO: create the KVM XICS device */ + Error *local_err = NULL; + + spapr_irq_init_device(spapr, &spapr_irq_xics, &local_err); + if (local_err) { + error_propagate(errp, local_err); + return; + } } static const char *spapr_irq_get_nodename_xics(SpaprMachineState *spapr) @@ -220,6 +234,18 @@ static const char *spapr_irq_get_nodename_xics(SpaprMachineState *spapr) return XICS_NODENAME; } +static void spapr_irq_init_emu_xics(SpaprMachineState *spapr, Error **errp) +{ + xics_spapr_init(spapr); +} + +static void spapr_irq_init_kvm_xics(SpaprMachineState *spapr, Error **errp) +{ + if (kvm_enabled()) { + xics_kvm_init(spapr, errp); + } +} + #define SPAPR_IRQ_XICS_NR_IRQS 0x1000 #define SPAPR_IRQ_XICS_NR_MSIS \ (XICS_IRQ_BASE + SPAPR_IRQ_XICS_NR_IRQS - SPAPR_IRQ_MSI) @@ -240,6 +266,8 @@ SpaprIrq spapr_irq_xics = { .reset = spapr_irq_reset_xics, .set_irq = spapr_irq_set_irq_xics, .get_nodename = spapr_irq_get_nodename_xics, + .init_emu = spapr_irq_init_emu_xics, + .init_kvm = spapr_irq_init_kvm_xics, }; /* @@ -248,19 +276,10 @@ SpaprIrq spapr_irq_xics = { static void spapr_irq_init_xive(SpaprMachineState *spapr, int nr_irqs, Error **errp) { - MachineState *machine = MACHINE(spapr); uint32_t nr_servers = spapr_max_server_number(spapr); DeviceState *dev; int i; - /* KVM XIVE device not yet available */ - if (kvm_enabled()) { - if (machine_kernel_irqchip_required(machine)) { - error_setg(errp, "kernel_irqchip requested. no KVM XIVE support"); - return; - } - } - dev = qdev_create(NULL, TYPE_SPAPR_XIVE); qdev_prop_set_uint32(dev, "nr-irqs", nr_irqs); /* @@ -350,12 +369,13 @@ static void spapr_irq_cpu_intc_create_xive(SpaprMachineState *spapr, static int spapr_irq_post_load_xive(SpaprMachineState *spapr, int version_id) { - return 0; + return spapr_xive_post_load(spapr->xive, version_id); } static void spapr_irq_reset_xive(SpaprMachineState *spapr, Error **errp) { CPUState *cs; + Error *local_err = NULL; CPU_FOREACH(cs) { PowerPCCPU *cpu = POWERPC_CPU(cs); @@ -364,6 +384,12 @@ static void spapr_irq_reset_xive(SpaprMachineState *spapr, Error **errp) spapr_xive_set_tctx_os_cam(spapr_cpu_state(cpu)->tctx); } + spapr_irq_init_device(spapr, &spapr_irq_xive, &local_err); + if (local_err) { + error_propagate(errp, local_err); + return; + } + /* Activate the XIVE MMIOs */ spapr_xive_mmio_set_enabled(spapr->xive, true); } @@ -372,7 +398,11 @@ static void spapr_irq_set_irq_xive(void *opaque, int srcno, int val) { SpaprMachineState *spapr = opaque; - xive_source_set_irq(&spapr->xive->source, srcno, val); + if (kvm_irqchip_in_kernel()) { + kvmppc_xive_source_set_irq(&spapr->xive->source, srcno, val); + } else { + xive_source_set_irq(&spapr->xive->source, srcno, val); + } } static const char *spapr_irq_get_nodename_xive(SpaprMachineState *spapr) @@ -380,6 +410,18 @@ static const char *spapr_irq_get_nodename_xive(SpaprMachineState *spapr) return spapr->xive->nodename; } +static void spapr_irq_init_emu_xive(SpaprMachineState *spapr, Error **errp) +{ + spapr_xive_init(spapr->xive, errp); +} + +static void spapr_irq_init_kvm_xive(SpaprMachineState *spapr, Error **errp) +{ + if (kvm_enabled()) { + kvmppc_xive_connect(spapr->xive, errp); + } +} + /* * XIVE uses the full IRQ number space. Set it to 8K to be compatible * with XICS. @@ -404,6 +446,8 @@ SpaprIrq spapr_irq_xive = { .reset = spapr_irq_reset_xive, .set_irq = spapr_irq_set_irq_xive, .get_nodename = spapr_irq_get_nodename_xive, + .init_emu = spapr_irq_init_emu_xive, + .init_kvm = spapr_irq_init_kvm_xive, }; /* @@ -428,14 +472,8 @@ static SpaprIrq *spapr_irq_current(SpaprMachineState *spapr) static void spapr_irq_init_dual(SpaprMachineState *spapr, int nr_irqs, Error **errp) { - MachineState *machine = MACHINE(spapr); Error *local_err = NULL; - if (kvm_enabled() && machine_kernel_irqchip_allowed(machine)) { - error_setg(errp, "No KVM support for the 'dual' machine"); - return; - } - spapr_irq_xics.init(spapr, spapr_irq_xics.nr_irqs, &local_err); if (local_err) { error_propagate(errp, local_err); @@ -514,6 +552,9 @@ static int spapr_irq_post_load_dual(SpaprMachineState *spapr, int version_id) * defaults to XICS at startup. */ if (spapr_ovec_test(spapr->ov5_cas, OV5_XIVE_EXPLOIT)) { + if (kvm_irqchip_in_kernel()) { + xics_kvm_disconnect(spapr, &error_fatal); + } spapr_irq_xive.reset(spapr, &error_fatal); } @@ -522,12 +563,30 @@ static int spapr_irq_post_load_dual(SpaprMachineState *spapr, int version_id) static void spapr_irq_reset_dual(SpaprMachineState *spapr, Error **errp) { + Error *local_err = NULL; + /* * Deactivate the XIVE MMIOs. The XIVE backend will reenable them * if selected. */ spapr_xive_mmio_set_enabled(spapr->xive, false); + /* Destroy all KVM devices */ + if (kvm_irqchip_in_kernel()) { + xics_kvm_disconnect(spapr, &local_err); + if (local_err) { + error_propagate(errp, local_err); + error_prepend(errp, "KVM XICS disconnect failed: "); + return; + } + kvmppc_xive_disconnect(spapr->xive, &local_err); + if (local_err) { + error_propagate(errp, local_err); + error_prepend(errp, "KVM XIVE disconnect failed: "); + return; + } + } + spapr_irq_current(spapr)->reset(spapr, errp); } @@ -565,6 +624,8 @@ SpaprIrq spapr_irq_dual = { .reset = spapr_irq_reset_dual, .set_irq = spapr_irq_set_irq_dual, .get_nodename = spapr_irq_get_nodename_dual, + .init_emu = NULL, /* should not be used */ + .init_kvm = NULL, /* should not be used */ }; @@ -763,6 +824,9 @@ SpaprIrq spapr_irq_xics_legacy = { .dt_populate = spapr_dt_xics, .cpu_intc_create = spapr_irq_cpu_intc_create_xics, .post_load = spapr_irq_post_load_xics, + .reset = spapr_irq_reset_xics, .set_irq = spapr_irq_set_irq_xics, .get_nodename = spapr_irq_get_nodename_xics, + .init_emu = spapr_irq_init_emu_xics, + .init_kvm = spapr_irq_init_kvm_xics, }; diff --git a/hw/ppc/spapr_pci.c b/hw/ppc/spapr_pci.c index 97961b0128..9cf2c41b8c 100644 --- a/hw/ppc/spapr_pci.c +++ b/hw/ppc/spapr_pci.c @@ -1626,28 +1626,6 @@ static void spapr_phb_unrealize(DeviceState *dev, Error **errp) memory_region_del_subregion(get_system_memory(), &sphb->mem32window); } -static bool spapr_phb_allows_extended_config_space(PCIBus *bus) -{ - SpaprPhbState *sphb = SPAPR_PCI_HOST_BRIDGE(BUS(bus)->parent); - - return sphb->pcie_ecs; -} - -static void spapr_phb_root_bus_class_init(ObjectClass *klass, void *data) -{ - PCIBusClass *pbc = PCI_BUS_CLASS(klass); - - pbc->allows_extended_config_space = spapr_phb_allows_extended_config_space; -} - -#define TYPE_SPAPR_PHB_ROOT_BUS "pci" - -static const TypeInfo spapr_phb_root_bus_info = { - .name = TYPE_SPAPR_PHB_ROOT_BUS, - .parent = TYPE_PCI_BUS, - .class_init = spapr_phb_root_bus_class_init, -}; - static void spapr_phb_realize(DeviceState *dev, Error **errp) { /* We don't use SPAPR_MACHINE() in order to exit gracefully if the user @@ -1753,7 +1731,16 @@ static void spapr_phb_realize(DeviceState *dev, Error **errp) pci_spapr_set_irq, pci_swizzle_map_irq_fn, sphb, &sphb->memspace, &sphb->iospace, PCI_DEVFN(0, 0), PCI_NUM_PINS, - TYPE_SPAPR_PHB_ROOT_BUS); + TYPE_PCI_BUS); + + /* + * Despite resembling a vanilla PCI bus in most ways, the PAPR + * para-virtualized PCI bus *does* permit PCI-E extended config + * space access + */ + if (sphb->pcie_ecs) { + bus->flags |= PCI_BUS_EXTENDED_CONFIG_SPACE; + } phb->bus = bus; qbus_set_hotplug_handler(BUS(phb->bus), OBJECT(sphb), NULL); @@ -2348,7 +2335,6 @@ void spapr_pci_rtas_init(void) static void spapr_pci_register_types(void) { type_register_static(&spapr_phb_info); - type_register_static(&spapr_phb_root_bus_info); } type_init(spapr_pci_register_types) diff --git a/hw/ppc/spapr_rtas.c b/hw/ppc/spapr_rtas.c index ee24212765..5bc1a93271 100644 --- a/hw/ppc/spapr_rtas.c +++ b/hw/ppc/spapr_rtas.c @@ -177,6 +177,7 @@ static void rtas_start_cpu(PowerPCCPU *callcpu, SpaprMachineState *spapr, } else { lpcr &= ~(LPCR_UPRT | LPCR_GTSE | LPCR_HR); } + env->spr[SPR_PSSCR] &= ~PSSCR_EC; } ppc_store_lpcr(newcpu, lpcr); @@ -205,8 +206,11 @@ static void rtas_stop_self(PowerPCCPU *cpu, SpaprMachineState *spapr, /* Disable Power-saving mode Exit Cause exceptions for the CPU. * This could deliver an interrupt on a dying CPU and crash the - * guest */ + * guest. + * For the same reason, set PSSCR_EC. + */ ppc_store_lpcr(cpu, env->spr[SPR_LPCR] & ~pcc->lpcr_pm); + env->spr[SPR_PSSCR] |= PSSCR_EC; cs->halted = 1; kvmppc_set_reg_ppc_online(cpu, 0); qemu_cpu_kick(cs); diff --git a/hw/rdma/rdma_backend.c b/hw/rdma/rdma_backend.c index cf34874e9d..c39051068d 100644 --- a/hw/rdma/rdma_backend.c +++ b/hw/rdma/rdma_backend.c @@ -14,16 +14,9 @@ */ #include "qemu/osdep.h" -#include "sysemu/sysemu.h" -#include "qapi/error.h" -#include "qapi/qmp/qlist.h" -#include "qapi/qmp/qnum.h" #include "qapi/qapi-events-rdma.h" #include <infiniband/verbs.h> -#include <infiniband/umad_types.h> -#include <infiniband/umad.h> -#include <rdma/rdma_user_cm.h> #include "contrib/rdmacm-mux/rdmacm-mux.h" #include "trace.h" diff --git a/hw/riscv/Makefile.objs b/hw/riscv/Makefile.objs index 79bfb3abf9..a65027304a 100644 --- a/hw/riscv/Makefile.objs +++ b/hw/riscv/Makefile.objs @@ -2,6 +2,7 @@ obj-$(CONFIG_SPIKE) += riscv_htif.o obj-$(CONFIG_HART) += riscv_hart.o obj-$(CONFIG_SIFIVE_E) += sifive_e.o obj-$(CONFIG_SIFIVE) += sifive_clint.o +obj-$(CONFIG_SIFIVE) += sifive_gpio.o obj-$(CONFIG_SIFIVE) += sifive_prci.o obj-$(CONFIG_SIFIVE) += sifive_plic.o obj-$(CONFIG_SIFIVE) += sifive_test.o diff --git a/hw/riscv/sifive_e.c b/hw/riscv/sifive_e.c index b1cd11363c..80ac56fa7d 100644 --- a/hw/riscv/sifive_e.c +++ b/hw/riscv/sifive_e.c @@ -146,11 +146,15 @@ static void riscv_sifive_e_soc_init(Object *obj) &error_abort); object_property_set_int(OBJECT(&s->cpus), smp_cpus, "num-harts", &error_abort); + sysbus_init_child_obj(obj, "riscv.sifive.e.gpio0", + &s->gpio, sizeof(s->gpio), + TYPE_SIFIVE_GPIO); } static void riscv_sifive_e_soc_realize(DeviceState *dev, Error **errp) { const struct MemmapEntry *memmap = sifive_e_memmap; + Error *err = NULL; SiFiveESoCState *s = RISCV_E_SOC(dev); MemoryRegion *sys_mem = get_system_memory(); @@ -184,8 +188,28 @@ static void riscv_sifive_e_soc_realize(DeviceState *dev, Error **errp) sifive_mmio_emulate(sys_mem, "riscv.sifive.e.aon", memmap[SIFIVE_E_AON].base, memmap[SIFIVE_E_AON].size); sifive_prci_create(memmap[SIFIVE_E_PRCI].base); - sifive_mmio_emulate(sys_mem, "riscv.sifive.e.gpio0", - memmap[SIFIVE_E_GPIO0].base, memmap[SIFIVE_E_GPIO0].size); + + /* GPIO */ + + object_property_set_bool(OBJECT(&s->gpio), true, "realized", &err); + if (err) { + error_propagate(errp, err); + return; + } + + /* Map GPIO registers */ + sysbus_mmio_map(SYS_BUS_DEVICE(&s->gpio), 0, memmap[SIFIVE_E_GPIO0].base); + + /* Pass all GPIOs to the SOC layer so they are available to the board */ + qdev_pass_gpios(DEVICE(&s->gpio), dev, NULL); + + /* Connect GPIO interrupts to the PLIC */ + for (int i = 0; i < 32; i++) { + sysbus_connect_irq(SYS_BUS_DEVICE(&s->gpio), i, + qdev_get_gpio_in(DEVICE(s->plic), + SIFIVE_E_GPIO0_IRQ0 + i)); + } + sifive_uart_create(sys_mem, memmap[SIFIVE_E_UART0].base, serial_hd(0), qdev_get_gpio_in(DEVICE(s->plic), SIFIVE_E_UART0_IRQ)); sifive_mmio_emulate(sys_mem, "riscv.sifive.e.qspi0", diff --git a/hw/riscv/sifive_gpio.c b/hw/riscv/sifive_gpio.c new file mode 100644 index 0000000000..06bd8112d7 --- /dev/null +++ b/hw/riscv/sifive_gpio.c @@ -0,0 +1,388 @@ +/* + * sifive System-on-Chip general purpose input/output register definition + * + * Copyright 2019 AdaCore + * + * Base on nrf51_gpio.c: + * + * Copyright 2018 Steffen Görtz <contrib@steffen-goertz.de> + * + * This code is licensed under the GPL version 2 or later. See + * the COPYING file in the top-level directory. + */ + +#include "qemu/osdep.h" +#include "qemu/log.h" +#include "hw/riscv/sifive_gpio.h" +#include "trace.h" + +static void update_output_irq(SIFIVEGPIOState *s) +{ + + uint32_t pending; + uint32_t pin; + + pending = s->high_ip & s->high_ie; + pending |= s->low_ip & s->low_ie; + pending |= s->rise_ip & s->rise_ie; + pending |= s->fall_ip & s->fall_ie; + + for (int i = 0; i < SIFIVE_GPIO_PINS; i++) { + pin = 1 << i; + qemu_set_irq(s->irq[i], (pending & pin) != 0); + trace_sifive_gpio_update_output_irq(i, (pending & pin) != 0); + } +} + +static void update_state(SIFIVEGPIOState *s) +{ + size_t i; + bool prev_ival, in, in_mask, port, out_xor, pull, output_en, input_en, + rise_ip, fall_ip, low_ip, high_ip, oval, actual_value, ival; + + for (i = 0; i < SIFIVE_GPIO_PINS; i++) { + + prev_ival = extract32(s->value, i, 1); + in = extract32(s->in, i, 1); + in_mask = extract32(s->in_mask, i, 1); + port = extract32(s->port, i, 1); + out_xor = extract32(s->out_xor, i, 1); + pull = extract32(s->pue, i, 1); + output_en = extract32(s->output_en, i, 1); + input_en = extract32(s->input_en, i, 1); + rise_ip = extract32(s->rise_ip, i, 1); + fall_ip = extract32(s->fall_ip, i, 1); + low_ip = extract32(s->low_ip, i, 1); + high_ip = extract32(s->high_ip, i, 1); + + /* Output value (IOF not supported) */ + oval = output_en && (port ^ out_xor); + + /* Pin both driven externally and internally */ + if (output_en && in_mask) { + qemu_log_mask(LOG_GUEST_ERROR, "GPIO pin %zu short circuited\n", i); + } + + if (in_mask) { + /* The pin is driven by external device */ + actual_value = in; + } else if (output_en) { + /* The pin is driven by internal circuit */ + actual_value = oval; + } else { + /* Floating? Apply pull-up resistor */ + actual_value = pull; + } + + qemu_set_irq(s->output[i], actual_value); + + /* Input value */ + ival = input_en && actual_value; + + /* Interrupts */ + high_ip = high_ip || ival; + s->high_ip = deposit32(s->high_ip, i, 1, high_ip); + + low_ip = low_ip || !ival; + s->low_ip = deposit32(s->low_ip, i, 1, low_ip); + + rise_ip = rise_ip || (ival && !prev_ival); + s->rise_ip = deposit32(s->rise_ip, i, 1, rise_ip); + + fall_ip = fall_ip || (!ival && prev_ival); + s->fall_ip = deposit32(s->fall_ip, i, 1, fall_ip); + + /* Update value */ + s->value = deposit32(s->value, i, 1, ival); + } + update_output_irq(s); +} + +static uint64_t sifive_gpio_read(void *opaque, hwaddr offset, unsigned int size) +{ + SIFIVEGPIOState *s = SIFIVE_GPIO(opaque); + uint64_t r = 0; + + switch (offset) { + case SIFIVE_GPIO_REG_VALUE: + r = s->value; + break; + + case SIFIVE_GPIO_REG_INPUT_EN: + r = s->input_en; + break; + + case SIFIVE_GPIO_REG_OUTPUT_EN: + r = s->output_en; + break; + + case SIFIVE_GPIO_REG_PORT: + r = s->port; + break; + + case SIFIVE_GPIO_REG_PUE: + r = s->pue; + break; + + case SIFIVE_GPIO_REG_DS: + r = s->ds; + break; + + case SIFIVE_GPIO_REG_RISE_IE: + r = s->rise_ie; + break; + + case SIFIVE_GPIO_REG_RISE_IP: + r = s->rise_ip; + break; + + case SIFIVE_GPIO_REG_FALL_IE: + r = s->fall_ie; + break; + + case SIFIVE_GPIO_REG_FALL_IP: + r = s->fall_ip; + break; + + case SIFIVE_GPIO_REG_HIGH_IE: + r = s->high_ie; + break; + + case SIFIVE_GPIO_REG_HIGH_IP: + r = s->high_ip; + break; + + case SIFIVE_GPIO_REG_LOW_IE: + r = s->low_ie; + break; + + case SIFIVE_GPIO_REG_LOW_IP: + r = s->low_ip; + break; + + case SIFIVE_GPIO_REG_IOF_EN: + r = s->iof_en; + break; + + case SIFIVE_GPIO_REG_IOF_SEL: + r = s->iof_sel; + break; + + case SIFIVE_GPIO_REG_OUT_XOR: + r = s->out_xor; + break; + + default: + qemu_log_mask(LOG_GUEST_ERROR, + "%s: bad read offset 0x%" HWADDR_PRIx "\n", + __func__, offset); + } + + trace_sifive_gpio_read(offset, r); + + return r; +} + +static void sifive_gpio_write(void *opaque, hwaddr offset, + uint64_t value, unsigned int size) +{ + SIFIVEGPIOState *s = SIFIVE_GPIO(opaque); + + trace_sifive_gpio_write(offset, value); + + switch (offset) { + + case SIFIVE_GPIO_REG_INPUT_EN: + s->input_en = value; + break; + + case SIFIVE_GPIO_REG_OUTPUT_EN: + s->output_en = value; + break; + + case SIFIVE_GPIO_REG_PORT: + s->port = value; + break; + + case SIFIVE_GPIO_REG_PUE: + s->pue = value; + break; + + case SIFIVE_GPIO_REG_DS: + s->ds = value; + break; + + case SIFIVE_GPIO_REG_RISE_IE: + s->rise_ie = value; + break; + + case SIFIVE_GPIO_REG_RISE_IP: + /* Write 1 to clear */ + s->rise_ip &= ~value; + break; + + case SIFIVE_GPIO_REG_FALL_IE: + s->fall_ie = value; + break; + + case SIFIVE_GPIO_REG_FALL_IP: + /* Write 1 to clear */ + s->fall_ip &= ~value; + break; + + case SIFIVE_GPIO_REG_HIGH_IE: + s->high_ie = value; + break; + + case SIFIVE_GPIO_REG_HIGH_IP: + /* Write 1 to clear */ + s->high_ip &= ~value; + break; + + case SIFIVE_GPIO_REG_LOW_IE: + s->low_ie = value; + break; + + case SIFIVE_GPIO_REG_LOW_IP: + /* Write 1 to clear */ + s->low_ip &= ~value; + break; + + case SIFIVE_GPIO_REG_IOF_EN: + s->iof_en = value; + break; + + case SIFIVE_GPIO_REG_IOF_SEL: + s->iof_sel = value; + break; + + case SIFIVE_GPIO_REG_OUT_XOR: + s->out_xor = value; + break; + + default: + qemu_log_mask(LOG_GUEST_ERROR, + "%s: bad write offset 0x%" HWADDR_PRIx "\n", + __func__, offset); + } + + update_state(s); +} + +static const MemoryRegionOps gpio_ops = { + .read = sifive_gpio_read, + .write = sifive_gpio_write, + .endianness = DEVICE_LITTLE_ENDIAN, + .impl.min_access_size = 4, + .impl.max_access_size = 4, +}; + +static void sifive_gpio_set(void *opaque, int line, int value) +{ + SIFIVEGPIOState *s = SIFIVE_GPIO(opaque); + + trace_sifive_gpio_set(line, value); + + assert(line >= 0 && line < SIFIVE_GPIO_PINS); + + s->in_mask = deposit32(s->in_mask, line, 1, value >= 0); + if (value >= 0) { + s->in = deposit32(s->in, line, 1, value != 0); + } + + update_state(s); +} + +static void sifive_gpio_reset(DeviceState *dev) +{ + SIFIVEGPIOState *s = SIFIVE_GPIO(dev); + + s->value = 0; + s->input_en = 0; + s->output_en = 0; + s->port = 0; + s->pue = 0; + s->ds = 0; + s->rise_ie = 0; + s->rise_ip = 0; + s->fall_ie = 0; + s->fall_ip = 0; + s->high_ie = 0; + s->high_ip = 0; + s->low_ie = 0; + s->low_ip = 0; + s->iof_en = 0; + s->iof_sel = 0; + s->out_xor = 0; + s->in = 0; + s->in_mask = 0; + +} + +static const VMStateDescription vmstate_sifive_gpio = { + .name = TYPE_SIFIVE_GPIO, + .version_id = 1, + .minimum_version_id = 1, + .fields = (VMStateField[]) { + VMSTATE_UINT32(value, SIFIVEGPIOState), + VMSTATE_UINT32(input_en, SIFIVEGPIOState), + VMSTATE_UINT32(output_en, SIFIVEGPIOState), + VMSTATE_UINT32(port, SIFIVEGPIOState), + VMSTATE_UINT32(pue, SIFIVEGPIOState), + VMSTATE_UINT32(rise_ie, SIFIVEGPIOState), + VMSTATE_UINT32(rise_ip, SIFIVEGPIOState), + VMSTATE_UINT32(fall_ie, SIFIVEGPIOState), + VMSTATE_UINT32(fall_ip, SIFIVEGPIOState), + VMSTATE_UINT32(high_ie, SIFIVEGPIOState), + VMSTATE_UINT32(high_ip, SIFIVEGPIOState), + VMSTATE_UINT32(low_ie, SIFIVEGPIOState), + VMSTATE_UINT32(low_ip, SIFIVEGPIOState), + VMSTATE_UINT32(iof_en, SIFIVEGPIOState), + VMSTATE_UINT32(iof_sel, SIFIVEGPIOState), + VMSTATE_UINT32(out_xor, SIFIVEGPIOState), + VMSTATE_UINT32(in, SIFIVEGPIOState), + VMSTATE_UINT32(in_mask, SIFIVEGPIOState), + VMSTATE_END_OF_LIST() + } +}; + +static void sifive_gpio_init(Object *obj) +{ + SIFIVEGPIOState *s = SIFIVE_GPIO(obj); + + memory_region_init_io(&s->mmio, obj, &gpio_ops, s, + TYPE_SIFIVE_GPIO, SIFIVE_GPIO_SIZE); + sysbus_init_mmio(SYS_BUS_DEVICE(obj), &s->mmio); + + + for (int i = 0; i < SIFIVE_GPIO_PINS; i++) { + sysbus_init_irq(SYS_BUS_DEVICE(obj), &s->irq[i]); + } + + qdev_init_gpio_in(DEVICE(s), sifive_gpio_set, SIFIVE_GPIO_PINS); + qdev_init_gpio_out(DEVICE(s), s->output, SIFIVE_GPIO_PINS); +} + +static void sifive_gpio_class_init(ObjectClass *klass, void *data) +{ + DeviceClass *dc = DEVICE_CLASS(klass); + + dc->vmsd = &vmstate_sifive_gpio; + dc->reset = sifive_gpio_reset; + dc->desc = "sifive GPIO"; +} + +static const TypeInfo sifive_gpio_info = { + .name = TYPE_SIFIVE_GPIO, + .parent = TYPE_SYS_BUS_DEVICE, + .instance_size = sizeof(SIFIVEGPIOState), + .instance_init = sifive_gpio_init, + .class_init = sifive_gpio_class_init +}; + +static void sifive_gpio_register_types(void) +{ + type_register_static(&sifive_gpio_info); +} + +type_init(sifive_gpio_register_types) diff --git a/hw/riscv/spike.c b/hw/riscv/spike.c index 2a000a5800..5b33d4be3b 100644 --- a/hw/riscv/spike.c +++ b/hw/riscv/spike.c @@ -39,6 +39,7 @@ #include "chardev/char.h" #include "sysemu/arch_init.h" #include "sysemu/device_tree.h" +#include "sysemu/qtest.h" #include "exec/address-spaces.h" #include "elf.h" @@ -160,7 +161,89 @@ static void create_fdt(SpikeState *s, const struct MemmapEntry *memmap, qemu_fdt_add_subnode(fdt, "/chosen"); qemu_fdt_setprop_string(fdt, "/chosen", "bootargs", cmdline); } - } +} + +static void spike_board_init(MachineState *machine) +{ + const struct MemmapEntry *memmap = spike_memmap; + + SpikeState *s = g_new0(SpikeState, 1); + MemoryRegion *system_memory = get_system_memory(); + MemoryRegion *main_mem = g_new(MemoryRegion, 1); + MemoryRegion *mask_rom = g_new(MemoryRegion, 1); + int i; + + /* Initialize SOC */ + object_initialize_child(OBJECT(machine), "soc", &s->soc, sizeof(s->soc), + TYPE_RISCV_HART_ARRAY, &error_abort, NULL); + object_property_set_str(OBJECT(&s->soc), machine->cpu_type, "cpu-type", + &error_abort); + object_property_set_int(OBJECT(&s->soc), smp_cpus, "num-harts", + &error_abort); + object_property_set_bool(OBJECT(&s->soc), true, "realized", + &error_abort); + + /* register system main memory (actual RAM) */ + memory_region_init_ram(main_mem, NULL, "riscv.spike.ram", + machine->ram_size, &error_fatal); + memory_region_add_subregion(system_memory, memmap[SPIKE_DRAM].base, + main_mem); + + /* create device tree */ + create_fdt(s, memmap, machine->ram_size, machine->kernel_cmdline); + + /* boot rom */ + memory_region_init_rom(mask_rom, NULL, "riscv.spike.mrom", + memmap[SPIKE_MROM].size, &error_fatal); + memory_region_add_subregion(system_memory, memmap[SPIKE_MROM].base, + mask_rom); + + if (machine->kernel_filename) { + load_kernel(machine->kernel_filename); + } + + /* reset vector */ + uint32_t reset_vec[8] = { + 0x00000297, /* 1: auipc t0, %pcrel_hi(dtb) */ + 0x02028593, /* addi a1, t0, %pcrel_lo(1b) */ + 0xf1402573, /* csrr a0, mhartid */ +#if defined(TARGET_RISCV32) + 0x0182a283, /* lw t0, 24(t0) */ +#elif defined(TARGET_RISCV64) + 0x0182b283, /* ld t0, 24(t0) */ +#endif + 0x00028067, /* jr t0 */ + 0x00000000, + memmap[SPIKE_DRAM].base, /* start: .dword DRAM_BASE */ + 0x00000000, + /* dtb: */ + }; + + /* copy in the reset vector in little_endian byte order */ + for (i = 0; i < sizeof(reset_vec) >> 2; i++) { + reset_vec[i] = cpu_to_le32(reset_vec[i]); + } + rom_add_blob_fixed_as("mrom.reset", reset_vec, sizeof(reset_vec), + memmap[SPIKE_MROM].base, &address_space_memory); + + /* copy in the device tree */ + if (fdt_pack(s->fdt) || fdt_totalsize(s->fdt) > + memmap[SPIKE_MROM].size - sizeof(reset_vec)) { + error_report("not enough space to store device-tree"); + exit(1); + } + qemu_fdt_dumpdtb(s->fdt, fdt_totalsize(s->fdt)); + rom_add_blob_fixed_as("mrom.fdt", s->fdt, fdt_totalsize(s->fdt), + memmap[SPIKE_MROM].base + sizeof(reset_vec), + &address_space_memory); + + /* initialize HTIF using symbols found in load_kernel */ + htif_mm_init(system_memory, mask_rom, &s->soc.harts[0].env, serial_hd(0)); + + /* Core Local Interruptor (timer and IPI) */ + sifive_clint_create(memmap[SPIKE_CLINT].base, memmap[SPIKE_CLINT].size, + smp_cpus, SIFIVE_SIP_BASE, SIFIVE_TIMECMP_BASE, SIFIVE_TIME_BASE); +} static void spike_v1_10_0_board_init(MachineState *machine) { @@ -172,6 +255,12 @@ static void spike_v1_10_0_board_init(MachineState *machine) MemoryRegion *mask_rom = g_new(MemoryRegion, 1); int i; + if (!qtest_enabled()) { + info_report("The Spike v1.10.0 machine has been deprecated. " + "Please use the generic spike machine and specify the ISA " + "versions using -cpu."); + } + /* Initialize SOC */ object_initialize_child(OBJECT(machine), "soc", &s->soc, sizeof(s->soc), TYPE_RISCV_HART_ARRAY, &error_abort, NULL); @@ -254,6 +343,12 @@ static void spike_v1_09_1_board_init(MachineState *machine) MemoryRegion *mask_rom = g_new(MemoryRegion, 1); int i; + if (!qtest_enabled()) { + info_report("The Spike v1.09.1 machine has been deprecated. " + "Please use the generic spike machine and specify the ISA " + "versions using -cpu."); + } + /* Initialize SOC */ object_initialize_child(OBJECT(machine), "soc", &s->soc, sizeof(s->soc), TYPE_RISCV_HART_ARRAY, &error_abort, NULL); @@ -359,8 +454,17 @@ static void spike_v1_10_0_machine_init(MachineClass *mc) mc->desc = "RISC-V Spike Board (Privileged ISA v1.10)"; mc->init = spike_v1_10_0_board_init; mc->max_cpus = 1; +} + +static void spike_machine_init(MachineClass *mc) +{ + mc->desc = "RISC-V Spike Board"; + mc->init = spike_board_init; + mc->max_cpus = 1; mc->is_default = 1; + mc->default_cpu_type = SPIKE_V1_10_0_CPU; } DEFINE_MACHINE("spike_v1.9.1", spike_v1_09_1_machine_init) DEFINE_MACHINE("spike_v1.10", spike_v1_10_0_machine_init) +DEFINE_MACHINE("spike", spike_machine_init) diff --git a/hw/riscv/trace-events b/hw/riscv/trace-events new file mode 100644 index 0000000000..6d59233e23 --- /dev/null +++ b/hw/riscv/trace-events @@ -0,0 +1,7 @@ +# See docs/devel/tracing.txt for syntax documentation. + +# hw/gpio/sifive_gpio.c +sifive_gpio_read(uint64_t offset, uint64_t r) "offset 0x%" PRIx64 " value 0x%" PRIx64 +sifive_gpio_write(uint64_t offset, uint64_t value) "offset 0x%" PRIx64 " value 0x%" PRIx64 +sifive_gpio_set(int64_t line, int64_t value) "line %" PRIi64 " value %" PRIi64 +sifive_gpio_update_output_irq(int64_t line, int64_t value) "line %" PRIi64 " value %" PRIi64 diff --git a/hw/riscv/virt.c b/hw/riscv/virt.c index fc4c6b306e..84d94d0c42 100644 --- a/hw/riscv/virt.c +++ b/hw/riscv/virt.c @@ -29,7 +29,6 @@ #include "hw/sysbus.h" #include "hw/char/serial.h" #include "target/riscv/cpu.h" -#include "hw/riscv/riscv_htif.h" #include "hw/riscv/riscv_hart.h" #include "hw/riscv/sifive_plic.h" #include "hw/riscv/sifive_clint.h" @@ -400,7 +399,7 @@ static void riscv_virt_board_init(MachineState *machine) /* Initialize SOC */ object_initialize_child(OBJECT(machine), "soc", &s->soc, sizeof(s->soc), TYPE_RISCV_HART_ARRAY, &error_abort, NULL); - object_property_set_str(OBJECT(&s->soc), VIRT_CPU, "cpu-type", + object_property_set_str(OBJECT(&s->soc), machine->cpu_type, "cpu-type", &error_abort); object_property_set_int(OBJECT(&s->soc), smp_cpus, "num-harts", &error_abort); @@ -526,6 +525,7 @@ static void riscv_virt_board_machine_init(MachineClass *mc) mc->desc = "RISC-V VirtIO Board (Privileged ISA v1.10)"; mc->init = riscv_virt_board_init; mc->max_cpus = 8; /* hardcoded limit in BBL */ + mc->default_cpu_type = VIRT_CPU; } DEFINE_MACHINE("virt", riscv_virt_board_machine_init) diff --git a/hw/s390x/event-facility.c b/hw/s390x/event-facility.c index ee5b83448b..e574223a22 100644 --- a/hw/s390x/event-facility.c +++ b/hw/s390x/event-facility.c @@ -466,12 +466,12 @@ static void init_event_facility(Object *obj) new = object_new(TYPE_SCLP_QUIESCE); object_property_add_child(obj, TYPE_SCLP_QUIESCE, new, NULL); object_unref(new); - qdev_set_parent_bus(DEVICE(new), &event_facility->sbus.qbus); + qdev_set_parent_bus(DEVICE(new), BUS(&event_facility->sbus)); new = object_new(TYPE_SCLP_CPU_HOTPLUG); object_property_add_child(obj, TYPE_SCLP_CPU_HOTPLUG, new, NULL); object_unref(new); - qdev_set_parent_bus(DEVICE(new), &event_facility->sbus.qbus); + qdev_set_parent_bus(DEVICE(new), BUS(&event_facility->sbus)); /* the facility will automatically realize the devices via the bus */ } diff --git a/hw/s390x/s390-virtio-ccw.c b/hw/s390x/s390-virtio-ccw.c index bbc6e8fa0b..4d643686cb 100644 --- a/hw/s390x/s390-virtio-ccw.c +++ b/hw/s390x/s390-virtio-ccw.c @@ -669,7 +669,9 @@ DEFINE_CCW_MACHINE(4_1, "4.1", true); static void ccw_machine_4_0_instance_options(MachineState *machine) { + static const S390FeatInit qemu_cpu_feat = { S390_FEAT_LIST_QEMU_V4_0 }; ccw_machine_4_1_instance_options(machine); + s390_set_qemu_cpu_model(0x2827, 12, 2, qemu_cpu_feat); } static void ccw_machine_4_0_class_options(MachineClass *mc) diff --git a/hw/scsi/lsi53c895a.c b/hw/scsi/lsi53c895a.c index da7239d94f..a8b7a199f9 100644 --- a/hw/scsi/lsi53c895a.c +++ b/hw/scsi/lsi53c895a.c @@ -1860,7 +1860,7 @@ static void lsi_reg_writeb(LSIState *s, int offset, uint8_t val) } if (val & LSI_SCNTL1_RST) { if (!(s->sstat0 & LSI_SSTAT0_RST)) { - qbus_reset_all(&s->bus.qbus); + qbus_reset_all(BUS(&s->bus)); s->sstat0 |= LSI_SSTAT0_RST; lsi_script_scsi_interrupt(s, LSI_SIST0_RST, 0); } diff --git a/hw/scsi/mptsas.c b/hw/scsi/mptsas.c index 929404fb48..e800683e91 100644 --- a/hw/scsi/mptsas.c +++ b/hw/scsi/mptsas.c @@ -540,7 +540,7 @@ reply_maybe_async: break; case MPI_SCSITASKMGMT_TASKTYPE_RESET_BUS: - qbus_reset_all(&s->bus.qbus); + qbus_reset_all(BUS(&s->bus)); break; default: @@ -803,7 +803,7 @@ static void mptsas_soft_reset(MPTSASState *s) s->intr_mask = MPI_HIM_DIM | MPI_HIM_RIM; mptsas_update_interrupt(s); - qbus_reset_all(&s->bus.qbus); + qbus_reset_all(BUS(&s->bus)); s->intr_status = 0; s->intr_mask = save_mask; diff --git a/hw/scsi/scsi-disk.c b/hw/scsi/scsi-disk.c index e7e865ab3b..7b89ac798b 100644 --- a/hw/scsi/scsi-disk.c +++ b/hw/scsi/scsi-disk.c @@ -2336,6 +2336,13 @@ static void scsi_realize(SCSIDevice *dev, Error **errp) return; } + if (blk_get_aio_context(s->qdev.conf.blk) != qemu_get_aio_context() && + !s->qdev.hba_supports_iothread) + { + error_setg(errp, "HBA does not support iothreads"); + return; + } + if (dev->type == TYPE_DISK) { if (!blkconf_geometry(&dev->conf, NULL, 65535, 255, 255, errp)) { return; @@ -2417,7 +2424,7 @@ static void scsi_cd_realize(SCSIDevice *dev, Error **errp) if (!dev->conf.blk) { /* Anonymous BlockBackend for an empty drive. As we put it into * dev->conf, qdev takes care of detaching on unplug. */ - dev->conf.blk = blk_new(0, BLK_PERM_ALL); + dev->conf.blk = blk_new(qemu_get_aio_context(), 0, BLK_PERM_ALL); ret = blk_attach_dev(dev->conf.blk, &dev->qdev); assert(ret == 0); } @@ -2929,13 +2936,14 @@ static const TypeInfo scsi_disk_base_info = { .abstract = true, }; -#define DEFINE_SCSI_DISK_PROPERTIES() \ - DEFINE_BLOCK_PROPERTIES(SCSIDiskState, qdev.conf), \ - DEFINE_BLOCK_ERROR_PROPERTIES(SCSIDiskState, qdev.conf), \ - DEFINE_PROP_STRING("ver", SCSIDiskState, version), \ - DEFINE_PROP_STRING("serial", SCSIDiskState, serial), \ - DEFINE_PROP_STRING("vendor", SCSIDiskState, vendor), \ - DEFINE_PROP_STRING("product", SCSIDiskState, product), \ +#define DEFINE_SCSI_DISK_PROPERTIES() \ + DEFINE_PROP_DRIVE_IOTHREAD("drive", SCSIDiskState, qdev.conf.blk), \ + DEFINE_BLOCK_PROPERTIES_BASE(SCSIDiskState, qdev.conf), \ + DEFINE_BLOCK_ERROR_PROPERTIES(SCSIDiskState, qdev.conf), \ + DEFINE_PROP_STRING("ver", SCSIDiskState, version), \ + DEFINE_PROP_STRING("serial", SCSIDiskState, serial), \ + DEFINE_PROP_STRING("vendor", SCSIDiskState, vendor), \ + DEFINE_PROP_STRING("product", SCSIDiskState, product), \ DEFINE_PROP_STRING("device_id", SCSIDiskState, device_id) diff --git a/hw/scsi/vhost-scsi.c b/hw/scsi/vhost-scsi.c index 61e2e57da9..6b01accf61 100644 --- a/hw/scsi/vhost-scsi.c +++ b/hw/scsi/vhost-scsi.c @@ -114,6 +114,10 @@ static void vhost_scsi_set_status(VirtIODevice *vdev, uint8_t val) VHostSCSICommon *vsc = VHOST_SCSI_COMMON(s); bool start = (val & VIRTIO_CONFIG_S_DRIVER_OK); + if (!vdev->vm_running) { + start = false; + } + if (vsc->dev.started == start) { return; } @@ -135,6 +139,28 @@ static void vhost_dummy_handle_output(VirtIODevice *vdev, VirtQueue *vq) { } +static int vhost_scsi_pre_save(void *opaque) +{ + VHostSCSICommon *vsc = opaque; + + /* At this point, backend must be stopped, otherwise + * it might keep writing to memory. */ + assert(!vsc->dev.started); + + return 0; +} + +static const VMStateDescription vmstate_virtio_vhost_scsi = { + .name = "virtio-vhost_scsi", + .minimum_version_id = 1, + .version_id = 1, + .fields = (VMStateField[]) { + VMSTATE_VIRTIO_DEVICE, + VMSTATE_END_OF_LIST() + }, + .pre_save = vhost_scsi_pre_save, +}; + static void vhost_scsi_realize(DeviceState *dev, Error **errp) { VirtIOSCSICommon *vs = VIRTIO_SCSI_COMMON(dev); @@ -173,13 +199,18 @@ static void vhost_scsi_realize(DeviceState *dev, Error **errp) goto close_fd; } - error_setg(&vsc->migration_blocker, - "vhost-scsi does not support migration"); - migrate_add_blocker(vsc->migration_blocker, &err); - if (err) { - error_propagate(errp, err); - error_free(vsc->migration_blocker); - goto close_fd; + if (!vsc->migratable) { + error_setg(&vsc->migration_blocker, + "vhost-scsi does not support migration in all cases. " + "When external environment supports it (Orchestrator migrates " + "target SCSI device state or use shared storage over network), " + "set 'migratable' property to true to enable migration."); + migrate_add_blocker(vsc->migration_blocker, &err); + if (err) { + error_propagate(errp, err); + error_free(vsc->migration_blocker); + goto close_fd; + } } vsc->dev.nvqs = VHOST_SCSI_VQ_NUM_FIXED + vs->conf.num_queues; @@ -204,7 +235,9 @@ static void vhost_scsi_realize(DeviceState *dev, Error **errp) return; free_vqs: - migrate_del_blocker(vsc->migration_blocker); + if (!vsc->migratable) { + migrate_del_blocker(vsc->migration_blocker); + } g_free(vsc->dev.vqs); close_fd: close(vhostfd); @@ -217,8 +250,10 @@ static void vhost_scsi_unrealize(DeviceState *dev, Error **errp) VHostSCSICommon *vsc = VHOST_SCSI_COMMON(dev); struct vhost_virtqueue *vqs = vsc->dev.vqs; - migrate_del_blocker(vsc->migration_blocker); - error_free(vsc->migration_blocker); + if (!vsc->migratable) { + migrate_del_blocker(vsc->migration_blocker); + error_free(vsc->migration_blocker); + } /* This will stop vhost backend. */ vhost_scsi_set_status(vdev, 0); @@ -242,6 +277,7 @@ static Property vhost_scsi_properties[] = { DEFINE_PROP_BIT64("t10_pi", VHostSCSICommon, host_features, VIRTIO_SCSI_F_T10_PI, false), + DEFINE_PROP_BOOL("migratable", VHostSCSICommon, migratable, false), DEFINE_PROP_END_OF_LIST(), }; @@ -252,6 +288,7 @@ static void vhost_scsi_class_init(ObjectClass *klass, void *data) FWPathProviderClass *fwc = FW_PATH_PROVIDER_CLASS(klass); dc->props = vhost_scsi_properties; + dc->vmsd = &vmstate_virtio_vhost_scsi; set_bit(DEVICE_CATEGORY_STORAGE, dc->categories); vdc->realize = vhost_scsi_realize; vdc->unrealize = vhost_scsi_unrealize; diff --git a/hw/scsi/vhost-user-scsi.c b/hw/scsi/vhost-user-scsi.c index 8b1e6876db..a9fd8ea305 100644 --- a/hw/scsi/vhost-user-scsi.c +++ b/hw/scsi/vhost-user-scsi.c @@ -69,6 +69,7 @@ static void vhost_user_scsi_realize(DeviceState *dev, Error **errp) VirtIOSCSICommon *vs = VIRTIO_SCSI_COMMON(dev); VHostUserSCSI *s = VHOST_USER_SCSI(dev); VHostSCSICommon *vsc = VHOST_SCSI_COMMON(s); + struct vhost_virtqueue *vqs = NULL; Error *err = NULL; int ret; @@ -93,6 +94,7 @@ static void vhost_user_scsi_realize(DeviceState *dev, Error **errp) vsc->dev.vqs = g_new(struct vhost_virtqueue, vsc->dev.nvqs); vsc->dev.vq_index = 0; vsc->dev.backend_features = 0; + vqs = vsc->dev.vqs; ret = vhost_dev_init(&vsc->dev, &s->vhost_user, VHOST_BACKEND_TYPE_USER, 0); @@ -100,6 +102,7 @@ static void vhost_user_scsi_realize(DeviceState *dev, Error **errp) error_setg(errp, "vhost-user-scsi: vhost initialization failed: %s", strerror(-ret)); vhost_user_cleanup(&s->vhost_user); + g_free(vqs); return; } diff --git a/hw/scsi/virtio-scsi.c b/hw/scsi/virtio-scsi.c index 839f120256..12d21bbc61 100644 --- a/hw/scsi/virtio-scsi.c +++ b/hw/scsi/virtio-scsi.c @@ -696,7 +696,7 @@ static void virtio_scsi_reset(VirtIODevice *vdev) assert(!s->dataplane_started); s->resetting++; - qbus_reset_all(&s->bus.qbus); + qbus_reset_all(BUS(&s->bus)); s->resetting--; vs->sense_size = VIRTIO_SCSI_SENSE_DEFAULT_SIZE; @@ -789,28 +789,31 @@ static void virtio_scsi_change(SCSIBus *bus, SCSIDevice *dev, SCSISense sense) } } +static void virtio_scsi_pre_hotplug(HotplugHandler *hotplug_dev, + DeviceState *dev, Error **errp) +{ + SCSIDevice *sd = SCSI_DEVICE(dev); + sd->hba_supports_iothread = true; +} + static void virtio_scsi_hotplug(HotplugHandler *hotplug_dev, DeviceState *dev, Error **errp) { VirtIODevice *vdev = VIRTIO_DEVICE(hotplug_dev); VirtIOSCSI *s = VIRTIO_SCSI(vdev); SCSIDevice *sd = SCSI_DEVICE(dev); + int ret; if (s->ctx && !s->dataplane_fenced) { - AioContext *ctx; if (blk_op_is_blocked(sd->conf.blk, BLOCK_OP_TYPE_DATAPLANE, errp)) { return; } - ctx = blk_get_aio_context(sd->conf.blk); - if (ctx != s->ctx && ctx != qemu_get_aio_context()) { - error_setg(errp, "Cannot attach a blockdev that is using " - "a different iothread"); - return; - } virtio_scsi_acquire(s); - blk_set_aio_context(sd->conf.blk, s->ctx); + ret = blk_set_aio_context(sd->conf.blk, s->ctx, errp); virtio_scsi_release(s); - + if (ret < 0) { + return; + } } if (virtio_vdev_has_feature(vdev, VIRTIO_SCSI_F_HOTPLUG)) { @@ -839,7 +842,8 @@ static void virtio_scsi_hotunplug(HotplugHandler *hotplug_dev, DeviceState *dev, if (s->ctx) { virtio_scsi_acquire(s); - blk_set_aio_context(sd->conf.blk, qemu_get_aio_context()); + /* If other users keep the BlockBackend in the iothread, that's ok */ + blk_set_aio_context(sd->conf.blk, qemu_get_aio_context(), NULL); virtio_scsi_release(s); } @@ -986,6 +990,7 @@ static void virtio_scsi_class_init(ObjectClass *klass, void *data) vdc->reset = virtio_scsi_reset; vdc->start_ioeventfd = virtio_scsi_dataplane_start; vdc->stop_ioeventfd = virtio_scsi_dataplane_stop; + hc->pre_plug = virtio_scsi_pre_hotplug; hc->plug = virtio_scsi_hotplug; hc->unplug = virtio_scsi_hotunplug; } diff --git a/hw/scsi/vmw_pvscsi.c b/hw/scsi/vmw_pvscsi.c index 584b4be07e..c39e33fa35 100644 --- a/hw/scsi/vmw_pvscsi.c +++ b/hw/scsi/vmw_pvscsi.c @@ -440,7 +440,7 @@ static void pvscsi_reset_adapter(PVSCSIState *s) { s->resetting++; - qbus_reset_all_fn(&s->bus); + qbus_reset_all(BUS(&s->bus)); s->resetting--; pvscsi_process_completion_queue(s); assert(QTAILQ_EMPTY(&s->pending_queue)); @@ -848,7 +848,7 @@ pvscsi_on_cmd_reset_bus(PVSCSIState *s) trace_pvscsi_on_cmd_arrived("PVSCSI_CMD_RESET_BUS"); s->resetting++; - qbus_reset_all_fn(&s->bus); + qbus_reset_all(BUS(&s->bus)); s->resetting--; return PVSCSI_COMMAND_PROCESSING_SUCCEEDED; } diff --git a/hw/sd/milkymist-memcard.c b/hw/sd/milkymist-memcard.c index df42aa1c54..dd1ba649d9 100644 --- a/hw/sd/milkymist-memcard.c +++ b/hw/sd/milkymist-memcard.c @@ -277,7 +277,7 @@ static void milkymist_memcard_realize(DeviceState *dev, Error **errp) /* FIXME use a qdev drive property instead of drive_get_next() */ dinfo = drive_get_next(IF_SD); blk = dinfo ? blk_by_legacy_dinfo(dinfo) : NULL; - carddev = qdev_create(&s->sdbus.qbus, TYPE_SD_CARD); + carddev = qdev_create(BUS(&s->sdbus), TYPE_SD_CARD); qdev_prop_set_drive(carddev, "drive", blk, &err); object_property_set_bool(OBJECT(carddev), true, "realized", &err); if (err) { diff --git a/hw/sd/ssi-sd.c b/hw/sd/ssi-sd.c index 623d0333e8..25e1009277 100644 --- a/hw/sd/ssi-sd.c +++ b/hw/sd/ssi-sd.c @@ -249,7 +249,7 @@ static void ssi_sd_realize(SSISlave *d, Error **errp) /* Create and plug in the sd card */ /* FIXME use a qdev drive property instead of drive_get_next() */ dinfo = drive_get_next(IF_SD); - carddev = qdev_create(&s->sdbus.qbus, TYPE_SD_CARD); + carddev = qdev_create(BUS(&s->sdbus), TYPE_SD_CARD); if (dinfo) { qdev_prop_set_drive(carddev, "drive", blk_by_legacy_dinfo(dinfo), &err); } diff --git a/hw/semihosting/Kconfig b/hw/semihosting/Kconfig new file mode 100644 index 0000000000..efe0a30734 --- /dev/null +++ b/hw/semihosting/Kconfig @@ -0,0 +1,3 @@ + +config SEMIHOSTING + bool diff --git a/hw/semihosting/Makefile.objs b/hw/semihosting/Makefile.objs new file mode 100644 index 0000000000..4ad47c05c0 --- /dev/null +++ b/hw/semihosting/Makefile.objs @@ -0,0 +1,2 @@ +obj-$(CONFIG_SEMIHOSTING) += config.o +obj-$(CONFIG_SEMIHOSTING) += console.o diff --git a/hw/semihosting/config.c b/hw/semihosting/config.c new file mode 100644 index 0000000000..2a8e7e1045 --- /dev/null +++ b/hw/semihosting/config.c @@ -0,0 +1,186 @@ +/* + * Semihosting configuration + * + * Copyright (c) 2015 Imagination Technologies + * Copyright (c) 2019 Linaro Ltd + * + * This controls the configuration of semihosting for all guest + * targets that support it. Architecture specific handling is handled + * in target/HW/HW-semi.c + * + * Semihosting is sightly strange in that it is also supported by some + * linux-user targets. However in that use case no configuration of + * the outputs and command lines is supported. + * + * The config module is common to all softmmu targets however as vl.c + * needs to link against the helpers. + * + * SPDX-License-Identifier: GPL-2.0-or-later + */ + +#include "qemu/osdep.h" +#include "qemu/option.h" +#include "qemu/config-file.h" +#include "qemu/error-report.h" +#include "hw/semihosting/semihost.h" +#include "chardev/char.h" + +QemuOptsList qemu_semihosting_config_opts = { + .name = "semihosting-config", + .implied_opt_name = "enable", + .head = QTAILQ_HEAD_INITIALIZER(qemu_semihosting_config_opts.head), + .desc = { + { + .name = "enable", + .type = QEMU_OPT_BOOL, + }, { + .name = "target", + .type = QEMU_OPT_STRING, + }, { + .name = "chardev", + .type = QEMU_OPT_STRING, + }, { + .name = "arg", + .type = QEMU_OPT_STRING, + }, + { /* end of list */ } + }, +}; + +typedef struct SemihostingConfig { + bool enabled; + SemihostingTarget target; + Chardev *chardev; + const char **argv; + int argc; + const char *cmdline; /* concatenated argv */ +} SemihostingConfig; + +static SemihostingConfig semihosting; +static const char *semihost_chardev; + +bool semihosting_enabled(void) +{ + return semihosting.enabled; +} + +SemihostingTarget semihosting_get_target(void) +{ + return semihosting.target; +} + +const char *semihosting_get_arg(int i) +{ + if (i >= semihosting.argc) { + return NULL; + } + return semihosting.argv[i]; +} + +int semihosting_get_argc(void) +{ + return semihosting.argc; +} + +const char *semihosting_get_cmdline(void) +{ + if (semihosting.cmdline == NULL && semihosting.argc > 0) { + semihosting.cmdline = g_strjoinv(" ", (gchar **)semihosting.argv); + } + return semihosting.cmdline; +} + +static int add_semihosting_arg(void *opaque, + const char *name, const char *val, + Error **errp) +{ + SemihostingConfig *s = opaque; + if (strcmp(name, "arg") == 0) { + s->argc++; + /* one extra element as g_strjoinv() expects NULL-terminated array */ + s->argv = g_realloc(s->argv, (s->argc + 1) * sizeof(void *)); + s->argv[s->argc - 1] = val; + s->argv[s->argc] = NULL; + } + return 0; +} + +/* Use strings passed via -kernel/-append to initialize semihosting.argv[] */ +void semihosting_arg_fallback(const char *file, const char *cmd) +{ + char *cmd_token; + + /* argv[0] */ + add_semihosting_arg(&semihosting, "arg", file, NULL); + + /* split -append and initialize argv[1..n] */ + cmd_token = strtok(g_strdup(cmd), " "); + while (cmd_token) { + add_semihosting_arg(&semihosting, "arg", cmd_token, NULL); + cmd_token = strtok(NULL, " "); + } +} + +Chardev *semihosting_get_chardev(void) +{ + return semihosting.chardev; +} + +void qemu_semihosting_enable(void) +{ + semihosting.enabled = true; + semihosting.target = SEMIHOSTING_TARGET_AUTO; +} + +int qemu_semihosting_config_options(const char *optarg) +{ + QemuOptsList *opt_list = qemu_find_opts("semihosting-config"); + QemuOpts *opts = qemu_opts_parse_noisily(opt_list, optarg, false); + + semihosting.enabled = true; + + if (opts != NULL) { + semihosting.enabled = qemu_opt_get_bool(opts, "enable", + true); + const char *target = qemu_opt_get(opts, "target"); + /* setup of chardev is deferred until they are initialised */ + semihost_chardev = qemu_opt_get(opts, "chardev"); + if (target != NULL) { + if (strcmp("native", target) == 0) { + semihosting.target = SEMIHOSTING_TARGET_NATIVE; + } else if (strcmp("gdb", target) == 0) { + semihosting.target = SEMIHOSTING_TARGET_GDB; + } else if (strcmp("auto", target) == 0) { + semihosting.target = SEMIHOSTING_TARGET_AUTO; + } else { + error_report("unsupported semihosting-config %s", + optarg); + return 1; + } + } else { + semihosting.target = SEMIHOSTING_TARGET_AUTO; + } + /* Set semihosting argument count and vector */ + qemu_opt_foreach(opts, add_semihosting_arg, + &semihosting, NULL); + } else { + error_report("unsupported semihosting-config %s", optarg); + return 1; + } + + return 0; +} + +void qemu_semihosting_connect_chardevs(void) +{ + /* We had to defer this until chardevs were created */ + if (semihost_chardev) { + Chardev *chr = qemu_chr_find(semihost_chardev); + if (chr == NULL) { + error_report("semihosting chardev '%s' not found", + semihost_chardev); + exit(1); + } + semihosting.chardev = chr; + } +} diff --git a/hw/semihosting/console.c b/hw/semihosting/console.c new file mode 100644 index 0000000000..466ea6dade --- /dev/null +++ b/hw/semihosting/console.c @@ -0,0 +1,84 @@ +/* + * Semihosting Console Support + * + * Copyright (c) 2015 Imagination Technologies + * Copyright (c) 2019 Linaro Ltd + * + * This provides support for outputting to a semihosting console. + * + * While most semihosting implementations support reading and writing + * to arbitrary file descriptors we treat the console as something + * specifically for debugging interaction. This means messages can be + * re-directed to gdb (if currently being used to debug) or even + * re-directed elsewhere. + * + * SPDX-License-Identifier: GPL-2.0-or-later + */ + +#include "qemu/osdep.h" +#include "cpu.h" +#include "hw/semihosting/semihost.h" +#include "hw/semihosting/console.h" +#include "exec/gdbstub.h" +#include "qemu/log.h" +#include "chardev/char.h" + +int qemu_semihosting_log_out(const char *s, int len) +{ + Chardev *chardev = semihosting_get_chardev(); + if (chardev) { + return qemu_chr_write_all(chardev, (uint8_t *) s, len); + } else { + return write(STDERR_FILENO, s, len); + } +} + +/* + * A re-implementation of lock_user_string that we can use locally + * instead of relying on softmmu-semi. Hopefully we can deprecate that + * in time. We either copy len bytes if specified or until we find a NULL. + */ +static GString *copy_user_string(CPUArchState *env, target_ulong addr, int len) +{ + CPUState *cpu = ENV_GET_CPU(env); + GString *s = g_string_sized_new(len ? len : 128); + uint8_t c; + bool done; + + do { + if (cpu_memory_rw_debug(cpu, addr++, &c, 1, 0) == 0) { + s = g_string_append_c(s, c); + done = len ? s->len == len : c == 0; + } else { + qemu_log_mask(LOG_GUEST_ERROR, + "%s: passed inaccessible address " TARGET_FMT_lx, + __func__, addr); + done = true; + } + } while (!done); + + return s; +} + +static void semihosting_cb(CPUState *cs, target_ulong ret, target_ulong err) +{ + if (ret == (target_ulong) -1) { + qemu_log("%s: gdb console output failed ("TARGET_FMT_ld")", + __func__, err); + } +} + +int qemu_semihosting_console_out(CPUArchState *env, target_ulong addr, int len) +{ + GString *s = copy_user_string(env, addr, len); + int out = s->len; + + if (use_gdb_syscalls()) { + gdb_do_syscall(semihosting_cb, "write,2,%x,%x", addr, s->len); + } else { + out = qemu_semihosting_log_out(s->str, s->len); + } + + g_string_free(s, true); + return out; +} diff --git a/hw/usb/dev-storage.c b/hw/usb/dev-storage.c index cd5551d94f..0e4e93ef16 100644 --- a/hw/usb/dev-storage.c +++ b/hw/usb/dev-storage.c @@ -616,7 +616,7 @@ static void usb_msd_storage_realize(USBDevice *dev, Error **errp) * The hack is probably a bad idea. */ blk_ref(blk); - blk_detach_dev(blk, &s->dev.qdev); + blk_detach_dev(blk, DEVICE(s)); s->conf.blk = NULL; usb_desc_create_serial(dev); diff --git a/hw/vfio/display.c b/hw/vfio/display.c index 2c2d3e5b71..a5a608c5b2 100644 --- a/hw/vfio/display.c +++ b/hw/vfio/display.c @@ -248,6 +248,7 @@ static VFIODMABuf *vfio_display_get_dmabuf(VFIOPCIDevice *vdev, dmabuf->buf.height = plane.height; dmabuf->buf.stride = plane.stride; dmabuf->buf.fourcc = plane.drm_format; + dmabuf->buf.modifier = plane.drm_format_mod; dmabuf->buf.fd = fd; if (plane_type == DRM_PLANE_TYPE_CURSOR) { vfio_display_update_cursor(dmabuf, &plane); diff --git a/hw/vfio/pci.c b/hw/vfio/pci.c index 8e555db12e..2a4091d216 100644 --- a/hw/vfio/pci.c +++ b/hw/vfio/pci.c @@ -2717,7 +2717,7 @@ static void vfio_req_notifier_handler(void *opaque) return; } - qdev_unplug(&vdev->pdev.qdev, &err); + qdev_unplug(DEVICE(vdev), &err); if (err) { warn_reportf_err(err, VFIO_MSG_PREFIX, vdev->vbasedev.name); } @@ -2839,7 +2839,7 @@ static void vfio_realize(PCIDevice *pdev, Error **errp) vdev->vbasedev.name = g_path_get_basename(vdev->vbasedev.sysfsdev); vdev->vbasedev.ops = &vfio_pci_ops; vdev->vbasedev.type = VFIO_DEVICE_TYPE_PCI; - vdev->vbasedev.dev = &vdev->pdev.qdev; + vdev->vbasedev.dev = DEVICE(vdev); tmp = g_strdup_printf("%s/iommu_group", vdev->vbasedev.sysfsdev); len = readlink(tmp, group_path, sizeof(group_path)); diff --git a/hw/virtio/vhost-user.c b/hw/virtio/vhost-user.c index 553319c7ac..4ca5b2551e 100644 --- a/hw/virtio/vhost-user.c +++ b/hw/virtio/vhost-user.c @@ -96,6 +96,7 @@ typedef enum VhostUserRequest { VHOST_USER_POSTCOPY_END = 30, VHOST_USER_GET_INFLIGHT_FD = 31, VHOST_USER_SET_INFLIGHT_FD = 32, + VHOST_USER_GPU_SET_SOCKET = 33, VHOST_USER_MAX } VhostUserRequest; @@ -353,6 +354,16 @@ static int vhost_user_write(struct vhost_dev *dev, VhostUserMsg *msg, return 0; } +int vhost_user_gpu_set_socket(struct vhost_dev *dev, int fd) +{ + VhostUserMsg msg = { + .hdr.request = VHOST_USER_GPU_SET_SOCKET, + .hdr.flags = VHOST_USER_VERSION, + }; + + return vhost_user_write(dev, &msg, &fd, 1); +} + static int vhost_user_set_log_base(struct vhost_dev *dev, uint64_t base, struct vhost_log *log) { diff --git a/hw/virtio/vhost.c b/hw/virtio/vhost.c index 7f61018f2a..60747a6f93 100644 --- a/hw/virtio/vhost.c +++ b/hw/virtio/vhost.c @@ -1081,7 +1081,7 @@ static void vhost_virtqueue_stop(struct vhost_dev *dev, r = dev->vhost_ops->vhost_get_vring_base(dev, &state); if (r < 0) { - VHOST_OPS_DEBUG("vhost VQ %d ring restore failed: %d", idx, r); + VHOST_OPS_DEBUG("vhost VQ %u ring restore failed: %d", idx, r); /* Connection to the backend is broken, so let's sync internal * last avail idx to the device used idx. */ @@ -1650,7 +1650,6 @@ fail_vq: hdev->vqs + i, hdev->vq_index + i); } - i = hdev->nvqs; fail_mem: fail_features: diff --git a/hw/virtio/virtio.c b/hw/virtio/virtio.c index 4805727b53..07f4a64b48 100644 --- a/hw/virtio/virtio.c +++ b/hw/virtio/virtio.c @@ -2312,9 +2312,8 @@ void virtio_instance_init_common(Object *proxy_obj, void *data, { DeviceState *vdev = data; - object_initialize(vdev, vdev_size, vdev_name); - object_property_add_child(proxy_obj, "virtio-backend", OBJECT(vdev), NULL); - object_unref(OBJECT(vdev)); + object_initialize_child(proxy_obj, "virtio-backend", vdev, vdev_size, + vdev_name, &error_abort, NULL); qdev_alias_all_properties(vdev, proxy_obj); } diff --git a/hw/watchdog/wdt_i6300esb.c b/hw/watchdog/wdt_i6300esb.c index 1c6eddf86a..f2d1e86526 100644 --- a/hw/watchdog/wdt_i6300esb.c +++ b/hw/watchdog/wdt_i6300esb.c @@ -200,7 +200,7 @@ static void i6300esb_timer_expired(void *vp) if (d->reboot_enabled) { d->previous_reboot_flag = 1; watchdog_perform_action(); /* This reboots, exits, etc */ - i6300esb_reset(&d->dev.qdev); + i6300esb_reset(DEVICE(d)); } /* In "free running mode" we start stage 1 again. */ diff --git a/include/block/block.h b/include/block/block.h index 9b083e2bca..f9415ed740 100644 --- a/include/block/block.h +++ b/include/block/block.h @@ -156,10 +156,15 @@ typedef struct HDGeometry { * BDRV_BLOCK_EOF: the returned pnum covers through end of file for this * layer, set by block layer * - * Internal flag: + * Internal flags: * BDRV_BLOCK_RAW: for use by passthrough drivers, such as raw, to request * that the block layer recompute the answer from the returned * BDS; must be accompanied by just BDRV_BLOCK_OFFSET_VALID. + * BDRV_BLOCK_RECURSE: request that the block layer will recursively search for + * zeroes in file child of current block node inside + * returned region. Only valid together with both + * BDRV_BLOCK_DATA and BDRV_BLOCK_OFFSET_VALID. Should not + * appear with BDRV_BLOCK_ZERO. * * If BDRV_BLOCK_OFFSET_VALID is set, the map parameter represents the * host offset within the returned BDS that is allocated for the @@ -184,6 +189,7 @@ typedef struct HDGeometry { #define BDRV_BLOCK_RAW 0x08 #define BDRV_BLOCK_ALLOCATED 0x10 #define BDRV_BLOCK_EOF 0x20 +#define BDRV_BLOCK_RECURSE 0x40 #define BDRV_BLOCK_OFFSET_MASK BDRV_SECTOR_MASK typedef QSIMPLEQ_HEAD(BlockReopenQueue, BlockReopenQueueEntry) BlockReopenQueue; @@ -428,8 +434,8 @@ void bdrv_drain_all(void); AIO_WAIT_WHILE(bdrv_get_aio_context(bs_), \ cond); }) -int bdrv_pdiscard(BdrvChild *child, int64_t offset, int bytes); -int bdrv_co_pdiscard(BdrvChild *child, int64_t offset, int bytes); +int bdrv_pdiscard(BdrvChild *child, int64_t offset, int64_t bytes); +int bdrv_co_pdiscard(BdrvChild *child, int64_t offset, int64_t bytes); int bdrv_has_zero_init_1(BlockDriverState *bs); int bdrv_has_zero_init(BlockDriverState *bs); bool bdrv_unallocated_blocks_are_zero(BlockDriverState *bs); @@ -577,15 +583,6 @@ AioContext *bdrv_get_aio_context(BlockDriverState *bs); */ void bdrv_coroutine_enter(BlockDriverState *bs, Coroutine *co); -/** - * bdrv_set_aio_context: - * - * Changes the #AioContext used for fd handlers, timers, and BHs by this - * BlockDriverState and all its children. - * - * This function must be called with iothread lock held. - */ -void bdrv_set_aio_context(BlockDriverState *bs, AioContext *new_context); void bdrv_set_aio_context_ignore(BlockDriverState *bs, AioContext *new_context, GSList **ignore); int bdrv_try_set_aio_context(BlockDriverState *bs, AioContext *ctx, diff --git a/include/block/block_int.h b/include/block/block_int.h index 1eebc7c8f3..06df2bda1b 100644 --- a/include/block/block_int.h +++ b/include/block/block_int.h @@ -1163,6 +1163,7 @@ void hmp_drive_add_node(Monitor *mon, const char *optstr); BdrvChild *bdrv_root_attach_child(BlockDriverState *child_bs, const char *child_name, const BdrvChildRole *child_role, + AioContext *ctx, uint64_t perm, uint64_t shared_perm, void *opaque, Error **errp); void bdrv_root_unref_child(BdrvChild *child); diff --git a/include/block/nvme.h b/include/block/nvme.h index 849a6f3fa3..3ec8efcc43 100644 --- a/include/block/nvme.h +++ b/include/block/nvme.h @@ -581,6 +581,7 @@ enum NvmeIdCtrlOncs { NVME_ONCS_WRITE_ZEROS = 1 << 3, NVME_ONCS_FEATURES = 1 << 4, NVME_ONCS_RESRVATIONS = 1 << 5, + NVME_ONCS_TIMESTAMP = 1 << 6, }; #define NVME_CTRL_SQES_MIN(sqes) ((sqes) & 0xf) @@ -622,6 +623,7 @@ enum NvmeFeatureIds { NVME_INTERRUPT_VECTOR_CONF = 0x9, NVME_WRITE_ATOMICITY = 0xa, NVME_ASYNCHRONOUS_EVENT_CONF = 0xb, + NVME_TIMESTAMP = 0xe, NVME_SOFTWARE_PROGRESS_MARKER = 0x80 }; diff --git a/include/block/raw-aio.h b/include/block/raw-aio.h index ba223dd1f1..0cb7cc74a2 100644 --- a/include/block/raw-aio.h +++ b/include/block/raw-aio.h @@ -50,9 +50,6 @@ LinuxAioState *laio_init(Error **errp); void laio_cleanup(LinuxAioState *s); int coroutine_fn laio_co_submit(BlockDriverState *bs, LinuxAioState *s, int fd, uint64_t offset, QEMUIOVector *qiov, int type); -BlockAIOCB *laio_submit(BlockDriverState *bs, LinuxAioState *s, int fd, - int64_t sector_num, QEMUIOVector *qiov, int nb_sectors, - BlockCompletionFunc *cb, void *opaque, int type); void laio_detach_aio_context(LinuxAioState *s, AioContext *old_context); void laio_attach_aio_context(LinuxAioState *s, AioContext *new_context); void laio_io_plug(BlockDriverState *bs, LinuxAioState *s); diff --git a/include/elf.h b/include/elf.h index ea7708a4ea..3501e0c8d0 100644 --- a/include/elf.h +++ b/include/elf.h @@ -598,6 +598,7 @@ typedef struct { #define HWCAP_S390_ETF3EH 256 #define HWCAP_S390_HIGH_GPRS 512 #define HWCAP_S390_TE 1024 +#define HWCAP_S390_VXRS 2048 /* M68K specific definitions. */ /* We use the top 24 bits to encode information about the diff --git a/include/exec/memory.h b/include/exec/memory.h index 9144a47f57..e6140e8a04 100644 --- a/include/exec/memory.h +++ b/include/exec/memory.h @@ -1255,23 +1255,6 @@ void memory_region_ram_resize(MemoryRegion *mr, ram_addr_t newsize, void memory_region_set_log(MemoryRegion *mr, bool log, unsigned client); /** - * memory_region_get_dirty: Check whether a range of bytes is dirty - * for a specified client. - * - * Checks whether a range of bytes has been written to since the last - * call to memory_region_reset_dirty() with the same @client. Dirty logging - * must be enabled. - * - * @mr: the memory region being queried. - * @addr: the address (relative to the start of the region) being queried. - * @size: the size of the range being queried. - * @client: the user of the logging information; %DIRTY_MEMORY_MIGRATION or - * %DIRTY_MEMORY_VGA. - */ -bool memory_region_get_dirty(MemoryRegion *mr, hwaddr addr, - hwaddr size, unsigned client); - -/** * memory_region_set_dirty: Mark a range of bytes as dirty in a memory region. * * Marks a range of bytes as dirty, after it has been dirtied outside diff --git a/include/hw/acpi/acpi-defs.h b/include/hw/acpi/acpi-defs.h index f9aa4bd398..57a3f58b0c 100644 --- a/include/hw/acpi/acpi-defs.h +++ b/include/hw/acpi/acpi-defs.h @@ -449,24 +449,6 @@ struct AcpiSratProcessorGiccAffinity { typedef struct AcpiSratProcessorGiccAffinity AcpiSratProcessorGiccAffinity; -/* PCI fw r3.0 MCFG table. */ -/* Subtable */ -struct AcpiMcfgAllocation { - uint64_t address; /* Base address, processor-relative */ - uint16_t pci_segment; /* PCI segment group number */ - uint8_t start_bus_number; /* Starting PCI Bus number */ - uint8_t end_bus_number; /* Final PCI Bus number */ - uint32_t reserved; -} QEMU_PACKED; -typedef struct AcpiMcfgAllocation AcpiMcfgAllocation; - -struct AcpiTableMcfg { - ACPI_TABLE_HEADER_DEF; - uint8_t reserved[8]; - AcpiMcfgAllocation allocation[0]; -} QEMU_PACKED; -typedef struct AcpiTableMcfg AcpiTableMcfg; - /* * TCPA Description Table * diff --git a/include/hw/acpi/pci.h b/include/hw/acpi/pci.h index 124af7d32a..8bbd32cf45 100644 --- a/include/hw/acpi/pci.h +++ b/include/hw/acpi/pci.h @@ -30,4 +30,5 @@ typedef struct AcpiMcfgInfo { uint32_t size; } AcpiMcfgInfo; +void build_mcfg(GArray *table_data, BIOSLinker *linker, AcpiMcfgInfo *info); #endif diff --git a/include/hw/arm/bcm2835_peripherals.h b/include/hw/arm/bcm2835_peripherals.h index f5b193f670..e79c21771f 100644 --- a/include/hw/arm/bcm2835_peripherals.h +++ b/include/hw/arm/bcm2835_peripherals.h @@ -13,6 +13,7 @@ #include "qemu-common.h" #include "hw/sysbus.h" +#include "hw/char/pl011.h" #include "hw/char/bcm2835_aux.h" #include "hw/display/bcm2835_fb.h" #include "hw/dma/bcm2835_dma.h" @@ -37,7 +38,7 @@ typedef struct BCM2835PeripheralState { MemoryRegion ram_alias[4]; qemu_irq irq, fiq; - SysBusDevice *uart0; + PL011State uart0; BCM2835AuxState aux; BCM2835FBState fb; BCM2835DMAState dma; diff --git a/include/hw/block/block.h b/include/hw/block/block.h index d06f25aa0f..607539057a 100644 --- a/include/hw/block/block.h +++ b/include/hw/block/block.h @@ -45,8 +45,7 @@ static inline unsigned int get_physical_block_exp(BlockConf *conf) return exp; } -#define DEFINE_BLOCK_PROPERTIES(_state, _conf) \ - DEFINE_PROP_DRIVE("drive", _state, _conf.blk), \ +#define DEFINE_BLOCK_PROPERTIES_BASE(_state, _conf) \ DEFINE_PROP_BLOCKSIZE("logical_block_size", _state, \ _conf.logical_block_size), \ DEFINE_PROP_BLOCKSIZE("physical_block_size", _state, \ @@ -59,6 +58,10 @@ static inline unsigned int get_physical_block_exp(BlockConf *conf) ON_OFF_AUTO_AUTO), \ DEFINE_PROP_BOOL("share-rw", _state, _conf.share_rw, false) +#define DEFINE_BLOCK_PROPERTIES(_state, _conf) \ + DEFINE_PROP_DRIVE("drive", _state, _conf.blk), \ + DEFINE_BLOCK_PROPERTIES_BASE(_state, _conf) + #define DEFINE_BLOCK_CHS_PROPERTIES(_state, _conf) \ DEFINE_PROP_UINT32("cyls", _state, _conf.cyls, 0), \ DEFINE_PROP_UINT32("heads", _state, _conf.heads, 0), \ diff --git a/include/hw/boards.h b/include/hw/boards.h index 6f7916f88f..6ff02bf3e4 100644 --- a/include/hw/boards.h +++ b/include/hw/boards.h @@ -292,6 +292,9 @@ struct MachineState { } \ type_init(machine_initfn##_register_types) +extern GlobalProperty hw_compat_4_0_1[]; +extern const size_t hw_compat_4_0_1_len; + extern GlobalProperty hw_compat_4_0[]; extern const size_t hw_compat_4_0_len; diff --git a/include/hw/i386/pc.h b/include/hw/i386/pc.h index 43df7230a2..5d5636241e 100644 --- a/include/hw/i386/pc.h +++ b/include/hw/i386/pc.h @@ -293,6 +293,9 @@ int e820_add_entry(uint64_t, uint64_t, uint32_t); int e820_get_num_entries(void); bool e820_get_entry(int, uint32_t, uint64_t *, uint64_t *); +extern GlobalProperty pc_compat_4_0_1[]; +extern const size_t pc_compat_4_0_1_len; + extern GlobalProperty pc_compat_4_0[]; extern const size_t pc_compat_4_0_len; diff --git a/include/hw/pci/pci.h b/include/hw/pci/pci.h index edf44de21d..d082707dfa 100644 --- a/include/hw/pci/pci.h +++ b/include/hw/pci/pci.h @@ -234,7 +234,7 @@ typedef struct PCIDeviceClass { * This doesn't mean pci host switch. * When card bus bridge is supported, this would be enhanced. */ - int is_bridge; + bool is_bridge; /* rom bar */ const char *romfile; @@ -395,7 +395,6 @@ typedef PCIINTxRoute (*pci_route_irq_fn)(void *opaque, int pin); #define TYPE_PCIE_BUS "PCIE" bool pci_bus_is_express(PCIBus *bus); -bool pci_bus_allows_extended_config_space(PCIBus *bus); void pci_root_bus_new_inplace(PCIBus *bus, size_t bus_size, DeviceState *parent, const char *name, diff --git a/include/hw/pci/pci_bus.h b/include/hw/pci/pci_bus.h index aea98d5040..0714f578af 100644 --- a/include/hw/pci/pci_bus.h +++ b/include/hw/pci/pci_bus.h @@ -17,12 +17,13 @@ typedef struct PCIBusClass { int (*bus_num)(PCIBus *bus); uint16_t (*numa_node)(PCIBus *bus); - bool (*allows_extended_config_space)(PCIBus *bus); } PCIBusClass; enum PCIBusFlags { /* This bus is the root of a PCI domain */ PCI_BUS_IS_ROOT = 0x0001, + /* PCIe extended configuration space is accessible on this bus */ + PCI_BUS_EXTENDED_CONFIG_SPACE = 0x0002, }; struct PCIBus { @@ -57,4 +58,9 @@ static inline bool pci_bus_is_root(PCIBus *bus) return !!(bus->flags & PCI_BUS_IS_ROOT); } +static inline bool pci_bus_allows_extended_config_space(PCIBus *bus) +{ + return !!(bus->flags & PCI_BUS_EXTENDED_CONFIG_SPACE); +} + #endif /* QEMU_PCI_BUS_H */ diff --git a/include/hw/ppc/spapr.h b/include/hw/ppc/spapr.h index 7e32f309c2..4f5becf1f3 100644 --- a/include/hw/ppc/spapr.h +++ b/include/hw/ppc/spapr.h @@ -119,6 +119,7 @@ struct SpaprMachineClass { bool pre_2_10_has_unused_icps; bool legacy_irq_allocation; bool broken_host_serial_model; /* present real host info to the guest */ + bool pre_4_1_migration; /* don't migrate hpt-max-page-size */ void (*phb_placement)(SpaprMachineState *spapr, uint32_t index, uint64_t *buid, hwaddr *pio, @@ -849,6 +850,7 @@ extern const VMStateDescription vmstate_spapr_cap_dfp; extern const VMStateDescription vmstate_spapr_cap_cfpc; extern const VMStateDescription vmstate_spapr_cap_sbbc; extern const VMStateDescription vmstate_spapr_cap_ibs; +extern const VMStateDescription vmstate_spapr_cap_hpt_maxpagesize; extern const VMStateDescription vmstate_spapr_cap_nested_kvm_hv; extern const VMStateDescription vmstate_spapr_cap_large_decr; extern const VMStateDescription vmstate_spapr_cap_ccf_assist; diff --git a/include/hw/ppc/spapr_irq.h b/include/hw/ppc/spapr_irq.h index b855f74e44..14cab73c9c 100644 --- a/include/hw/ppc/spapr_irq.h +++ b/include/hw/ppc/spapr_irq.h @@ -48,6 +48,8 @@ typedef struct SpaprIrq { void (*reset)(SpaprMachineState *spapr, Error **errp); void (*set_irq)(void *opaque, int srcno, int val); const char *(*get_nodename)(SpaprMachineState *spapr); + void (*init_emu)(SpaprMachineState *spapr, Error **errp); + void (*init_kvm)(SpaprMachineState *spapr, Error **errp); } SpaprIrq; extern SpaprIrq spapr_irq_xics; diff --git a/include/hw/ppc/spapr_xive.h b/include/hw/ppc/spapr_xive.h index fc3e9652f9..b26befcf6b 100644 --- a/include/hw/ppc/spapr_xive.h +++ b/include/hw/ppc/spapr_xive.h @@ -38,16 +38,55 @@ typedef struct SpaprXive { /* TIMA mapping address */ hwaddr tm_base; MemoryRegion tm_mmio; + + /* KVM support */ + int fd; + void *tm_mmap; + VMChangeStateEntry *change; } SpaprXive; +/* + * The sPAPR machine has a unique XIVE IC device. Assign a fixed value + * to the controller block id value. It can nevertheless be changed + * for testing purpose. + */ +#define SPAPR_XIVE_BLOCK_ID 0x0 + bool spapr_xive_irq_claim(SpaprXive *xive, uint32_t lisn, bool lsi); bool spapr_xive_irq_free(SpaprXive *xive, uint32_t lisn); void spapr_xive_pic_print_info(SpaprXive *xive, Monitor *mon); +int spapr_xive_post_load(SpaprXive *xive, int version_id); void spapr_xive_hcall_init(SpaprMachineState *spapr); void spapr_dt_xive(SpaprMachineState *spapr, uint32_t nr_servers, void *fdt, uint32_t phandle); void spapr_xive_set_tctx_os_cam(XiveTCTX *tctx); void spapr_xive_mmio_set_enabled(SpaprXive *xive, bool enable); +void spapr_xive_map_mmio(SpaprXive *xive); + +int spapr_xive_end_to_target(uint8_t end_blk, uint32_t end_idx, + uint32_t *out_server, uint8_t *out_prio); +void spapr_xive_init(SpaprXive *xive, Error **errp); + +/* + * KVM XIVE device helpers + */ +void kvmppc_xive_connect(SpaprXive *xive, Error **errp); +void kvmppc_xive_disconnect(SpaprXive *xive, Error **errp); +void kvmppc_xive_reset(SpaprXive *xive, Error **errp); +void kvmppc_xive_set_source_config(SpaprXive *xive, uint32_t lisn, XiveEAS *eas, + Error **errp); +void kvmppc_xive_sync_source(SpaprXive *xive, uint32_t lisn, Error **errp); +uint64_t kvmppc_xive_esb_rw(XiveSource *xsrc, int srcno, uint32_t offset, + uint64_t data, bool write); +void kvmppc_xive_set_queue_config(SpaprXive *xive, uint8_t end_blk, + uint32_t end_idx, XiveEND *end, + Error **errp); +void kvmppc_xive_get_queue_config(SpaprXive *xive, uint8_t end_blk, + uint32_t end_idx, XiveEND *end, + Error **errp); +void kvmppc_xive_synchronize_state(SpaprXive *xive, Error **errp); +int kvmppc_xive_pre_save(SpaprXive *xive); +int kvmppc_xive_post_load(SpaprXive *xive, int version_id); #endif /* PPC_SPAPR_XIVE_H */ diff --git a/include/hw/ppc/xics.h b/include/hw/ppc/xics.h index eb65ad7e43..d6f8e4c4c2 100644 --- a/include/hw/ppc/xics.h +++ b/include/hw/ppc/xics.h @@ -119,6 +119,7 @@ struct ICSState { uint32_t offset; ICSIRQState *irqs; XICSFabric *xics; + bool init; /* sPAPR ICS device initialized */ }; #define ICS_PROP_XICS "xics" diff --git a/include/hw/ppc/xics_spapr.h b/include/hw/ppc/xics_spapr.h index 15a8dcff66..2476b540ed 100644 --- a/include/hw/ppc/xics_spapr.h +++ b/include/hw/ppc/xics_spapr.h @@ -34,6 +34,7 @@ void spapr_dt_xics(SpaprMachineState *spapr, uint32_t nr_servers, void *fdt, uint32_t phandle); int xics_kvm_init(SpaprMachineState *spapr, Error **errp); +void xics_kvm_disconnect(SpaprMachineState *spapr, Error **errp); void xics_spapr_init(SpaprMachineState *spapr); #endif /* XICS_SPAPR_H */ diff --git a/include/hw/ppc/xive.h b/include/hw/ppc/xive.h index c4f27742ca..d872f96d1a 100644 --- a/include/hw/ppc/xive.h +++ b/include/hw/ppc/xive.h @@ -140,6 +140,7 @@ #ifndef PPC_XIVE_H #define PPC_XIVE_H +#include "sysemu/kvm.h" #include "hw/qdev-core.h" #include "hw/sysbus.h" #include "hw/ppc/xive_regs.h" @@ -194,6 +195,9 @@ typedef struct XiveSource { uint32_t esb_shift; MemoryRegion esb_mmio; + /* KVM support */ + void *esb_mmap; + XiveNotifier *xive; } XiveSource; @@ -423,4 +427,14 @@ static inline uint32_t xive_nvt_cam_line(uint8_t nvt_blk, uint32_t nvt_idx) return (nvt_blk << 19) | nvt_idx; } +/* + * KVM XIVE device helpers + */ + +void kvmppc_xive_source_reset_one(XiveSource *xsrc, int srcno, Error **errp); +void kvmppc_xive_source_set_irq(void *opaque, int srcno, int val); +void kvmppc_xive_cpu_connect(XiveTCTX *tctx, Error **errp); +void kvmppc_xive_cpu_synchronize_state(XiveTCTX *tctx, Error **errp); +void kvmppc_xive_cpu_get_state(XiveTCTX *tctx, Error **errp); + #endif /* PPC_XIVE_H */ diff --git a/include/hw/ppc/xive_regs.h b/include/hw/ppc/xive_regs.h index bf36678a24..1a8c5b5e64 100644 --- a/include/hw/ppc/xive_regs.h +++ b/include/hw/ppc/xive_regs.h @@ -208,6 +208,12 @@ typedef struct XiveEND { #define xive_end_is_backlog(end) (be32_to_cpu((end)->w0) & END_W0_BACKLOG) #define xive_end_is_escalate(end) (be32_to_cpu((end)->w0) & END_W0_ESCALATE_CTL) +static inline uint64_t xive_end_qaddr(XiveEND *end) +{ + return ((uint64_t) be32_to_cpu(end->w2) & 0x0fffffff) << 32 | + be32_to_cpu(end->w3); +} + /* Notification Virtual Target (NVT) */ typedef struct XiveNVT { uint32_t w0; diff --git a/include/hw/qdev-properties.h b/include/hw/qdev-properties.h index b6758c852e..1eae5ab056 100644 --- a/include/hw/qdev-properties.h +++ b/include/hw/qdev-properties.h @@ -28,6 +28,7 @@ extern const PropertyInfo qdev_prop_blockdev_on_error; extern const PropertyInfo qdev_prop_bios_chs_trans; extern const PropertyInfo qdev_prop_fdc_drive_type; extern const PropertyInfo qdev_prop_drive; +extern const PropertyInfo qdev_prop_drive_iothread; extern const PropertyInfo qdev_prop_netdev; extern const PropertyInfo qdev_prop_pci_devfn; extern const PropertyInfo qdev_prop_blocksize; @@ -198,6 +199,8 @@ extern const PropertyInfo qdev_prop_pcie_link_width; DEFINE_PROP(_n, _s, _f, qdev_prop_netdev, NICPeers) #define DEFINE_PROP_DRIVE(_n, _s, _f) \ DEFINE_PROP(_n, _s, _f, qdev_prop_drive, BlockBackend *) +#define DEFINE_PROP_DRIVE_IOTHREAD(_n, _s, _f) \ + DEFINE_PROP(_n, _s, _f, qdev_prop_drive_iothread, BlockBackend *) #define DEFINE_PROP_MACADDR(_n, _s, _f) \ DEFINE_PROP(_n, _s, _f, qdev_prop_macaddr, MACAddr) #define DEFINE_PROP_ON_OFF_AUTO(_n, _s, _f, _d) \ diff --git a/include/hw/riscv/sifive_e.h b/include/hw/riscv/sifive_e.h index f715f8606f..3b14eb7462 100644 --- a/include/hw/riscv/sifive_e.h +++ b/include/hw/riscv/sifive_e.h @@ -19,6 +19,8 @@ #ifndef HW_SIFIVE_E_H #define HW_SIFIVE_E_H +#include "hw/riscv/sifive_gpio.h" + #define TYPE_RISCV_E_SOC "riscv.sifive.e.soc" #define RISCV_E_SOC(obj) \ OBJECT_CHECK(SiFiveESoCState, (obj), TYPE_RISCV_E_SOC) @@ -30,6 +32,7 @@ typedef struct SiFiveESoCState { /*< public >*/ RISCVHartArrayState cpus; DeviceState *plic; + SIFIVEGPIOState gpio; } SiFiveESoCState; typedef struct SiFiveEState { @@ -63,8 +66,9 @@ enum { }; enum { - SIFIVE_E_UART0_IRQ = 3, - SIFIVE_E_UART1_IRQ = 4 + SIFIVE_E_UART0_IRQ = 3, + SIFIVE_E_UART1_IRQ = 4, + SIFIVE_E_GPIO0_IRQ0 = 8 }; #define SIFIVE_E_PLIC_HART_CONFIG "M" diff --git a/include/hw/riscv/sifive_gpio.h b/include/hw/riscv/sifive_gpio.h new file mode 100644 index 0000000000..fce03d6c41 --- /dev/null +++ b/include/hw/riscv/sifive_gpio.h @@ -0,0 +1,72 @@ +/* + * sifive System-on-Chip general purpose input/output register definition + * + * Copyright 2019 AdaCore + * + * Base on nrf51_gpio.c: + * + * Copyright 2018 Steffen Görtz <contrib@steffen-goertz.de> + * + * This code is licensed under the GPL version 2 or later. See + * the COPYING file in the top-level directory. + */ +#ifndef SIFIVE_GPIO_H +#define SIFIVE_GPIO_H + +#include "hw/sysbus.h" +#define TYPE_SIFIVE_GPIO "sifive_soc.gpio" +#define SIFIVE_GPIO(obj) OBJECT_CHECK(SIFIVEGPIOState, (obj), TYPE_SIFIVE_GPIO) + +#define SIFIVE_GPIO_PINS 32 + +#define SIFIVE_GPIO_SIZE 0x100 + +#define SIFIVE_GPIO_REG_VALUE 0x000 +#define SIFIVE_GPIO_REG_INPUT_EN 0x004 +#define SIFIVE_GPIO_REG_OUTPUT_EN 0x008 +#define SIFIVE_GPIO_REG_PORT 0x00C +#define SIFIVE_GPIO_REG_PUE 0x010 +#define SIFIVE_GPIO_REG_DS 0x014 +#define SIFIVE_GPIO_REG_RISE_IE 0x018 +#define SIFIVE_GPIO_REG_RISE_IP 0x01C +#define SIFIVE_GPIO_REG_FALL_IE 0x020 +#define SIFIVE_GPIO_REG_FALL_IP 0x024 +#define SIFIVE_GPIO_REG_HIGH_IE 0x028 +#define SIFIVE_GPIO_REG_HIGH_IP 0x02C +#define SIFIVE_GPIO_REG_LOW_IE 0x030 +#define SIFIVE_GPIO_REG_LOW_IP 0x034 +#define SIFIVE_GPIO_REG_IOF_EN 0x038 +#define SIFIVE_GPIO_REG_IOF_SEL 0x03C +#define SIFIVE_GPIO_REG_OUT_XOR 0x040 + +typedef struct SIFIVEGPIOState { + SysBusDevice parent_obj; + + MemoryRegion mmio; + + qemu_irq irq[SIFIVE_GPIO_PINS]; + qemu_irq output[SIFIVE_GPIO_PINS]; + + uint32_t value; /* Actual value of the pin */ + uint32_t input_en; + uint32_t output_en; + uint32_t port; /* Pin value requested by the user */ + uint32_t pue; + uint32_t ds; + uint32_t rise_ie; + uint32_t rise_ip; + uint32_t fall_ie; + uint32_t fall_ip; + uint32_t high_ie; + uint32_t high_ip; + uint32_t low_ie; + uint32_t low_ip; + uint32_t iof_en; + uint32_t iof_sel; + uint32_t out_xor; + uint32_t in; + uint32_t in_mask; + +} SIFIVEGPIOState; + +#endif diff --git a/include/hw/riscv/virt.h b/include/hw/riscv/virt.h index 568764b570..d01a1a85c4 100644 --- a/include/hw/riscv/virt.h +++ b/include/hw/riscv/virt.h @@ -74,9 +74,9 @@ enum { FDT_PLIC_ADDR_CELLS + FDT_PLIC_INT_CELLS) #if defined(TARGET_RISCV32) -#define VIRT_CPU TYPE_RISCV_CPU_RV32GCSU_V1_10_0 +#define VIRT_CPU TYPE_RISCV_CPU_BASE32 #elif defined(TARGET_RISCV64) -#define VIRT_CPU TYPE_RISCV_CPU_RV64GCSU_V1_10_0 +#define VIRT_CPU TYPE_RISCV_CPU_BASE64 #endif #endif diff --git a/include/hw/scsi/scsi.h b/include/hw/scsi/scsi.h index acef25faa4..426566a5c6 100644 --- a/include/hw/scsi/scsi.h +++ b/include/hw/scsi/scsi.h @@ -88,6 +88,7 @@ struct SCSIDevice int scsi_version; int default_scsi_version; bool needs_vpd_bl_emulation; + bool hba_supports_iothread; }; extern const VMStateDescription vmstate_scsi_device; diff --git a/include/hw/semihosting/console.h b/include/hw/semihosting/console.h new file mode 100644 index 0000000000..30e66ae20a --- /dev/null +++ b/include/hw/semihosting/console.h @@ -0,0 +1,38 @@ +/* + * Semihosting Console + * + * Copyright (c) 2019 Linaro Ltd + * + * SPDX-License-Identifier: GPL-2.0-or-later + */ + +#ifndef _SEMIHOST_CONSOLE_H_ +#define _SEMIHOST_CONSOLE_H_ + +/** + * qemu_semihosting_console_out: + * @env: CPUArchState + * @s: host address of guest string + * @len: length of string or 0 (string is null terminated) + * + * Send a guest string to the debug console. This may be the remote + * gdb session if a softmmu guest is currently being debugged. + * + * Returns: number of bytes written. + */ +int qemu_semihosting_console_out(CPUArchState *env, target_ulong s, int len); + +/** + * qemu_semihosting_log_out: + * @s: pointer to string + * @len: length of string + * + * Send a string to the debug output. Unlike console_out these strings + * can't be sent to a remote gdb instance as they don't exist in guest + * memory. + * + * Returns: number of bytes written + */ +int qemu_semihosting_log_out(const char *s, int len); + +#endif /* _SEMIHOST_CONSOLE_H_ */ diff --git a/include/exec/semihost.h b/include/hw/semihosting/semihost.h index 5980939c7b..60fc42d851 100644 --- a/include/exec/semihost.h +++ b/include/hw/semihosting/semihost.h @@ -51,12 +51,23 @@ static inline const char *semihosting_get_cmdline(void) { return NULL; } -#else + +static inline Chardev *semihosting_get_chardev(void) +{ + return NULL; +} +#else /* !CONFIG_USER_ONLY */ bool semihosting_enabled(void); SemihostingTarget semihosting_get_target(void); const char *semihosting_get_arg(int i); int semihosting_get_argc(void); const char *semihosting_get_cmdline(void); -#endif +void semihosting_arg_fallback(const char *file, const char *cmd); +Chardev *semihosting_get_chardev(void); +/* for vl.c hooks */ +void qemu_semihosting_enable(void); +int qemu_semihosting_config_options(const char *opt); +void qemu_semihosting_connect_chardevs(void); +#endif /* CONFIG_USER_ONLY */ -#endif +#endif /* SEMIHOST_H */ diff --git a/include/hw/sysbus.h b/include/hw/sysbus.h index 1aedcf05c9..4c668fbbdc 100644 --- a/include/hw/sysbus.h +++ b/include/hw/sysbus.h @@ -89,6 +89,7 @@ qemu_irq sysbus_get_connected_irq(SysBusDevice *dev, int n); void sysbus_mmio_map(SysBusDevice *dev, int n, hwaddr addr); void sysbus_mmio_map_overlap(SysBusDevice *dev, int n, hwaddr addr, int priority); +void sysbus_mmio_unmap(SysBusDevice *dev, int n); void sysbus_add_io(SysBusDevice *dev, hwaddr addr, MemoryRegion *mem); MemoryRegion *sysbus_address_space(SysBusDevice *dev); diff --git a/include/hw/virtio/vhost-backend.h b/include/hw/virtio/vhost-backend.h index d6632a18e6..6f6670783f 100644 --- a/include/hw/virtio/vhost-backend.h +++ b/include/hw/virtio/vhost-backend.h @@ -170,4 +170,6 @@ int vhost_backend_invalidate_device_iotlb(struct vhost_dev *dev, int vhost_backend_handle_iotlb_msg(struct vhost_dev *dev, struct vhost_iotlb_msg *imsg); +int vhost_user_gpu_set_socket(struct vhost_dev *dev, int fd); + #endif /* VHOST_BACKEND_H */ diff --git a/include/hw/virtio/vhost-scsi-common.h b/include/hw/virtio/vhost-scsi-common.h index 57fb1d87b5..4eab767ee8 100644 --- a/include/hw/virtio/vhost-scsi-common.h +++ b/include/hw/virtio/vhost-scsi-common.h @@ -36,6 +36,7 @@ typedef struct VHostSCSICommon { int target; int lun; uint64_t host_features; + bool migratable; } VHostSCSICommon; int vhost_scsi_common_start(VHostSCSICommon *vsc); diff --git a/include/hw/virtio/virtio-gpu-bswap.h b/include/hw/virtio/virtio-gpu-bswap.h new file mode 100644 index 0000000000..38d12160f6 --- /dev/null +++ b/include/hw/virtio/virtio-gpu-bswap.h @@ -0,0 +1,61 @@ +/* + * Virtio GPU Device + * + * Copyright Red Hat, Inc. 2013-2014 + * + * Authors: + * Dave Airlie <airlied@redhat.com> + * Gerd Hoffmann <kraxel@redhat.com> + * + * This work is licensed under the terms of the GNU GPL, version 2 or later. + * See the COPYING file in the top-level directory. + */ + +#ifndef HW_VIRTIO_GPU_BSWAP_H +#define HW_VIRTIO_GPU_BSWAP_H + +#include "qemu/bswap.h" + +static inline void +virtio_gpu_ctrl_hdr_bswap(struct virtio_gpu_ctrl_hdr *hdr) +{ + le32_to_cpus(&hdr->type); + le32_to_cpus(&hdr->flags); + le64_to_cpus(&hdr->fence_id); + le32_to_cpus(&hdr->ctx_id); + le32_to_cpus(&hdr->padding); +} + +static inline void +virtio_gpu_bswap_32(void *ptr, size_t size) +{ +#ifdef HOST_WORDS_BIGENDIAN + + size_t i; + struct virtio_gpu_ctrl_hdr *hdr = (struct virtio_gpu_ctrl_hdr *) ptr; + + virtio_gpu_ctrl_hdr_bswap(hdr); + + i = sizeof(struct virtio_gpu_ctrl_hdr); + while (i < size) { + le32_to_cpus((uint32_t *)(ptr + i)); + i = i + sizeof(uint32_t); + } + +#endif +} + +static inline void +virtio_gpu_t2d_bswap(struct virtio_gpu_transfer_to_host_2d *t2d) +{ + virtio_gpu_ctrl_hdr_bswap(&t2d->hdr); + le32_to_cpus(&t2d->r.x); + le32_to_cpus(&t2d->r.y); + le32_to_cpus(&t2d->r.width); + le32_to_cpus(&t2d->r.height); + le64_to_cpus(&t2d->offset); + le32_to_cpus(&t2d->resource_id); + le32_to_cpus(&t2d->padding); +} + +#endif diff --git a/include/hw/virtio/virtio-gpu-pci.h b/include/hw/virtio/virtio-gpu-pci.h new file mode 100644 index 0000000000..2f69b5a9cc --- /dev/null +++ b/include/hw/virtio/virtio-gpu-pci.h @@ -0,0 +1,40 @@ +/* + * Virtio GPU PCI Device + * + * Copyright Red Hat, Inc. 2013-2014 + * + * Authors: + * Dave Airlie <airlied@redhat.com> + * Gerd Hoffmann <kraxel@redhat.com> + * + * This work is licensed under the terms of the GNU GPL, version 2. + * See the COPYING file in the top-level directory. + */ + +#ifndef HW_VIRTIO_GPU_PCI_H +#define HW_VIRTIO_GPU_PCI_H + +#include "hw/virtio/virtio-pci.h" +#include "hw/virtio/virtio-gpu.h" + +typedef struct VirtIOGPUPCIBase VirtIOGPUPCIBase; + +/* + * virtio-gpu-pci-base: This extends VirtioPCIProxy. + */ +#define TYPE_VIRTIO_GPU_PCI_BASE "virtio-gpu-pci-base" +#define VIRTIO_GPU_PCI_BASE(obj) \ + OBJECT_CHECK(VirtIOGPUPCIBase, (obj), TYPE_VIRTIO_GPU_PCI_BASE) + +struct VirtIOGPUPCIBase { + VirtIOPCIProxy parent_obj; + VirtIOGPUBase *vgpu; +}; + +/* to share between PCI and VGA */ +#define DEFINE_VIRTIO_GPU_PCI_PROPERTIES(_state) \ + DEFINE_PROP_BIT("ioeventfd", _state, flags, \ + VIRTIO_PCI_FLAG_USE_IOEVENTFD_BIT, false), \ + DEFINE_PROP_UINT32("vectors", _state, nvectors, 3) + +#endif /* HW_VIRTIO_GPU_PCI_H */ diff --git a/include/hw/virtio/virtio-gpu-pixman.h b/include/hw/virtio/virtio-gpu-pixman.h new file mode 100644 index 0000000000..4dba782758 --- /dev/null +++ b/include/hw/virtio/virtio-gpu-pixman.h @@ -0,0 +1,45 @@ +/* + * Virtio GPU Device + * + * Copyright Red Hat, Inc. 2013-2014 + * + * Authors: + * Dave Airlie <airlied@redhat.com> + * Gerd Hoffmann <kraxel@redhat.com> + * + * This work is licensed under the terms of the GNU GPL, version 2 or later. + * See the COPYING file in the top-level directory. + */ + +#ifndef HW_VIRTIO_GPU_PIXMAN_H +#define HW_VIRTIO_GPU_PIXMAN_H + +#include "ui/qemu-pixman.h" +#include "standard-headers/linux/virtio_gpu.h" + +static inline pixman_format_code_t +virtio_gpu_get_pixman_format(uint32_t virtio_gpu_format) +{ + switch (virtio_gpu_format) { + case VIRTIO_GPU_FORMAT_B8G8R8X8_UNORM: + return PIXMAN_BE_b8g8r8x8; + case VIRTIO_GPU_FORMAT_B8G8R8A8_UNORM: + return PIXMAN_BE_b8g8r8a8; + case VIRTIO_GPU_FORMAT_X8R8G8B8_UNORM: + return PIXMAN_BE_x8r8g8b8; + case VIRTIO_GPU_FORMAT_A8R8G8B8_UNORM: + return PIXMAN_BE_a8r8g8b8; + case VIRTIO_GPU_FORMAT_R8G8B8X8_UNORM: + return PIXMAN_BE_r8g8b8x8; + case VIRTIO_GPU_FORMAT_R8G8B8A8_UNORM: + return PIXMAN_BE_r8g8b8a8; + case VIRTIO_GPU_FORMAT_X8B8G8R8_UNORM: + return PIXMAN_BE_x8b8g8r8; + case VIRTIO_GPU_FORMAT_A8B8G8R8_UNORM: + return PIXMAN_BE_a8b8g8r8; + default: + return 0; + } +} + +#endif diff --git a/include/hw/virtio/virtio-gpu.h b/include/hw/virtio/virtio-gpu.h index 60425c5d58..8ecac1987a 100644 --- a/include/hw/virtio/virtio-gpu.h +++ b/include/hw/virtio/virtio-gpu.h @@ -19,13 +19,24 @@ #include "ui/console.h" #include "hw/virtio/virtio.h" #include "qemu/log.h" +#include "sysemu/vhost-user-backend.h" #include "standard-headers/linux/virtio_gpu.h" +#define TYPE_VIRTIO_GPU_BASE "virtio-gpu-base" +#define VIRTIO_GPU_BASE(obj) \ + OBJECT_CHECK(VirtIOGPUBase, (obj), TYPE_VIRTIO_GPU_BASE) +#define VIRTIO_GPU_BASE_GET_CLASS(obj) \ + OBJECT_GET_CLASS(VirtIOGPUBaseClass, obj, TYPE_VIRTIO_GPU_BASE) +#define VIRTIO_GPU_BASE_CLASS(klass) \ + OBJECT_CLASS_CHECK(VirtIOGPUBaseClass, klass, TYPE_VIRTIO_GPU_BASE) + #define TYPE_VIRTIO_GPU "virtio-gpu-device" #define VIRTIO_GPU(obj) \ OBJECT_CHECK(VirtIOGPU, (obj), TYPE_VIRTIO_GPU) +#define TYPE_VHOST_USER_GPU "vhost-user-gpu" + #define VIRTIO_ID_GPU 16 struct virtio_gpu_simple_resource { @@ -58,7 +69,7 @@ struct virtio_gpu_requested_state { int x, y; }; -enum virtio_gpu_conf_flags { +enum virtio_gpu_base_conf_flags { VIRTIO_GPU_FLAG_VIRGL_ENABLED = 1, VIRTIO_GPU_FLAG_STATS_ENABLED, VIRTIO_GPU_FLAG_EDID_ENABLED, @@ -71,8 +82,7 @@ enum virtio_gpu_conf_flags { #define virtio_gpu_edid_enabled(_cfg) \ (_cfg.flags & (1 << VIRTIO_GPU_FLAG_EDID_ENABLED)) -struct virtio_gpu_conf { - uint64_t max_hostmem; +struct virtio_gpu_base_conf { uint32_t max_outputs; uint32_t flags; uint32_t xres; @@ -88,31 +98,55 @@ struct virtio_gpu_ctrl_command { QTAILQ_ENTRY(virtio_gpu_ctrl_command) next; }; -typedef struct VirtIOGPU { +typedef struct VirtIOGPUBase { VirtIODevice parent_obj; - QEMUBH *ctrl_bh; - QEMUBH *cursor_bh; + Error *migration_blocker; + + struct virtio_gpu_base_conf conf; + struct virtio_gpu_config virtio_config; + + bool use_virgl_renderer; + int renderer_blocked; + int enable; + + struct virtio_gpu_scanout scanout[VIRTIO_GPU_MAX_SCANOUTS]; + + int enabled_output_bitmask; + struct virtio_gpu_requested_state req_state[VIRTIO_GPU_MAX_SCANOUTS]; +} VirtIOGPUBase; + +typedef struct VirtIOGPUBaseClass { + VirtioDeviceClass parent; + + void (*gl_unblock)(VirtIOGPUBase *g); +} VirtIOGPUBaseClass; + +#define VIRTIO_GPU_BASE_PROPERTIES(_state, _conf) \ + DEFINE_PROP_UINT32("max_outputs", _state, _conf.max_outputs, 1), \ + DEFINE_PROP_BIT("edid", _state, _conf.flags, \ + VIRTIO_GPU_FLAG_EDID_ENABLED, false), \ + DEFINE_PROP_UINT32("xres", _state, _conf.xres, 1024), \ + DEFINE_PROP_UINT32("yres", _state, _conf.yres, 768) + +typedef struct VirtIOGPU { + VirtIOGPUBase parent_obj; + + uint64_t conf_max_hostmem; + VirtQueue *ctrl_vq; VirtQueue *cursor_vq; - int enable; + QEMUBH *ctrl_bh; + QEMUBH *cursor_bh; QTAILQ_HEAD(, virtio_gpu_simple_resource) reslist; QTAILQ_HEAD(, virtio_gpu_ctrl_command) cmdq; QTAILQ_HEAD(, virtio_gpu_ctrl_command) fenceq; - struct virtio_gpu_scanout scanout[VIRTIO_GPU_MAX_SCANOUTS]; - struct virtio_gpu_requested_state req_state[VIRTIO_GPU_MAX_SCANOUTS]; - - struct virtio_gpu_conf conf; uint64_t hostmem; - int enabled_output_bitmask; - struct virtio_gpu_config virtio_config; - bool use_virgl_renderer; bool renderer_inited; - int renderer_blocked; bool renderer_reset; QEMUTimer *fence_poll; QEMUTimer *print_stats; @@ -124,17 +158,19 @@ typedef struct VirtIOGPU { uint32_t req_3d; uint32_t bytes_3d; } stats; - - Error *migration_blocker; } VirtIOGPU; -extern const GraphicHwOps virtio_gpu_ops; +typedef struct VhostUserGPU { + VirtIOGPUBase parent_obj; + + VhostUserBackend *vhost; + int vhost_gpu_fd; /* closed by the chardev */ + CharBackend vhost_chr; + QemuDmaBuf dmabuf[VIRTIO_GPU_MAX_SCANOUTS]; + bool backend_blocked; +} VhostUserGPU; -/* to share between PCI and VGA */ -#define DEFINE_VIRTIO_GPU_PCI_PROPERTIES(_state) \ - DEFINE_PROP_BIT("ioeventfd", _state, flags, \ - VIRTIO_PCI_FLAG_USE_IOEVENTFD_BIT, false), \ - DEFINE_PROP_UINT32("vectors", _state, nvectors, 3) +extern const GraphicHwOps virtio_gpu_ops; #define VIRTIO_GPU_FILL_CMD(out) do { \ size_t s; \ @@ -148,6 +184,15 @@ extern const GraphicHwOps virtio_gpu_ops; } \ } while (0) +/* virtio-gpu-base.c */ +bool virtio_gpu_base_device_realize(DeviceState *qdev, + VirtIOHandleOutput ctrl_cb, + VirtIOHandleOutput cursor_cb, + Error **errp); +void virtio_gpu_base_reset(VirtIOGPUBase *g); +void virtio_gpu_base_fill_display_info(VirtIOGPUBase *g, + struct virtio_gpu_resp_display_info *dpy_info); + /* virtio-gpu.c */ void virtio_gpu_ctrl_response(VirtIOGPU *g, struct virtio_gpu_ctrl_command *cmd, @@ -175,4 +220,5 @@ void virtio_gpu_virgl_fence_poll(VirtIOGPU *g); void virtio_gpu_virgl_reset(VirtIOGPU *g); int virtio_gpu_virgl_init(VirtIOGPU *g); int virtio_gpu_virgl_get_num_capsets(VirtIOGPU *g); + #endif diff --git a/include/sysemu/accel.h b/include/sysemu/accel.h index 70e9e2f2a1..81293cdb08 100644 --- a/include/sysemu/accel.h +++ b/include/sysemu/accel.h @@ -36,7 +36,6 @@ typedef struct AccelClass { ObjectClass parent_class; /*< public >*/ - const char *opt_name; const char *name; int (*init_machine)(MachineState *ms); void (*setup_post)(MachineState *ms, AccelState *accel); diff --git a/include/sysemu/block-backend.h b/include/sysemu/block-backend.h index 938de34fe9..733c4957eb 100644 --- a/include/sysemu/block-backend.h +++ b/include/sysemu/block-backend.h @@ -76,7 +76,7 @@ typedef struct BlockBackendPublic { ThrottleGroupMember throttle_group_member; } BlockBackendPublic; -BlockBackend *blk_new(uint64_t perm, uint64_t shared_perm); +BlockBackend *blk_new(AioContext *ctx, uint64_t perm, uint64_t shared_perm); BlockBackend *blk_new_open(const char *filename, const char *reference, QDict *options, int flags, Error **errp); int blk_get_refcnt(BlockBackend *blk); @@ -208,7 +208,8 @@ void blk_op_unblock(BlockBackend *blk, BlockOpType op, Error *reason); void blk_op_block_all(BlockBackend *blk, Error *reason); void blk_op_unblock_all(BlockBackend *blk, Error *reason); AioContext *blk_get_aio_context(BlockBackend *blk); -void blk_set_aio_context(BlockBackend *blk, AioContext *new_context); +int blk_set_aio_context(BlockBackend *blk, AioContext *new_context, + Error **errp); void blk_add_aio_context_notifier(BlockBackend *blk, void (*attached_aio_context)(AioContext *new_context, void *opaque), void (*detach_aio_context)(void *opaque), void *opaque); diff --git a/include/sysemu/sysemu.h b/include/sysemu/sysemu.h index 5f133cae83..61579ae71e 100644 --- a/include/sysemu/sysemu.h +++ b/include/sysemu/sysemu.h @@ -193,5 +193,6 @@ extern QemuOptsList qemu_nic_opts; extern QemuOptsList qemu_net_opts; extern QemuOptsList qemu_global_opts; extern QemuOptsList qemu_mon_opts; +extern QemuOptsList qemu_semihosting_config_opts; #endif diff --git a/include/ui/console.h b/include/ui/console.h index fef900db76..f981696848 100644 --- a/include/ui/console.h +++ b/include/ui/console.h @@ -175,6 +175,7 @@ typedef struct QemuDmaBuf { uint32_t height; uint32_t stride; uint32_t fourcc; + uint64_t modifier; uint32_t texture; bool y0_top; } QemuDmaBuf; diff --git a/include/ui/egl-helpers.h b/include/ui/egl-helpers.h index b976cb8728..d714127799 100644 --- a/include/ui/egl-helpers.h +++ b/include/ui/egl-helpers.h @@ -36,7 +36,8 @@ extern struct gbm_device *qemu_egl_rn_gbm_dev; extern EGLContext qemu_egl_rn_ctx; int egl_rendernode_init(const char *rendernode, DisplayGLMode mode); -int egl_get_fd_for_texture(uint32_t tex_id, EGLint *stride, EGLint *fourcc); +int egl_get_fd_for_texture(uint32_t tex_id, EGLint *stride, EGLint *fourcc, + EGLuint64KHR *modifier); void egl_dmabuf_import_texture(QemuDmaBuf *dmabuf); void egl_dmabuf_release_texture(QemuDmaBuf *dmabuf); diff --git a/linux-user/Makefile.objs b/linux-user/Makefile.objs index 769b8d8336..285c5dfa17 100644 --- a/linux-user/Makefile.objs +++ b/linux-user/Makefile.objs @@ -6,4 +6,6 @@ obj-y = main.o syscall.o strace.o mmap.o signal.o \ obj-$(TARGET_HAS_BFLT) += flatload.o obj-$(TARGET_I386) += vm86.o obj-$(TARGET_ARM) += arm/nwfpe/ +obj-$(TARGET_ARM) += arm/semihost.o +obj-$(TARGET_AARCH64) += arm/semihost.o obj-$(TARGET_M68K) += m68k-sim.o diff --git a/linux-user/arm/semihost.c b/linux-user/arm/semihost.c new file mode 100644 index 0000000000..9554102a85 --- /dev/null +++ b/linux-user/arm/semihost.c @@ -0,0 +1,24 @@ +/* + * ARM Semihosting Console Support + * + * Copyright (c) 2019 Linaro Ltd + * + * Currently ARM is unique in having support for semihosting support + * in linux-user. So for now we implement the common console API but + * just for arm linux-user. + * + * SPDX-License-Identifier: GPL-2.0-or-later + */ + +#include "qemu/osdep.h" +#include "cpu.h" +#include "hw/semihosting/console.h" +#include "qemu.h" + +int qemu_semihosting_console_out(CPUArchState *env, target_ulong addr, int len) +{ + void *s = lock_user_string(addr); + len = write(STDERR_FILENO, s, len ? len : strlen(s)); + unlock_user(s, addr, 0); + return len; +} diff --git a/linux-user/elfload.c b/linux-user/elfload.c index a57b7049dd..5451d262ec 100644 --- a/linux-user/elfload.c +++ b/linux-user/elfload.c @@ -1308,6 +1308,34 @@ static inline void init_thread(struct target_pt_regs *regs, #define ELF_DATA ELFDATA2MSB #define ELF_ARCH EM_S390 +#include "elf.h" + +#define ELF_HWCAP get_elf_hwcap() + +#define GET_FEATURE(_feat, _hwcap) \ + do { if (s390_has_feat(_feat)) { hwcap |= _hwcap; } } while (0) + +static uint32_t get_elf_hwcap(void) +{ + /* + * Let's assume we always have esan3 and zarch. + * 31-bit processes can use 64-bit registers (high gprs). + */ + uint32_t hwcap = HWCAP_S390_ESAN3 | HWCAP_S390_ZARCH | HWCAP_S390_HIGH_GPRS; + + GET_FEATURE(S390_FEAT_STFLE, HWCAP_S390_STFLE); + GET_FEATURE(S390_FEAT_MSA, HWCAP_S390_MSA); + GET_FEATURE(S390_FEAT_LONG_DISPLACEMENT, HWCAP_S390_LDISP); + GET_FEATURE(S390_FEAT_EXTENDED_IMMEDIATE, HWCAP_S390_EIMM); + if (s390_has_feat(S390_FEAT_EXTENDED_TRANSLATION_3) && + s390_has_feat(S390_FEAT_ETF3_ENH)) { + hwcap |= HWCAP_S390_ETF3EH; + } + GET_FEATURE(S390_FEAT_VECTOR, HWCAP_S390_VXRS); + + return hwcap; +} + static inline void init_thread(struct target_pt_regs *regs, struct image_info *infop) { regs->psw.addr = infop->entry; diff --git a/linux-user/riscv/target_elf.h b/linux-user/riscv/target_elf.h index a6716a6aac..9dd65652ee 100644 --- a/linux-user/riscv/target_elf.h +++ b/linux-user/riscv/target_elf.h @@ -9,6 +9,7 @@ #define RISCV_TARGET_ELF_H static inline const char *cpu_get_model(uint32_t eflags) { + /* TYPE_RISCV_CPU_ANY */ return "any"; } #endif diff --git a/linux-user/s390x/signal.c b/linux-user/s390x/signal.c index 3d3cb67bbe..ecfa2a14a9 100644 --- a/linux-user/s390x/signal.c +++ b/linux-user/s390x/signal.c @@ -123,7 +123,7 @@ static void save_sigregs(CPUS390XState *env, target_sigregs *sregs) */ //save_fp_regs(¤t->thread.fp_regs); FIXME for (i = 0; i < 16; i++) { - __put_user(get_freg(env, i)->ll, &sregs->fpregs.fprs[i]); + __put_user(*get_freg(env, i), &sregs->fpregs.fprs[i]); } } @@ -254,7 +254,7 @@ restore_sigregs(CPUS390XState *env, target_sigregs *sc) __get_user(env->aregs[i], &sc->regs.acrs[i]); } for (i = 0; i < 16; i++) { - __get_user(get_freg(env, i)->ll, &sc->fpregs.fprs[i]); + __get_user(*get_freg(env, i), &sc->fpregs.fprs[i]); } return err; diff --git a/linux-user/syscall.c b/linux-user/syscall.c index 55212585e0..5e29e675e9 100644 --- a/linux-user/syscall.c +++ b/linux-user/syscall.c @@ -763,14 +763,7 @@ safe_syscall2(int, nanosleep, const struct timespec *, req, safe_syscall4(int, clock_nanosleep, const clockid_t, clock, int, flags, const struct timespec *, req, struct timespec *, rem) #endif -#ifdef __NR_msgsnd -safe_syscall4(int, msgsnd, int, msgid, const void *, msgp, size_t, sz, - int, flags) -safe_syscall5(int, msgrcv, int, msgid, void *, msgp, size_t, sz, - long, msgtype, int, flags) -safe_syscall4(int, semtimedop, int, semid, struct sembuf *, tsops, - unsigned, nsops, const struct timespec *, timeout) -#else +#if !defined(__NR_msgsnd) || !defined(__NR_msgrcv) || !defined(__NR_semtimedop) /* This host kernel architecture uses a single ipc syscall; fake up * wrappers for the sub-operations to hide this implementation detail. * Annoyingly we can't include linux/ipc.h to get the constant definitions @@ -785,14 +778,29 @@ safe_syscall4(int, semtimedop, int, semid, struct sembuf *, tsops, safe_syscall6(int, ipc, int, call, long, first, long, second, long, third, void *, ptr, long, fifth) +#endif +#ifdef __NR_msgsnd +safe_syscall4(int, msgsnd, int, msgid, const void *, msgp, size_t, sz, + int, flags) +#else static int safe_msgsnd(int msgid, const void *msgp, size_t sz, int flags) { return safe_ipc(Q_IPCCALL(0, Q_MSGSND), msgid, sz, flags, (void *)msgp, 0); } +#endif +#ifdef __NR_msgrcv +safe_syscall5(int, msgrcv, int, msgid, void *, msgp, size_t, sz, + long, msgtype, int, flags) +#else static int safe_msgrcv(int msgid, void *msgp, size_t sz, long type, int flags) { return safe_ipc(Q_IPCCALL(1, Q_MSGRCV), msgid, sz, flags, msgp, type); } +#endif +#ifdef __NR_semtimedop +safe_syscall4(int, semtimedop, int, semid, struct sembuf *, tsops, + unsigned, nsops, const struct timespec *, timeout) +#else static int safe_semtimedop(int semid, struct sembuf *tsops, unsigned nsops, const struct timespec *timeout) { @@ -2027,14 +2027,6 @@ void memory_region_set_log(MemoryRegion *mr, bool log, unsigned client) memory_region_transaction_commit(); } -bool memory_region_get_dirty(MemoryRegion *mr, hwaddr addr, - hwaddr size, unsigned client) -{ - assert(mr->ram_block); - return cpu_physical_memory_get_dirty(memory_region_get_ram_addr(mr) + addr, - size, client); -} - void memory_region_set_dirty(MemoryRegion *mr, hwaddr addr, hwaddr size) { diff --git a/migration/block-dirty-bitmap.c b/migration/block-dirty-bitmap.c index d1bb863cb6..4a896a09eb 100644 --- a/migration/block-dirty-bitmap.c +++ b/migration/block-dirty-bitmap.c @@ -273,7 +273,6 @@ static int init_dirty_bitmap_migration(void) BlockDriverState *bs; BdrvDirtyBitmap *bitmap; DirtyBitmapMigBitmapState *dbms; - BdrvNextIterator it; Error *local_err = NULL; dirty_bitmap_mig_state.bulk_completed = false; @@ -281,13 +280,8 @@ static int init_dirty_bitmap_migration(void) dirty_bitmap_mig_state.prev_bitmap = NULL; dirty_bitmap_mig_state.no_bitmaps = false; - for (bs = bdrv_first(&it); bs; bs = bdrv_next(&it)) { - const char *drive_name = bdrv_get_device_or_node_name(bs); - - /* skip automatically inserted nodes */ - while (bs && bs->drv && bs->implicit) { - bs = backing_bs(bs); - } + for (bs = bdrv_next_all_states(NULL); bs; bs = bdrv_next_all_states(bs)) { + const char *name = bdrv_get_device_or_node_name(bs); for (bitmap = bdrv_dirty_bitmap_next(bs, NULL); bitmap; bitmap = bdrv_dirty_bitmap_next(bs, bitmap)) @@ -296,7 +290,7 @@ static int init_dirty_bitmap_migration(void) continue; } - if (drive_name == NULL) { + if (!name || strcmp(name, "") == 0) { error_report("Found bitmap '%s' in unnamed node %p. It can't " "be migrated", bdrv_dirty_bitmap_name(bitmap), bs); goto fail; @@ -313,7 +307,7 @@ static int init_dirty_bitmap_migration(void) dbms = g_new0(DirtyBitmapMigBitmapState, 1); dbms->bs = bs; - dbms->node_name = drive_name; + dbms->node_name = name; dbms->bitmap = bitmap; dbms->total_sectors = bdrv_nb_sectors(bs); dbms->sectors_per_chunk = CHUNK_SIZE * 8 * diff --git a/migration/block.c b/migration/block.c index 83c633fb3f..91f98ef44a 100644 --- a/migration/block.c +++ b/migration/block.c @@ -417,7 +417,8 @@ static int init_blk_migration(QEMUFile *f) } bmds = g_new0(BlkMigDevState, 1); - bmds->blk = blk_new(BLK_PERM_CONSISTENT_READ, BLK_PERM_ALL); + bmds->blk = blk_new(qemu_get_aio_context(), + BLK_PERM_CONSISTENT_READ, BLK_PERM_ALL); bmds->blk_name = g_strdup(bdrv_get_device_name(bs)); bmds->bulk_completed = 0; bmds->total_sectors = sectors; diff --git a/migration/fd.c b/migration/fd.c index a7c13df4ad..0a29ecdebf 100644 --- a/migration/fd.c +++ b/migration/fd.c @@ -52,12 +52,14 @@ static gboolean fd_accept_incoming_migration(QIOChannel *ioc, return G_SOURCE_REMOVE; } -void fd_start_incoming_migration(const char *infd, Error **errp) +void fd_start_incoming_migration(const char *fdname, Error **errp) { QIOChannel *ioc; - int fd; + int fd = monitor_fd_param(cur_mon, fdname, errp); + if (fd == -1) { + return; + } - fd = strtol(infd, NULL, 0); trace_migration_fd_incoming(fd); ioc = qio_channel_new_fd(fd, errp); diff --git a/migration/fd.h b/migration/fd.h index a14a63ce2e..b901bc014e 100644 --- a/migration/fd.h +++ b/migration/fd.h @@ -16,7 +16,7 @@ #ifndef QEMU_MIGRATION_FD_H #define QEMU_MIGRATION_FD_H -void fd_start_incoming_migration(const char *path, Error **errp); +void fd_start_incoming_migration(const char *fdname, Error **errp); void fd_start_outgoing_migration(MigrationState *s, const char *fdname, Error **errp); diff --git a/migration/ram.c b/migration/ram.c index 4c60869226..908517fc2b 100644 --- a/migration/ram.c +++ b/migration/ram.c @@ -661,8 +661,6 @@ typedef struct { uint64_t num_packets; /* pages sent through this channel */ uint64_t num_pages; - /* syncs main thread and channels */ - QemuSemaphore sem_sync; } MultiFDSendParams; typedef struct { @@ -894,8 +892,6 @@ static int multifd_recv_unfill_packet(MultiFDRecvParams *p, Error **errp) struct { MultiFDSendParams *params; - /* number of created threads */ - int count; /* array of pages to sent */ MultiFDPages_t *pages; /* syncs main thread and channels */ @@ -1027,7 +1023,6 @@ void multifd_save_cleanup(void) p->c = NULL; qemu_mutex_destroy(&p->mutex); qemu_sem_destroy(&p->sem); - qemu_sem_destroy(&p->sem_sync); g_free(p->name); p->name = NULL; multifd_pages_clear(p->pages); @@ -1174,8 +1169,6 @@ static void multifd_new_send_channel_async(QIOTask *task, gpointer opaque) p->running = true; qemu_thread_create(&p->thread, p->name, multifd_send_thread, p, QEMU_THREAD_JOINABLE); - - atomic_inc(&multifd_send_state->count); } } @@ -1191,7 +1184,6 @@ int multifd_save_setup(void) thread_count = migrate_multifd_channels(); multifd_send_state = g_malloc0(sizeof(*multifd_send_state)); multifd_send_state->params = g_new0(MultiFDSendParams, thread_count); - atomic_set(&multifd_send_state->count, 0); multifd_send_state->pages = multifd_pages_init(page_count); qemu_sem_init(&multifd_send_state->sem_sync, 0); qemu_sem_init(&multifd_send_state->channels_ready, 0); @@ -1201,7 +1193,6 @@ int multifd_save_setup(void) qemu_mutex_init(&p->mutex); qemu_sem_init(&p->sem, 0); - qemu_sem_init(&p->sem_sync, 0); p->quit = false; p->pending_job = 0; p->id = i; @@ -2236,7 +2227,7 @@ static RAMBlock *unqueue_page(RAMState *rs, ram_addr_t *offset) } /** - * get_queued_page: unqueue a page from the postocpy requests + * get_queued_page: unqueue a page from the postcopy requests * * Skips pages that are already sent (!dirty) * @@ -3182,11 +3173,11 @@ static int ram_state_init(RAMState **rsp) QSIMPLEQ_INIT(&(*rsp)->src_page_requests); /* - * Count the total number of pages used by ram blocks not including any - * gaps due to alignment or unplugs. + * This must match with the initial values of dirty bitmap. + * Currently we initialize the dirty bitmap to all zeros so + * here the total dirty page count is zero. */ - (*rsp)->migration_dirty_pages = ram_bytes_total() >> TARGET_PAGE_BITS; - + (*rsp)->migration_dirty_pages = 0; ram_state_reset(*rsp); return 0; @@ -3201,8 +3192,16 @@ static void ram_list_init_bitmaps(void) if (ram_bytes_total()) { RAMBLOCK_FOREACH_NOT_IGNORED(block) { pages = block->max_length >> TARGET_PAGE_BITS; + /* + * The initial dirty bitmap for migration must be set with all + * ones to make sure we'll migrate every guest RAM page to + * destination. + * Here we didn't set RAMBlock.bmap simply because it is already + * set in ram_list.dirty_memory[DIRTY_MEMORY_MIGRATION] in + * ram_block_add, and that's where we'll sync the dirty bitmaps. + * Here setting RAMBlock.bmap would be fine too but not necessary. + */ block->bmap = bitmap_new(pages); - bitmap_set(block->bmap, 0, pages); if (migrate_postcopy_ram()) { block->unsentmap = bitmap_new(pages); bitmap_set(block->unsentmap, 0, pages); diff --git a/nbd/server.c b/nbd/server.c index e21bd501dc..aeca3893fe 100644 --- a/nbd/server.c +++ b/nbd/server.c @@ -1484,13 +1484,15 @@ NBDExport *nbd_export_new(BlockDriverState *bs, uint64_t dev_offset, if ((nbdflags & NBD_FLAG_READ_ONLY) == 0) { perm |= BLK_PERM_WRITE; } - blk = blk_new(perm, BLK_PERM_CONSISTENT_READ | BLK_PERM_WRITE_UNCHANGED | - BLK_PERM_WRITE | BLK_PERM_GRAPH_MOD); + blk = blk_new(bdrv_get_aio_context(bs), perm, + BLK_PERM_CONSISTENT_READ | BLK_PERM_WRITE_UNCHANGED | + BLK_PERM_WRITE | BLK_PERM_GRAPH_MOD); ret = blk_insert_bs(blk, bs, errp); if (ret < 0) { goto fail; } blk_set_enable_write_cache(blk, !writethrough); + blk_set_allow_aio_context_change(blk, true); exp->refcount = 1; QTAILQ_INIT(&exp->clients); @@ -470,8 +470,8 @@ void numa_cpu_pre_plug(const CPUArchId *slot, DeviceState *dev, Error **errp) "node-id", errp); } } else if (node_id != slot->props.node_id) { - error_setg(errp, "node-id=%d must match numa node specified " - "with -numa option", node_id); + error_setg(errp, "invalid node-id, must be %"PRId64, + slot->props.node_id); } } diff --git a/qapi/block-core.json b/qapi/block-core.json index 7ccbfff9d0..1defcde048 100644 --- a/qapi/block-core.json +++ b/qapi/block-core.json @@ -2004,18 +2004,34 @@ '*persistent': 'bool', '*autoload': 'bool', '*disabled': 'bool' } } ## +# @BlockDirtyBitmapMergeSource: +# +# @local: name of the bitmap, attached to the same node as target bitmap. +# +# @external: bitmap with specified node +# +# Since: 4.1 +## +{ 'alternate': 'BlockDirtyBitmapMergeSource', + 'data': { 'local': 'str', + 'external': 'BlockDirtyBitmap' } } + +## # @BlockDirtyBitmapMerge: # -# @node: name of device/node which the bitmap is tracking +# @node: name of device/node which the @target bitmap is tracking # # @target: name of the destination dirty bitmap # -# @bitmaps: name(s) of the source dirty bitmap(s) +# @bitmaps: name(s) of the source dirty bitmap(s) at @node and/or fully +# specifed BlockDirtyBitmap elements. The latter are supported +# since 4.1. # # Since: 4.0 ## { 'struct': 'BlockDirtyBitmapMerge', - 'data': { 'node': 'str', 'target': 'str', 'bitmaps': ['str'] } } + 'data': { 'node': 'str', 'target': 'str', + 'bitmaps': ['BlockDirtyBitmapMergeSource'] } } ## # @block-dirty-bitmap-add: @@ -3215,6 +3231,8 @@ # # @cor_write: a write due to copy-on-read (since 2.11) # +# @cluster_alloc_space: an allocation of file space for a cluster (since 4.1) +# # Since: 2.9 ## { 'enum': 'BlkdebugEvent', 'prefix': 'BLKDBG', @@ -3233,7 +3251,7 @@ 'pwritev_rmw_tail', 'pwritev_rmw_after_tail', 'pwritev', 'pwritev_zero', 'pwritev_done', 'empty_image_prepare', 'l1_shrink_write_table', 'l1_shrink_free_l2_clusters', - 'cor_write'] } + 'cor_write', 'cluster_alloc_space'] } ## # @BlkdebugInjectErrorOptions: diff --git a/qemu-deprecated.texi b/qemu-deprecated.texi index 90cb677849..50292d820b 100644 --- a/qemu-deprecated.texi +++ b/qemu-deprecated.texi @@ -138,6 +138,21 @@ The ``acl_show'', ``acl_reset'', ``acl_policy'', ``acl_add'', and ``acl_remove'' commands are deprecated with no replacement. Authorization for VNC should be performed using the pluggable QAuthZ objects. +@section System emulator CPUS + +@subsection RISC-V ISA CPUs (since 4.1) + +The RISC-V cpus with the ISA version in the CPU name have been depcreated. The +four CPUs are: ``rv32gcsu-v1.9.1``, ``rv32gcsu-v1.10.0``, ``rv64gcsu-v1.9.1`` and +``rv64gcsu-v1.10.0``. Instead the version can be specified via the CPU ``priv_spec`` +option when using the ``rv32`` or ``rv64`` CPUs. + +@subsection RISC-V ISA CPUs (since 4.1) + +The RISC-V no MMU cpus have been depcreated. The two CPUs: ``rv32imacu-nommu`` and +``rv64imacu-nommu`` should no longer be used. Instead the MMU status can be specified +via the CPU ``mmu`` option when using the ``rv32`` or ``rv64`` CPUs. + @section System emulator devices @subsection bluetooth (since 3.1) @@ -160,6 +175,12 @@ This machine type uses an unmaintained firmware, broken in lots of ways, and unable to start post-2004 operating systems. 40p machine type should be used instead. +@subsection spike_v1.9.1 and spike_v1.10 (since 4.1) + +The version specific Spike machines have been deprecated in favour of the +generic ``spike`` machine. If you need to specify an older version of the RISC-V +spec you can use the ``-cpu rv64gcsu,priv_spec=v1.9.1`` command line argument. + @section Device options @subsection Block device options diff --git a/qemu-img.c b/qemu-img.c index 28fba1e7a7..07b6e2a808 100644 --- a/qemu-img.c +++ b/qemu-img.c @@ -3164,7 +3164,7 @@ static int img_rebase(int argc, char **argv) BlockBackend *blk = NULL, *blk_old_backing = NULL, *blk_new_backing = NULL; uint8_t *buf_old = NULL; uint8_t *buf_new = NULL; - BlockDriverState *bs = NULL; + BlockDriverState *bs = NULL, *prefix_chain_bs = NULL; char *filename; const char *fmt, *cache, *src_cache, *out_basefmt, *out_baseimg; int c, flags, src_flags, ret; @@ -3309,29 +3309,19 @@ static int img_rebase(int argc, char **argv) /* For safe rebasing we need to compare old and new backing file */ if (!unsafe) { - char backing_name[PATH_MAX]; QDict *options = NULL; - - if (bs->backing) { - if (bs->backing_format[0] != '\0') { - options = qdict_new(); - qdict_put_str(options, "driver", bs->backing_format); - } - - if (force_share) { - if (!options) { - options = qdict_new(); - } - qdict_put_bool(options, BDRV_OPT_FORCE_SHARE, true); - } - bdrv_get_backing_filename(bs, backing_name, sizeof(backing_name)); - blk_old_backing = blk_new_open(backing_name, NULL, - options, src_flags, &local_err); - if (!blk_old_backing) { + BlockDriverState *base_bs = backing_bs(bs); + + if (base_bs) { + blk_old_backing = blk_new(qemu_get_aio_context(), + BLK_PERM_CONSISTENT_READ, + BLK_PERM_ALL); + ret = blk_insert_bs(blk_old_backing, base_bs, + &local_err); + if (ret < 0) { error_reportf_err(local_err, - "Could not open old backing file '%s': ", - backing_name); - ret = -1; + "Could not reuse old backing file '%s': ", + base_bs->filename); goto out; } } else { @@ -3364,15 +3354,35 @@ static int img_rebase(int argc, char **argv) goto out; } - blk_new_backing = blk_new_open(out_real_path, NULL, - options, src_flags, &local_err); - g_free(out_real_path); - if (!blk_new_backing) { - error_reportf_err(local_err, - "Could not open new backing file '%s': ", - out_baseimg); - ret = -1; - goto out; + /* + * Find out whether we rebase an image on top of a previous image + * in its chain. + */ + prefix_chain_bs = bdrv_find_backing_image(bs, out_real_path); + if (prefix_chain_bs) { + g_free(out_real_path); + blk_new_backing = blk_new(qemu_get_aio_context(), + BLK_PERM_CONSISTENT_READ, + BLK_PERM_ALL); + ret = blk_insert_bs(blk_new_backing, prefix_chain_bs, + &local_err); + if (ret < 0) { + error_reportf_err(local_err, + "Could not reuse backing file '%s': ", + out_baseimg); + goto out; + } + } else { + blk_new_backing = blk_new_open(out_real_path, NULL, + options, src_flags, &local_err); + g_free(out_real_path); + if (!blk_new_backing) { + error_reportf_err(local_err, + "Could not open new backing file '%s': ", + out_baseimg); + ret = -1; + goto out; + } } } } @@ -3448,6 +3458,23 @@ static int img_rebase(int argc, char **argv) continue; } + if (prefix_chain_bs) { + /* + * If cluster wasn't changed since prefix_chain, we don't need + * to take action + */ + ret = bdrv_is_allocated_above(backing_bs(bs), prefix_chain_bs, + offset, n, &n); + if (ret < 0) { + error_report("error while reading image metadata: %s", + strerror(-ret)); + goto out; + } + if (!ret) { + continue; + } + } + /* * Read old and new backing file and take into consideration that * backing files may be smaller than the COW image. diff --git a/qemu-options.hx b/qemu-options.hx index 7ae3373a00..0d8beb4afd 100644 --- a/qemu-options.hx +++ b/qemu-options.hx @@ -2080,7 +2080,7 @@ Specify SMBIOS type 0 fields @item -smbios type=1[,manufacturer=@var{str}][,product=@var{str}][,version=@var{str}][,serial=@var{str}][,uuid=@var{uuid}][,sku=@var{str}][,family=@var{str}] Specify SMBIOS type 1 fields -@item -smbios type=2[,manufacturer=@var{str}][,product=@var{str}][,version=@var{str}][,serial=@var{str}][,asset=@var{str}][,location=@var{str}][,family=@var{str}] +@item -smbios type=2[,manufacturer=@var{str}][,product=@var{str}][,version=@var{str}][,serial=@var{str}][,asset=@var{str}][,location=@var{str}] Specify SMBIOS type 2 fields @item -smbios type=3[,manufacturer=@var{str}][,version=@var{str}][,serial=@var{str}][,asset=@var{str}][,sku=@var{str}] @@ -4025,12 +4025,12 @@ STEXI Enable semihosting mode (ARM, M68K, Xtensa, MIPS, Nios II only). ETEXI DEF("semihosting-config", HAS_ARG, QEMU_OPTION_semihosting_config, - "-semihosting-config [enable=on|off][,target=native|gdb|auto][,arg=str[,...]]\n" \ + "-semihosting-config [enable=on|off][,target=native|gdb|auto][,chardev=id][,arg=str[,...]]\n" \ " semihosting configuration\n", QEMU_ARCH_ARM | QEMU_ARCH_M68K | QEMU_ARCH_XTENSA | QEMU_ARCH_LM32 | QEMU_ARCH_MIPS | QEMU_ARCH_NIOS2) STEXI -@item -semihosting-config [enable=on|off][,target=native|gdb|auto][,arg=str[,...]] +@item -semihosting-config [enable=on|off][,target=native|gdb|auto][,chardev=id][,arg=str[,...]] @findex -semihosting-config Enable and configure semihosting (ARM, M68K, Xtensa, MIPS, Nios II only). @table @option @@ -4038,6 +4038,8 @@ Enable and configure semihosting (ARM, M68K, Xtensa, MIPS, Nios II only). Defines where the semihosting calls will be addressed, to QEMU (@code{native}) or to GDB (@code{gdb}). The default is @code{auto}, which means @code{gdb} during debug sessions and @code{native} otherwise. +@item chardev=@var{str1} +Send the output to a chardev backend output for native or auto output when not in gdb @item arg=@var{str1},arg=@var{str2},... Allows the user to pass input arguments, and can be used multiple times to build up a list. The old-style @code{-kernel}/@code{-append} method of passing a diff --git a/qom/object.c b/qom/object.c index 99c4fa707e..3966a3d461 100644 --- a/qom/object.c +++ b/qom/object.c @@ -28,6 +28,7 @@ #include "qapi/qmp/qbool.h" #include "qapi/qmp/qnum.h" #include "qapi/qmp/qstring.h" +#include "qemu/error-report.h" #define MAX_INTERFACES 32 @@ -448,7 +449,6 @@ static void object_initialize_with_type(void *data, size_t size, TypeImpl *type) { Object *obj = data; - g_assert(type != NULL); type_initialize(type); g_assert(type->instance_size >= sizeof(Object)); @@ -468,6 +468,11 @@ void object_initialize(void *data, size_t size, const char *typename) { TypeImpl *type = type_get_by_name(typename); + if (!type) { + error_report("missing object type '%s'", typename); + abort(); + } + object_initialize_with_type(data, size, type); } @@ -144,7 +144,7 @@ cc-option = $(if $(shell $(CC) $1 $2 -S -o /dev/null -xc /dev/null \ cc-c-option = $(if $(shell $(CC) $1 $2 -c -o /dev/null -xc /dev/null \ >/dev/null 2>&1 && echo OK), $2, $3) -VPATH_SUFFIXES = %.c %.h %.S %.cc %.cpp %.m %.mak %.texi %.sh %.rc Kconfig% +VPATH_SUFFIXES = %.c %.h %.S %.cc %.cpp %.m %.mak %.texi %.sh %.rc Kconfig% %.json.in set-vpath = $(if $1,$(foreach PATTERN,$(VPATH_SUFFIXES),$(eval vpath $(PATTERN) $1))) # install-prog list, dir @@ -392,3 +392,10 @@ TEXI2MAN = $(call quiet-command, \ $(call TEXI2MAN) %.8: $(call TEXI2MAN) + +GEN_SUBST = $(call quiet-command, \ + sed -e "s!@libexecdir@!$(libexecdir)!g" < $< > $@, \ + "GEN","$@") + +%.json: %.json.in + $(call GEN_SUBST) diff --git a/scripts/checkpatch.pl b/scripts/checkpatch.pl index 88682cb0a9..c2aaf421da 100755 --- a/scripts/checkpatch.pl +++ b/scripts/checkpatch.pl @@ -1949,7 +1949,8 @@ sub process { } # no C99 // comments - if ($line =~ m{//}) { + if ($line =~ m{//} && + $rawline !~ m{// SPDX-License-Identifier: }) { ERROR("do not use C99 // comments\n" . $herecurr); } # Remove C99 comments. diff --git a/stubs/Makefile.objs b/stubs/Makefile.objs index 73452ad265..9c7393b08c 100644 --- a/stubs/Makefile.objs +++ b/stubs/Makefile.objs @@ -40,3 +40,4 @@ stub-obj-y += pci-host-piix.o stub-obj-y += ram-block.o stub-obj-y += ramfb.o stub-obj-y += fw_cfg.o +stub-obj-$(CONFIG_SOFTMMU) += semihost.o diff --git a/stubs/semihost.c b/stubs/semihost.c new file mode 100644 index 0000000000..4d5b3c0653 --- /dev/null +++ b/stubs/semihost.c @@ -0,0 +1,70 @@ +/* + * Semihosting Stubs for SoftMMU + * + * Copyright (c) 2019 Linaro Ltd + * + * Stubs for SoftMMU targets that don't actually do semihosting. + * + * SPDX-License-Identifier: GPL-2.0-or-later + */ + +#include "qemu/osdep.h" +#include "qemu/option.h" +#include "qemu/error-report.h" +#include "hw/semihosting/semihost.h" + +/* Empty config */ +QemuOptsList qemu_semihosting_config_opts = { + .name = "", + .head = QTAILQ_HEAD_INITIALIZER(qemu_semihosting_config_opts.head), + .desc = { + { /* end of list */ } + }, +}; + +/* Queries to config status default to off */ +bool semihosting_enabled(void) +{ + return false; +} + +SemihostingTarget semihosting_get_target(void) +{ + return SEMIHOSTING_TARGET_AUTO; +} + +/* + * All the rest are empty subs. We could g_assert_not_reached() but + * that adds extra weight to the final binary. Waste not want not. + */ +void qemu_semihosting_enable(void) +{ +} + +int qemu_semihosting_config_options(const char *optarg) +{ + return 1; +} + +const char *semihosting_get_arg(int i) +{ + return NULL; +} + +int semihosting_get_argc(void) +{ + return 0; +} + +const char *semihosting_get_cmdline(void) +{ + return NULL; +} + +void semihosting_arg_fallback(const char *file, const char *cmd) +{ +} + +void qemu_semihosting_connect_chardevs(void) +{ +} diff --git a/target/arm/arm-semi.c b/target/arm/arm-semi.c index ddb94e0aba..53e807ab72 100644 --- a/target/arm/arm-semi.c +++ b/target/arm/arm-semi.c @@ -2,6 +2,7 @@ * Arm "Angel" semihosting syscalls * * Copyright (c) 2005, 2007 CodeSourcery. + * Copyright (c) 2019 Linaro * Written by Paul Brook. * * This program is free software; you can redistribute it and/or modify @@ -16,12 +17,18 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, see <http://www.gnu.org/licenses/>. + * + * ARM Semihosting is documented in: + * Semihosting for AArch32 and AArch64 Release 2.0 + * https://static.docs.arm.com/100863/0200/semihosting.pdf */ #include "qemu/osdep.h" #include "cpu.h" -#include "exec/semihost.h" +#include "hw/semihosting/semihost.h" +#include "hw/semihosting/console.h" +#include "qemu/log.h" #ifdef CONFIG_USER_ONLY #include "qemu.h" @@ -239,6 +246,15 @@ static target_ulong arm_gdb_syscall(ARMCPU *cpu, gdb_syscall_complete_cb cb, put_user_u64(val, args + (n) * 8) : \ put_user_u32(val, args + (n) * 4)) +/* + * Do a semihosting call. + * + * The specification always says that the "return register" either + * returns a specific value or is corrupted, so we don't need to + * report to our caller whether we are returning a value or trying to + * leave the register unchanged. We use 0xdeadbeef as the return value + * when there isn't a defined return value for the call. + */ target_ulong do_arm_semihosting(CPUARMState *env) { ARMCPU *cpu = arm_env_get_cpu(env); @@ -299,32 +315,10 @@ target_ulong do_arm_semihosting(CPUARMState *env) return set_swi_errno(ts, close(arg0)); } case TARGET_SYS_WRITEC: - { - char c; - - if (get_user_u8(c, args)) - /* FIXME - should this error code be -TARGET_EFAULT ? */ - return (uint32_t)-1; - /* Write to debug console. stderr is near enough. */ - if (use_gdb_syscalls()) { - return arm_gdb_syscall(cpu, arm_semi_cb, "write,2,%x,1", args); - } else { - return write(STDERR_FILENO, &c, 1); - } - } + qemu_semihosting_console_out(env, args, 1); + return 0xdeadbeef; case TARGET_SYS_WRITE0: - if (!(s = lock_user_string(args))) - /* FIXME - should this error code be -TARGET_EFAULT ? */ - return (uint32_t)-1; - len = strlen(s); - if (use_gdb_syscalls()) { - return arm_gdb_syscall(cpu, arm_semi_cb, "write,2,%x,%x", - args, len); - } else { - ret = write(STDERR_FILENO, s, len); - } - unlock_user(s, args, 0); - return ret; + return qemu_semihosting_console_out(env, args, 0); case TARGET_SYS_WRITE: GET_ARG(0); GET_ARG(1); @@ -337,13 +331,15 @@ target_ulong do_arm_semihosting(CPUARMState *env) } else { s = lock_user(VERIFY_READ, arg1, len, 1); if (!s) { - /* FIXME - should this error code be -TARGET_EFAULT ? */ - return (uint32_t)-1; + /* Return bytes not written on error */ + return len; } ret = set_swi_errno(ts, write(arg0, s, len)); unlock_user(s, arg1, 0); - if (ret == (uint32_t)-1) - return -1; + if (ret == (uint32_t)-1) { + ret = 0; + } + /* Return bytes not written */ return len - ret; } case TARGET_SYS_READ: @@ -358,19 +354,21 @@ target_ulong do_arm_semihosting(CPUARMState *env) } else { s = lock_user(VERIFY_WRITE, arg1, len, 0); if (!s) { - /* FIXME - should this error code be -TARGET_EFAULT ? */ - return (uint32_t)-1; + /* return bytes not read */ + return len; } do { ret = set_swi_errno(ts, read(arg0, s, len)); } while (ret == -1 && errno == EINTR); unlock_user(s, arg1, len); - if (ret == (uint32_t)-1) - return -1; + if (ret == (uint32_t)-1) { + ret = 0; + } + /* Return bytes not read */ return len - ret; } case TARGET_SYS_READC: - /* XXX: Read from debug console. Not implemented. */ + qemu_log_mask(LOG_UNIMP, "%s: SYS_READC not implemented", __func__); return 0; case TARGET_SYS_ISTTY: GET_ARG(0); @@ -404,7 +402,7 @@ target_ulong do_arm_semihosting(CPUARMState *env) return buf.st_size; } case TARGET_SYS_TMPNAM: - /* XXX: Not implemented. */ + qemu_log_mask(LOG_UNIMP, "%s: SYS_TMPNAM not implemented", __func__); return -1; case TARGET_SYS_REMOVE: GET_ARG(0); @@ -509,14 +507,16 @@ target_ulong do_arm_semihosting(CPUARMState *env) output_size = ts->info->arg_end - ts->info->arg_start; if (!output_size) { - /* We special-case the "empty command line" case (argc==0). - Just provide the terminating 0. */ + /* + * We special-case the "empty command line" case (argc==0). + * Just provide the terminating 0. + */ output_size = 1; } #endif if (output_size > input_size) { - /* Not enough space to store command-line arguments. */ + /* Not enough space to store command-line arguments. */ return -1; } @@ -570,8 +570,10 @@ target_ulong do_arm_semihosting(CPUARMState *env) GET_ARG(0); #ifdef CONFIG_USER_ONLY - /* Some C libraries assume the heap immediately follows .bss, so - allocate it using sbrk. */ + /* + * Some C libraries assume the heap immediately follows .bss, so + * allocate it using sbrk. + */ if (!ts->heap_limit) { abi_ulong ret; @@ -619,7 +621,8 @@ target_ulong do_arm_semihosting(CPUARMState *env) } case TARGET_SYS_EXIT: if (is_a64(env)) { - /* The A64 version of this call takes a parameter block, + /* + * The A64 version of this call takes a parameter block, * so the application-exit type can return a subcode which * is the exit status code from the application. */ @@ -632,14 +635,17 @@ target_ulong do_arm_semihosting(CPUARMState *env) ret = 1; } } else { - /* ARM specifies only Stopped_ApplicationExit as normal - * exit, everything else is considered an error */ + /* + * ARM specifies only Stopped_ApplicationExit as normal + * exit, everything else is considered an error + */ ret = (args == ADP_Stopped_ApplicationExit) ? 0 : 1; } gdb_exit(env, ret); exit(ret); case TARGET_SYS_SYNCCACHE: - /* Clean the D-cache and invalidate the I-cache for the specified + /* + * Clean the D-cache and invalidate the I-cache for the specified * virtual address range. This is a nop for us since we don't * implement caches. This is only present on A64. */ diff --git a/target/arm/helper.c b/target/arm/helper.c index acd23c53ca..719fb92e60 100644 --- a/target/arm/helper.c +++ b/target/arm/helper.c @@ -16,7 +16,7 @@ #include "exec/cpu_ldst.h" #include "arm_ldst.h" #include <zlib.h> /* For crc32 */ -#include "exec/semihost.h" +#include "hw/semihosting/semihost.h" #include "sysemu/cpus.h" #include "sysemu/kvm.h" #include "fpu/softfloat.h" diff --git a/target/arm/translate-a64.c b/target/arm/translate-a64.c index 42999c5801..092f0df3c4 100644 --- a/target/arm/translate-a64.c +++ b/target/arm/translate-a64.c @@ -29,7 +29,7 @@ #include "qemu/host-utils.h" #include "qemu/qemu-print.h" -#include "exec/semihost.h" +#include "hw/semihosting/semihost.h" #include "exec/gen-icount.h" #include "exec/helper-proto.h" diff --git a/target/arm/translate.c b/target/arm/translate.c index 298c262825..d240c1b714 100644 --- a/target/arm/translate.c +++ b/target/arm/translate.c @@ -30,7 +30,7 @@ #include "qemu/bitops.h" #include "qemu/qemu-print.h" #include "arm_ldst.h" -#include "exec/semihost.h" +#include "hw/semihosting/semihost.h" #include "exec/helper-proto.h" #include "exec/helper-gen.h" diff --git a/target/i386/cpu.c b/target/i386/cpu.c index 536d7d1520..c1ab86d63e 100644 --- a/target/i386/cpu.c +++ b/target/i386/cpu.c @@ -4730,6 +4730,9 @@ static void x86_cpu_reset(CPUState *s) env->pat = 0x0007040600070406ULL; env->msr_ia32_misc_enable = MSR_IA32_MISC_ENABLE_DEFAULT; + if (env->features[FEAT_1_ECX] & CPUID_EXT_MONITOR) { + env->msr_ia32_misc_enable |= MSR_IA32_MISC_ENABLE_MWAIT; + } memset(env->dr, 0, sizeof(env->dr)); env->dr[6] = DR6_FIXED_1; diff --git a/target/i386/cpu.h b/target/i386/cpu.h index fce6660bac..bd06523a53 100644 --- a/target/i386/cpu.h +++ b/target/i386/cpu.h @@ -387,6 +387,7 @@ typedef enum X86Seg { #define MSR_IA32_MISC_ENABLE 0x1a0 /* Indicates good rep/movs microcode on some processors: */ #define MSR_IA32_MISC_ENABLE_DEFAULT 1 +#define MSR_IA32_MISC_ENABLE_MWAIT (1ULL << 18) #define MSR_MTRRphysBase(reg) (0x200 + 2 * (reg)) #define MSR_MTRRphysMask(reg) (0x200 + 2 * (reg) + 1) diff --git a/target/lm32/helper.c b/target/lm32/helper.c index 20ea17ba23..8cd4840052 100644 --- a/target/lm32/helper.c +++ b/target/lm32/helper.c @@ -22,7 +22,7 @@ #include "exec/exec-all.h" #include "qemu/host-utils.h" #include "sysemu/sysemu.h" -#include "exec/semihost.h" +#include "hw/semihosting/semihost.h" #include "exec/log.h" bool lm32_cpu_tlb_fill(CPUState *cs, vaddr address, int size, diff --git a/target/m68k/op_helper.c b/target/m68k/op_helper.c index 1ecc772b5c..bde2d551ff 100644 --- a/target/m68k/op_helper.c +++ b/target/m68k/op_helper.c @@ -21,7 +21,7 @@ #include "exec/helper-proto.h" #include "exec/exec-all.h" #include "exec/cpu_ldst.h" -#include "exec/semihost.h" +#include "hw/semihosting/semihost.h" #if defined(CONFIG_USER_ONLY) diff --git a/target/mips/Makefile.objs b/target/mips/Makefile.objs index 651f36f517..3448ad5e19 100644 --- a/target/mips/Makefile.objs +++ b/target/mips/Makefile.objs @@ -1,4 +1,5 @@ obj-y += translate.o dsp_helper.o op_helper.o lmi_helper.o helper.o cpu.o -obj-y += gdbstub.o msa_helper.o mips-semi.o +obj-y += gdbstub.o msa_helper.o +obj-$(CONFIG_SOFTMMU) += mips-semi.o obj-$(CONFIG_SOFTMMU) += machine.o cp0_timer.o obj-$(CONFIG_KVM) += kvm.o diff --git a/target/mips/cpu.h b/target/mips/cpu.h index 1f41cf66d5..06a8ed4748 100644 --- a/target/mips/cpu.h +++ b/target/mips/cpu.h @@ -22,10 +22,10 @@ typedef struct CPUMIPSTLBContext CPUMIPSTLBContext; typedef union wr_t wr_t; union wr_t { - int8_t b[MSA_WRLEN/8]; - int16_t h[MSA_WRLEN/16]; - int32_t w[MSA_WRLEN/32]; - int64_t d[MSA_WRLEN/64]; + int8_t b[MSA_WRLEN / 8]; + int16_t h[MSA_WRLEN / 16]; + int32_t w[MSA_WRLEN / 32]; + int64_t d[MSA_WRLEN / 64]; }; typedef union fpr_t fpr_t; @@ -37,7 +37,8 @@ union fpr_t { /* FPU/MSA register mapping is not tested on big-endian hosts. */ wr_t wr; /* vector data */ }; -/* define FP_ENDIAN_IDX to access the same location +/* + *define FP_ENDIAN_IDX to access the same location * in the fpr_t union regardless of the host endianness */ #if defined(HOST_WORDS_BIGENDIAN) @@ -71,16 +72,29 @@ struct CPUMIPSFPUContext { #define FCR31_FS 24 #define FCR31_ABS2008 19 #define FCR31_NAN2008 18 -#define SET_FP_COND(num,env) do { ((env).fcr31) |= ((num) ? (1 << ((num) + 24)) : (1 << 23)); } while(0) -#define CLEAR_FP_COND(num,env) do { ((env).fcr31) &= ~((num) ? (1 << ((num) + 24)) : (1 << 23)); } while(0) -#define GET_FP_COND(env) ((((env).fcr31 >> 24) & 0xfe) | (((env).fcr31 >> 23) & 0x1)) +#define SET_FP_COND(num, env) do { ((env).fcr31) |= \ + ((num) ? (1 << ((num) + 24)) : \ + (1 << 23)); \ + } while (0) +#define CLEAR_FP_COND(num, env) do { ((env).fcr31) &= \ + ~((num) ? (1 << ((num) + 24)) : \ + (1 << 23)); \ + } while (0) +#define GET_FP_COND(env) ((((env).fcr31 >> 24) & 0xfe) | \ + (((env).fcr31 >> 23) & 0x1)) #define GET_FP_CAUSE(reg) (((reg) >> 12) & 0x3f) #define GET_FP_ENABLE(reg) (((reg) >> 7) & 0x1f) #define GET_FP_FLAGS(reg) (((reg) >> 2) & 0x1f) -#define SET_FP_CAUSE(reg,v) do { (reg) = ((reg) & ~(0x3f << 12)) | ((v & 0x3f) << 12); } while(0) -#define SET_FP_ENABLE(reg,v) do { (reg) = ((reg) & ~(0x1f << 7)) | ((v & 0x1f) << 7); } while(0) -#define SET_FP_FLAGS(reg,v) do { (reg) = ((reg) & ~(0x1f << 2)) | ((v & 0x1f) << 2); } while(0) -#define UPDATE_FP_FLAGS(reg,v) do { (reg) |= ((v & 0x1f) << 2); } while(0) +#define SET_FP_CAUSE(reg, v) do { (reg) = ((reg) & ~(0x3f << 12)) | \ + ((v & 0x3f) << 12); \ + } while (0) +#define SET_FP_ENABLE(reg, v) do { (reg) = ((reg) & ~(0x1f << 7)) | \ + ((v & 0x1f) << 7); \ + } while (0) +#define SET_FP_FLAGS(reg, v) do { (reg) = ((reg) & ~(0x1f << 2)) | \ + ((v & 0x1f) << 2); \ + } while (0) +#define UPDATE_FP_FLAGS(reg, v) do { (reg) |= ((v & 0x1f) << 2); } while (0) #define FP_INEXACT 1 #define FP_UNDERFLOW 2 #define FP_OVERFLOW 4 @@ -95,25 +109,25 @@ struct CPUMIPSFPUContext { typedef struct CPUMIPSMVPContext CPUMIPSMVPContext; struct CPUMIPSMVPContext { int32_t CP0_MVPControl; -#define CP0MVPCo_CPA 3 -#define CP0MVPCo_STLB 2 -#define CP0MVPCo_VPC 1 -#define CP0MVPCo_EVP 0 +#define CP0MVPCo_CPA 3 +#define CP0MVPCo_STLB 2 +#define CP0MVPCo_VPC 1 +#define CP0MVPCo_EVP 0 int32_t CP0_MVPConf0; -#define CP0MVPC0_M 31 -#define CP0MVPC0_TLBS 29 -#define CP0MVPC0_GS 28 -#define CP0MVPC0_PCP 27 -#define CP0MVPC0_PTLBE 16 -#define CP0MVPC0_TCA 15 -#define CP0MVPC0_PVPE 10 -#define CP0MVPC0_PTC 0 +#define CP0MVPC0_M 31 +#define CP0MVPC0_TLBS 29 +#define CP0MVPC0_GS 28 +#define CP0MVPC0_PCP 27 +#define CP0MVPC0_PTLBE 16 +#define CP0MVPC0_TCA 15 +#define CP0MVPC0_PVPE 10 +#define CP0MVPC0_PTC 0 int32_t CP0_MVPConf1; -#define CP0MVPC1_CIM 31 -#define CP0MVPC1_CIF 30 -#define CP0MVPC1_PCX 20 -#define CP0MVPC1_PCP2 10 -#define CP0MVPC1_PCP1 0 +#define CP0MVPC1_CIM 31 +#define CP0MVPC1_CIF 30 +#define CP0MVPC1_PCX 20 +#define CP0MVPC1_PCP2 10 +#define CP0MVPC1_PCP1 0 }; typedef struct mips_def_t mips_def_t; @@ -481,44 +495,44 @@ struct CPUMIPSState { */ int32_t CP0_Random; int32_t CP0_VPEControl; -#define CP0VPECo_YSI 21 -#define CP0VPECo_GSI 20 -#define CP0VPECo_EXCPT 16 -#define CP0VPECo_TE 15 -#define CP0VPECo_TargTC 0 +#define CP0VPECo_YSI 21 +#define CP0VPECo_GSI 20 +#define CP0VPECo_EXCPT 16 +#define CP0VPECo_TE 15 +#define CP0VPECo_TargTC 0 int32_t CP0_VPEConf0; -#define CP0VPEC0_M 31 -#define CP0VPEC0_XTC 21 -#define CP0VPEC0_TCS 19 -#define CP0VPEC0_SCS 18 -#define CP0VPEC0_DSC 17 -#define CP0VPEC0_ICS 16 -#define CP0VPEC0_MVP 1 -#define CP0VPEC0_VPA 0 +#define CP0VPEC0_M 31 +#define CP0VPEC0_XTC 21 +#define CP0VPEC0_TCS 19 +#define CP0VPEC0_SCS 18 +#define CP0VPEC0_DSC 17 +#define CP0VPEC0_ICS 16 +#define CP0VPEC0_MVP 1 +#define CP0VPEC0_VPA 0 int32_t CP0_VPEConf1; -#define CP0VPEC1_NCX 20 -#define CP0VPEC1_NCP2 10 -#define CP0VPEC1_NCP1 0 +#define CP0VPEC1_NCX 20 +#define CP0VPEC1_NCP2 10 +#define CP0VPEC1_NCP1 0 target_ulong CP0_YQMask; target_ulong CP0_VPESchedule; target_ulong CP0_VPEScheFBack; int32_t CP0_VPEOpt; -#define CP0VPEOpt_IWX7 15 -#define CP0VPEOpt_IWX6 14 -#define CP0VPEOpt_IWX5 13 -#define CP0VPEOpt_IWX4 12 -#define CP0VPEOpt_IWX3 11 -#define CP0VPEOpt_IWX2 10 -#define CP0VPEOpt_IWX1 9 -#define CP0VPEOpt_IWX0 8 -#define CP0VPEOpt_DWX7 7 -#define CP0VPEOpt_DWX6 6 -#define CP0VPEOpt_DWX5 5 -#define CP0VPEOpt_DWX4 4 -#define CP0VPEOpt_DWX3 3 -#define CP0VPEOpt_DWX2 2 -#define CP0VPEOpt_DWX1 1 -#define CP0VPEOpt_DWX0 0 +#define CP0VPEOpt_IWX7 15 +#define CP0VPEOpt_IWX6 14 +#define CP0VPEOpt_IWX5 13 +#define CP0VPEOpt_IWX4 12 +#define CP0VPEOpt_IWX3 11 +#define CP0VPEOpt_IWX2 10 +#define CP0VPEOpt_IWX1 9 +#define CP0VPEOpt_IWX0 8 +#define CP0VPEOpt_DWX7 7 +#define CP0VPEOpt_DWX6 6 +#define CP0VPEOpt_DWX5 5 +#define CP0VPEOpt_DWX4 4 +#define CP0VPEOpt_DWX3 3 +#define CP0VPEOpt_DWX2 2 +#define CP0VPEOpt_DWX1 1 +#define CP0VPEOpt_DWX0 0 /* * CP0 Register 2 */ @@ -625,33 +639,33 @@ struct CPUMIPSState { #define CP0PC_PSN 0 /* 5..0 */ int32_t CP0_SRSConf0_rw_bitmask; int32_t CP0_SRSConf0; -#define CP0SRSC0_M 31 -#define CP0SRSC0_SRS3 20 -#define CP0SRSC0_SRS2 10 -#define CP0SRSC0_SRS1 0 +#define CP0SRSC0_M 31 +#define CP0SRSC0_SRS3 20 +#define CP0SRSC0_SRS2 10 +#define CP0SRSC0_SRS1 0 int32_t CP0_SRSConf1_rw_bitmask; int32_t CP0_SRSConf1; -#define CP0SRSC1_M 31 -#define CP0SRSC1_SRS6 20 -#define CP0SRSC1_SRS5 10 -#define CP0SRSC1_SRS4 0 +#define CP0SRSC1_M 31 +#define CP0SRSC1_SRS6 20 +#define CP0SRSC1_SRS5 10 +#define CP0SRSC1_SRS4 0 int32_t CP0_SRSConf2_rw_bitmask; int32_t CP0_SRSConf2; -#define CP0SRSC2_M 31 -#define CP0SRSC2_SRS9 20 -#define CP0SRSC2_SRS8 10 -#define CP0SRSC2_SRS7 0 +#define CP0SRSC2_M 31 +#define CP0SRSC2_SRS9 20 +#define CP0SRSC2_SRS8 10 +#define CP0SRSC2_SRS7 0 int32_t CP0_SRSConf3_rw_bitmask; int32_t CP0_SRSConf3; -#define CP0SRSC3_M 31 -#define CP0SRSC3_SRS12 20 -#define CP0SRSC3_SRS11 10 -#define CP0SRSC3_SRS10 0 +#define CP0SRSC3_M 31 +#define CP0SRSC3_SRS12 20 +#define CP0SRSC3_SRS11 10 +#define CP0SRSC3_SRS10 0 int32_t CP0_SRSConf4_rw_bitmask; int32_t CP0_SRSConf4; -#define CP0SRSC4_SRS15 20 -#define CP0SRSC4_SRS14 10 -#define CP0SRSC4_SRS13 0 +#define CP0SRSC4_SRS15 20 +#define CP0SRSC4_SRS14 10 +#define CP0SRSC4_SRS13 0 /* * CP0 Register 7 */ @@ -963,9 +977,11 @@ struct CPUMIPSState { /* TMASK defines different execution modes */ #define MIPS_HFLAG_TMASK 0x1F5807FF #define MIPS_HFLAG_MODE 0x00007 /* execution modes */ - /* The KSU flags must be the lowest bits in hflags. The flag order - must be the same as defined for CP0 Status. This allows to use - the bits as the value of mmu_idx. */ + /* + * The KSU flags must be the lowest bits in hflags. The flag order + * must be the same as defined for CP0 Status. This allows to use + * the bits as the value of mmu_idx. + */ #define MIPS_HFLAG_KSU 0x00003 /* kernel/supervisor/user mode mask */ #define MIPS_HFLAG_UM 0x00002 /* user mode flag */ #define MIPS_HFLAG_SM 0x00001 /* supervisor mode flag */ @@ -975,18 +991,22 @@ struct CPUMIPSState { #define MIPS_HFLAG_CP0 0x00010 /* CP0 enabled */ #define MIPS_HFLAG_FPU 0x00020 /* FPU enabled */ #define MIPS_HFLAG_F64 0x00040 /* 64-bit FPU enabled */ - /* True if the MIPS IV COP1X instructions can be used. This also - controls the non-COP1X instructions RECIP.S, RECIP.D, RSQRT.S - and RSQRT.D. */ + /* + * True if the MIPS IV COP1X instructions can be used. This also + * controls the non-COP1X instructions RECIP.S, RECIP.D, RSQRT.S + * and RSQRT.D. + */ #define MIPS_HFLAG_COP1X 0x00080 /* COP1X instructions enabled */ #define MIPS_HFLAG_RE 0x00100 /* Reversed endianness */ #define MIPS_HFLAG_AWRAP 0x00200 /* 32-bit compatibility address wrapping */ #define MIPS_HFLAG_M16 0x00400 /* MIPS16 mode flag */ #define MIPS_HFLAG_M16_SHIFT 10 - /* If translation is interrupted between the branch instruction and + /* + * If translation is interrupted between the branch instruction and * the delay slot, record what type of branch it is so that we can * resume translation properly. It might be possible to reduce - * this from three bits to two. */ + * this from three bits to two. + */ #define MIPS_HFLAG_BMASK_BASE 0x803800 #define MIPS_HFLAG_B 0x00800 /* Unconditional branch */ #define MIPS_HFLAG_BC 0x01000 /* Conditional branch */ @@ -1073,8 +1093,10 @@ void mips_cpu_list(void); extern void cpu_wrdsp(uint32_t rs, uint32_t mask_num, CPUMIPSState *env); extern uint32_t cpu_rddsp(uint32_t mask_num, CPUMIPSState *env); -/* MMU modes definitions. We carefully match the indices with our - hflags layout. */ +/* + * MMU modes definitions. We carefully match the indices with our + * hflags layout. + */ #define MMU_MODE0_SUFFIX _kernel #define MMU_MODE1_SUFFIX _super #define MMU_MODE2_SUFFIX _user @@ -1090,14 +1112,15 @@ static inline int hflags_mmu_index(uint32_t hflags) } } -static inline int cpu_mmu_index (CPUMIPSState *env, bool ifetch) +static inline int cpu_mmu_index(CPUMIPSState *env, bool ifetch) { return hflags_mmu_index(env->hflags); } #include "exec/cpu-all.h" -/* Memory access type : +/* + * Memory access type : * may be needed for precise access rights control and precise exceptions. */ enum { @@ -1182,7 +1205,7 @@ void cpu_mips_soft_irq(CPUMIPSState *env, int irq, int level); void itc_reconfigure(struct MIPSITUState *tag); /* helper.c */ -target_ulong exception_resume_pc (CPUMIPSState *env); +target_ulong exception_resume_pc(CPUMIPSState *env); static inline void restore_snan_bit_mode(CPUMIPSState *env) { diff --git a/target/mips/dsp_helper.c b/target/mips/dsp_helper.c index 739b69dd45..8c58eeb0bf 100644 --- a/target/mips/dsp_helper.c +++ b/target/mips/dsp_helper.c @@ -22,8 +22,10 @@ #include "exec/helper-proto.h" #include "qemu/bitops.h" -/* As the byte ordering doesn't matter, i.e. all columns are treated - identically, these unions can be used directly. */ +/* + * As the byte ordering doesn't matter, i.e. all columns are treated + * identically, these unions can be used directly. + */ typedef union { uint8_t ub[4]; int8_t sb[4]; @@ -1445,9 +1447,15 @@ target_ulong helper_precr_ob_qh(target_ulong rs, target_ulong rt) return temp; } -#define PRECR_QH_PW(name, var) \ -target_ulong helper_precr_##name##_qh_pw(target_ulong rs, target_ulong rt, \ - uint32_t sa) \ + +/* + * In case sa == 0, use rt2, rt0, rs2, rs0. + * In case sa != 0, use rt3, rt1, rs3, rs1. + */ +#define PRECR_QH_PW(name, var) \ +target_ulong helper_precr_##name##_qh_pw(target_ulong rs, \ + target_ulong rt, \ + uint32_t sa) \ { \ uint16_t rs3, rs2, rs1, rs0; \ uint16_t rt3, rt2, rt1, rt0; \ @@ -1456,8 +1464,6 @@ target_ulong helper_precr_##name##_qh_pw(target_ulong rs, target_ulong rt, \ MIPSDSP_SPLIT64_16(rs, rs3, rs2, rs1, rs0); \ MIPSDSP_SPLIT64_16(rt, rt3, rt2, rt1, rt0); \ \ - /* When sa = 0, we use rt2, rt0, rs2, rs0; \ - * when sa != 0, we use rt3, rt1, rs3, rs1. */ \ if (sa == 0) { \ tempD = rt2 << var; \ tempC = rt0 << var; \ @@ -1965,7 +1971,8 @@ SHIFT_PH(shra_r, rnd16_rashift); #undef SHIFT_PH /** DSP Multiply Sub-class insns **/ -/* Return value made up by two 16bits value. +/* + * Return value made up by two 16bits value. * FIXME give the macro a better name. */ #define MUL_RETURN32_16_PH(name, func, \ @@ -3274,11 +3281,15 @@ target_ulong helper_dextr_l(target_ulong ac, target_ulong shift, CPUMIPSState *env) { uint64_t temp[3]; + target_ulong ret; shift = shift & 0x3F; mipsdsp_rndrashift_acc(temp, ac, shift, env); - return (temp[1] << 63) | (temp[0] >> 1); + + ret = (temp[1] << 63) | (temp[0] >> 1); + + return ret; } target_ulong helper_dextr_r_l(target_ulong ac, target_ulong shift, @@ -3286,6 +3297,7 @@ target_ulong helper_dextr_r_l(target_ulong ac, target_ulong shift, { uint64_t temp[3]; uint32_t temp128; + target_ulong ret; shift = shift & 0x3F; mipsdsp_rndrashift_acc(temp, ac, shift, env); @@ -3305,7 +3317,9 @@ target_ulong helper_dextr_r_l(target_ulong ac, target_ulong shift, set_DSPControl_overflow_flag(1, 23, env); } - return (temp[1] << 63) | (temp[0] >> 1); + ret = (temp[1] << 63) | (temp[0] >> 1); + + return ret; } target_ulong helper_dextr_rs_l(target_ulong ac, target_ulong shift, @@ -3313,6 +3327,7 @@ target_ulong helper_dextr_rs_l(target_ulong ac, target_ulong shift, { uint64_t temp[3]; uint32_t temp128; + target_ulong ret; shift = shift & 0x3F; mipsdsp_rndrashift_acc(temp, ac, shift, env); @@ -3338,7 +3353,10 @@ target_ulong helper_dextr_rs_l(target_ulong ac, target_ulong shift, } set_DSPControl_overflow_flag(1, 23, env); } - return (temp[1] << 63) | (temp[0] >> 1); + + ret = (temp[1] << 63) | (temp[0] >> 1); + + return ret; } #endif diff --git a/target/mips/helper.c b/target/mips/helper.c index 9799f2ede1..68e44df4da 100644 --- a/target/mips/helper.c +++ b/target/mips/helper.c @@ -43,7 +43,7 @@ int no_mmu_map_address (CPUMIPSState *env, hwaddr *physical, int *prot, target_ulong address, int rw, int access_type) { *physical = address; - *prot = PAGE_READ | PAGE_WRITE; + *prot = PAGE_READ | PAGE_WRITE | PAGE_EXEC; return TLBRET_MATCH; } @@ -61,7 +61,7 @@ int fixed_mmu_map_address (CPUMIPSState *env, hwaddr *physical, int *prot, else *physical = address; - *prot = PAGE_READ | PAGE_WRITE; + *prot = PAGE_READ | PAGE_WRITE | PAGE_EXEC; return TLBRET_MATCH; } @@ -101,6 +101,9 @@ int r4k_map_address (CPUMIPSState *env, hwaddr *physical, int *prot, *prot = PAGE_READ; if (n ? tlb->D1 : tlb->D0) *prot |= PAGE_WRITE; + if (!(n ? tlb->XI1 : tlb->XI0)) { + *prot |= PAGE_EXEC; + } return TLBRET_MATCH; } return TLBRET_DIRTY; @@ -182,7 +185,7 @@ static int get_seg_physical_address(CPUMIPSState *env, hwaddr *physical, } else { /* The segment is unmapped */ *physical = physical_base | (real_address & segmask); - *prot = PAGE_READ | PAGE_WRITE; + *prot = PAGE_READ | PAGE_WRITE | PAGE_EXEC; return TLBRET_MATCH; } } @@ -907,7 +910,7 @@ bool mips_cpu_tlb_fill(CPUState *cs, vaddr address, int size, } if (ret == TLBRET_MATCH) { tlb_set_page(cs, address & TARGET_PAGE_MASK, - physical & TARGET_PAGE_MASK, prot | PAGE_EXEC, + physical & TARGET_PAGE_MASK, prot, mmu_idx, TARGET_PAGE_SIZE); return true; } @@ -927,7 +930,7 @@ bool mips_cpu_tlb_fill(CPUState *cs, vaddr address, int size, access_type, mips_access_type, mmu_idx); if (ret == TLBRET_MATCH) { tlb_set_page(cs, address & TARGET_PAGE_MASK, - physical & TARGET_PAGE_MASK, prot | PAGE_EXEC, + physical & TARGET_PAGE_MASK, prot, mmu_idx, TARGET_PAGE_SIZE); return true; } diff --git a/target/mips/helper.h b/target/mips/helper.h index a6d687e340..51f0e1c183 100644 --- a/target/mips/helper.h +++ b/target/mips/helper.h @@ -2,7 +2,9 @@ DEF_HELPER_3(raise_exception_err, noreturn, env, i32, int) DEF_HELPER_2(raise_exception, noreturn, env, i32) DEF_HELPER_1(raise_exception_debug, noreturn, env) +#ifndef CONFIG_USER_ONLY DEF_HELPER_1(do_semihosting, void, env) +#endif #ifdef TARGET_MIPS64 DEF_HELPER_4(sdl, void, env, tl, tl, int) @@ -876,9 +878,7 @@ DEF_HELPER_5(msa_hsub_u_df, void, env, i32, i32, i32, i32) DEF_HELPER_5(msa_sldi_df, void, env, i32, i32, i32, i32) DEF_HELPER_5(msa_splati_df, void, env, i32, i32, i32, i32) -DEF_HELPER_5(msa_copy_s_df, void, env, i32, i32, i32, i32) -DEF_HELPER_5(msa_copy_u_df, void, env, i32, i32, i32, i32) -DEF_HELPER_5(msa_insert_df, void, env, i32, i32, i32, i32) + DEF_HELPER_5(msa_insve_df, void, env, i32, i32, i32, i32) DEF_HELPER_3(msa_ctcmsa, void, env, tl, i32) DEF_HELPER_2(msa_cfcmsa, tl, env, i32) @@ -938,6 +938,18 @@ DEF_HELPER_4(msa_pcnt_df, void, env, i32, i32, i32) DEF_HELPER_4(msa_nloc_df, void, env, i32, i32, i32) DEF_HELPER_4(msa_nlzc_df, void, env, i32, i32, i32) +DEF_HELPER_4(msa_copy_s_b, void, env, i32, i32, i32) +DEF_HELPER_4(msa_copy_s_h, void, env, i32, i32, i32) +DEF_HELPER_4(msa_copy_s_w, void, env, i32, i32, i32) +DEF_HELPER_4(msa_copy_s_d, void, env, i32, i32, i32) +DEF_HELPER_4(msa_copy_u_b, void, env, i32, i32, i32) +DEF_HELPER_4(msa_copy_u_h, void, env, i32, i32, i32) +DEF_HELPER_4(msa_copy_u_w, void, env, i32, i32, i32) +DEF_HELPER_4(msa_insert_b, void, env, i32, i32, i32) +DEF_HELPER_4(msa_insert_h, void, env, i32, i32, i32) +DEF_HELPER_4(msa_insert_w, void, env, i32, i32, i32) +DEF_HELPER_4(msa_insert_d, void, env, i32, i32, i32) + DEF_HELPER_4(msa_fclass_df, void, env, i32, i32, i32) DEF_HELPER_4(msa_ftrunc_s_df, void, env, i32, i32, i32) DEF_HELPER_4(msa_ftrunc_u_df, void, env, i32, i32, i32) diff --git a/target/mips/lmi_helper.c b/target/mips/lmi_helper.c index fb1245b39d..6c645cf679 100644 --- a/target/mips/lmi_helper.c +++ b/target/mips/lmi_helper.c @@ -21,9 +21,11 @@ #include "cpu.h" #include "exec/helper-proto.h" -/* If the byte ordering doesn't matter, i.e. all columns are treated - identically, then this union can be used directly. If byte ordering - does matter, we generally ignore dumping to memory. */ +/* + * If the byte ordering doesn't matter, i.e. all columns are treated + * identically, then this union can be used directly. If byte ordering + * does matter, we generally ignore dumping to memory. + */ typedef union { uint8_t ub[8]; int8_t sb[8]; diff --git a/target/mips/mips-semi.c b/target/mips/mips-semi.c index a7aefbaefc..35bdfd7c77 100644 --- a/target/mips/mips-semi.c +++ b/target/mips/mips-semi.c @@ -22,7 +22,8 @@ #include "qemu/log.h" #include "exec/helper-proto.h" #include "exec/softmmu-semi.h" -#include "exec/semihost.h" +#include "hw/semihosting/semihost.h" +#include "hw/semihosting/console.h" typedef enum UHIOp { UHI_exit = 1, @@ -329,13 +330,12 @@ void helper_do_semihosting(CPUMIPSState *env) p2 = strstr(p, "%d"); if (p2) { int char_num = p2 - p; - char *buf = g_malloc(char_num + 1); - strncpy(buf, p, char_num); - buf[char_num] = '\0'; - gpr[2] = printf("%s%d%s", buf, (int)gpr[5], p2 + 2); - g_free(buf); + GString *s = g_string_new_len(p, char_num); + g_string_append_printf(s, "%d%s", (int)gpr[5], p2 + 2); + gpr[2] = qemu_semihosting_log_out(s->str, s->len); + g_string_free(s, true); } else { - gpr[2] = printf("%s", p); + gpr[2] = qemu_semihosting_log_out(p, strlen(p)); } FREE_TARGET_STRING(p, gpr[4]); break; diff --git a/target/mips/msa_helper.c b/target/mips/msa_helper.c index c74e3cdc65..be059a3d6f 100644 --- a/target/mips/msa_helper.c +++ b/target/mips/msa_helper.c @@ -42,6 +42,467 @@ /* Element-by-element access macros */ #define DF_ELEMENTS(df) (MSA_WRLEN / DF_BITS(df)) + + +/* + * Bit Count + * --------- + * + * +---------------+----------------------------------------------------------+ + * | NLOC.B | Vector Leading Ones Count (byte) | + * | NLOC.H | Vector Leading Ones Count (halfword) | + * | NLOC.W | Vector Leading Ones Count (word) | + * | NLOC.D | Vector Leading Ones Count (doubleword) | + * | NLZC.B | Vector Leading Zeros Count (byte) | + * | NLZC.H | Vector Leading Zeros Count (halfword) | + * | NLZC.W | Vector Leading Zeros Count (word) | + * | NLZC.D | Vector Leading Zeros Count (doubleword) | + * | PCNT.B | Vector Population Count (byte) | + * | PCNT.H | Vector Population Count (halfword) | + * | PCNT.W | Vector Population Count (word) | + * | PCNT.D | Vector Population Count (doubleword) | + * +---------------+----------------------------------------------------------+ + */ + +/* TODO: insert Bit Count group helpers here */ + + +/* + * Bit Move + * -------- + * + * +---------------+----------------------------------------------------------+ + * | BMNZ.V | Vector Bit Move If Not Zero | + * | BMZ.V | Vector Bit Move If Zero | + * | BSEL.V | Vector Bit Select | + * | BINSL.B | Vector Bit Insert Left (byte) | + * | BINSL.H | Vector Bit Insert Left (halfword) | + * | BINSL.W | Vector Bit Insert Left (word) | + * | BINSL.D | Vector Bit Insert Left (doubleword) | + * | BINSR.B | Vector Bit Insert Right (byte) | + * | BINSR.H | Vector Bit Insert Right (halfword) | + * | BINSR.W | Vector Bit Insert Right (word) | + * | BINSR.D | Vector Bit Insert Right (doubleword) | + * +---------------+----------------------------------------------------------+ + */ + +/* TODO: insert Bit Move group helpers here */ + + +/* + * Bit Set + * ------- + * + * +---------------+----------------------------------------------------------+ + * | BCLR.B | Vector Bit Clear (byte) | + * | BCLR.H | Vector Bit Clear (halfword) | + * | BCLR.W | Vector Bit Clear (word) | + * | BCLR.D | Vector Bit Clear (doubleword) | + * | BNEG.B | Vector Bit Negate (byte) | + * | BNEG.H | Vector Bit Negate (halfword) | + * | BNEG.W | Vector Bit Negate (word) | + * | BNEG.D | Vector Bit Negate (doubleword) | + * | BSET.B | Vector Bit Set (byte) | + * | BSET.H | Vector Bit Set (halfword) | + * | BSET.W | Vector Bit Set (word) | + * | BSET.D | Vector Bit Set (doubleword) | + * +---------------+----------------------------------------------------------+ + */ + +/* TODO: insert Bit Set group helpers here */ + + +/* + * Fixed Multiply + * -------------- + * + * +---------------+----------------------------------------------------------+ + * | MADD_Q.H | Vector Fixed-Point Multiply and Add (halfword) | + * | MADD_Q.W | Vector Fixed-Point Multiply and Add (word) | + * | MADDR_Q.H | Vector Fixed-Point Multiply and Add Rounded (halfword) | + * | MADDR_Q.W | Vector Fixed-Point Multiply and Add Rounded (word) | + * | MSUB_Q.H | Vector Fixed-Point Multiply and Subtr. (halfword) | + * | MSUB_Q.W | Vector Fixed-Point Multiply and Subtr. (word) | + * | MSUBR_Q.H | Vector Fixed-Point Multiply and Subtr. Rounded (halfword)| + * | MSUBR_Q.W | Vector Fixed-Point Multiply and Subtr. Rounded (word) | + * | MUL_Q.H | Vector Fixed-Point Multiply (halfword) | + * | MUL_Q.W | Vector Fixed-Point Multiply (word) | + * | MULR_Q.H | Vector Fixed-Point Multiply Rounded (halfword) | + * | MULR_Q.W | Vector Fixed-Point Multiply Rounded (word) | + * +---------------+----------------------------------------------------------+ + */ + +/* TODO: insert Fixed Multiply group helpers here */ + + +/* + * Float Max Min + * ------------- + * + * +---------------+----------------------------------------------------------+ + * | FMAX_A.W | Vector Floating-Point Maximum (Absolute) (word) | + * | FMAX_A.D | Vector Floating-Point Maximum (Absolute) (doubleword) | + * | FMAX.W | Vector Floating-Point Maximum (word) | + * | FMAX.D | Vector Floating-Point Maximum (doubleword) | + * | FMIN_A.W | Vector Floating-Point Minimum (Absolute) (word) | + * | FMIN_A.D | Vector Floating-Point Minimum (Absolute) (doubleword) | + * | FMIN.W | Vector Floating-Point Minimum (word) | + * | FMIN.D | Vector Floating-Point Minimum (doubleword) | + * +---------------+----------------------------------------------------------+ + */ + +/* TODO: insert Float Max Min group helpers here */ + + +/* + * Int Add + * ------- + * + * +---------------+----------------------------------------------------------+ + * | ADD_A.B | Vector Add Absolute Values (byte) | + * | ADD_A.H | Vector Add Absolute Values (halfword) | + * | ADD_A.W | Vector Add Absolute Values (word) | + * | ADD_A.D | Vector Add Absolute Values (doubleword) | + * | ADDS_A.B | Vector Signed Saturated Add (of Absolute) (byte) | + * | ADDS_A.H | Vector Signed Saturated Add (of Absolute) (halfword) | + * | ADDS_A.W | Vector Signed Saturated Add (of Absolute) (word) | + * | ADDS_A.D | Vector Signed Saturated Add (of Absolute) (doubleword) | + * | ADDS_S.B | Vector Signed Saturated Add (of Signed) (byte) | + * | ADDS_S.H | Vector Signed Saturated Add (of Signed) (halfword) | + * | ADDS_S.W | Vector Signed Saturated Add (of Signed) (word) | + * | ADDS_S.D | Vector Signed Saturated Add (of Signed) (doubleword) | + * | ADDS_U.B | Vector Unsigned Saturated Add (of Unsigned) (byte) | + * | ADDS_U.H | Vector Unsigned Saturated Add (of Unsigned) (halfword) | + * | ADDS_U.W | Vector Unsigned Saturated Add (of Unsigned) (word) | + * | ADDS_U.D | Vector Unsigned Saturated Add (of Unsigned) (doubleword) | + * | ADDV.B | Vector Add (byte) | + * | ADDV.H | Vector Add (halfword) | + * | ADDV.W | Vector Add (word) | + * | ADDV.D | Vector Add (doubleword) | + * | HSUB_S.H | Vector Signed Horizontal Add (halfword) | + * | HSUB_S.W | Vector Signed Horizontal Add (word) | + * | HSUB_S.D | Vector Signed Horizontal Add (doubleword) | + * | HSUB_U.H | Vector Unigned Horizontal Add (halfword) | + * | HSUB_U.W | Vector Unigned Horizontal Add (word) | + * | HSUB_U.D | Vector Unigned Horizontal Add (doubleword) | + * +---------------+----------------------------------------------------------+ + */ + +/* TODO: insert Int Add group helpers here */ + + +/* + * Int Average + * ----------- + * + * +---------------+----------------------------------------------------------+ + * | AVE_S.B | Vector Signed Average (byte) | + * | AVE_S.H | Vector Signed Average (halfword) | + * | AVE_S.W | Vector Signed Average (word) | + * | AVE_S.D | Vector Signed Average (doubleword) | + * | AVE_U.B | Vector Unsigned Average (byte) | + * | AVE_U.H | Vector Unsigned Average (halfword) | + * | AVE_U.W | Vector Unsigned Average (word) | + * | AVE_U.D | Vector Unsigned Average (doubleword) | + * | AVER_S.B | Vector Signed Average Rounded (byte) | + * | AVER_S.H | Vector Signed Average Rounded (halfword) | + * | AVER_S.W | Vector Signed Average Rounded (word) | + * | AVER_S.D | Vector Signed Average Rounded (doubleword) | + * | AVER_U.B | Vector Unsigned Average Rounded (byte) | + * | AVER_U.H | Vector Unsigned Average Rounded (halfword) | + * | AVER_U.W | Vector Unsigned Average Rounded (word) | + * | AVER_U.D | Vector Unsigned Average Rounded (doubleword) | + * +---------------+----------------------------------------------------------+ + */ + +/* TODO: insert Int Average group helpers here */ + + +/* + * Int Compare + * ----------- + * + * +---------------+----------------------------------------------------------+ + * | CEQ.B | Vector Compare Equal (byte) | + * | CEQ.H | Vector Compare Equal (halfword) | + * | CEQ.W | Vector Compare Equal (word) | + * | CEQ.D | Vector Compare Equal (doubleword) | + * | CLE_S.B | Vector Compare Signed Less Than or Equal (byte) | + * | CLE_S.H | Vector Compare Signed Less Than or Equal (halfword) | + * | CLE_S.W | Vector Compare Signed Less Than or Equal (word) | + * | CLE_S.D | Vector Compare Signed Less Than or Equal (doubleword) | + * | CLE_U.B | Vector Compare Unsigned Less Than or Equal (byte) | + * | CLE_U.H | Vector Compare Unsigned Less Than or Equal (halfword) | + * | CLE_U.W | Vector Compare Unsigned Less Than or Equal (word) | + * | CLE_U.D | Vector Compare Unsigned Less Than or Equal (doubleword) | + * | CLT_S.B | Vector Compare Signed Less Than (byte) | + * | CLT_S.H | Vector Compare Signed Less Than (halfword) | + * | CLT_S.W | Vector Compare Signed Less Than (word) | + * | CLT_S.D | Vector Compare Signed Less Than (doubleword) | + * | CLT_U.B | Vector Compare Unsigned Less Than (byte) | + * | CLT_U.H | Vector Compare Unsigned Less Than (halfword) | + * | CLT_U.W | Vector Compare Unsigned Less Than (word) | + * | CLT_U.D | Vector Compare Unsigned Less Than (doubleword) | + * +---------------+----------------------------------------------------------+ + */ + +/* TODO: insert Int Compare group helpers here */ + + +/* + * Int Divide + * ---------- + * + * +---------------+----------------------------------------------------------+ + * | DIV_S.B | Vector Signed Divide (byte) | + * | DIV_S.H | Vector Signed Divide (halfword) | + * | DIV_S.W | Vector Signed Divide (word) | + * | DIV_S.D | Vector Signed Divide (doubleword) | + * | DIV_U.B | Vector Unsigned Divide (byte) | + * | DIV_U.H | Vector Unsigned Divide (halfword) | + * | DIV_U.W | Vector Unsigned Divide (word) | + * | DIV_U.D | Vector Unsigned Divide (doubleword) | + * +---------------+----------------------------------------------------------+ + */ + +/* TODO: insert Int Divide group helpers here */ + + +/* + * Int Dot Product + * --------------- + * + * +---------------+----------------------------------------------------------+ + * | DOTP_S.H | Vector Signed Dot Product (halfword) | + * | DOTP_S.W | Vector Signed Dot Product (word) | + * | DOTP_S.D | Vector Signed Dot Product (doubleword) | + * | DOTP_U.H | Vector Unsigned Dot Product (halfword) | + * | DOTP_U.W | Vector Unsigned Dot Product (word) | + * | DOTP_U.D | Vector Unsigned Dot Product (doubleword) | + * +---------------+----------------------------------------------------------+ + */ + +/* TODO: insert Int Dot Product group helpers here */ + + +/* + * Int Max Min + * ----------- + * + * +---------------+----------------------------------------------------------+ + * | MAX_A.B | Vector Maximum Based on Absolute Value (byte) | + * | MAX_A.H | Vector Maximum Based on Absolute Value (halfword) | + * | MAX_A.W | Vector Maximum Based on Absolute Value (word) | + * | MAX_A.D | Vector Maximum Based on Absolute Value (doubleword) | + * | MAX_S.B | Vector Signed Maximum (byte) | + * | MAX_S.H | Vector Signed Maximum (halfword) | + * | MAX_S.W | Vector Signed Maximum (word) | + * | MAX_S.D | Vector Signed Maximum (doubleword) | + * | MAX_U.B | Vector Unsigned Maximum (byte) | + * | MAX_U.H | Vector Unsigned Maximum (halfword) | + * | MAX_U.W | Vector Unsigned Maximum (word) | + * | MAX_U.D | Vector Unsigned Maximum (doubleword) | + * | MIN_A.B | Vector Minimum Based on Absolute Value (byte) | + * | MIN_A.H | Vector Minimum Based on Absolute Value (halfword) | + * | MIN_A.W | Vector Minimum Based on Absolute Value (word) | + * | MIN_A.D | Vector Minimum Based on Absolute Value (doubleword) | + * | MIN_S.B | Vector Signed Minimum (byte) | + * | MIN_S.H | Vector Signed Minimum (halfword) | + * | MIN_S.W | Vector Signed Minimum (word) | + * | MIN_S.D | Vector Signed Minimum (doubleword) | + * | MIN_U.B | Vector Unsigned Minimum (byte) | + * | MIN_U.H | Vector Unsigned Minimum (halfword) | + * | MIN_U.W | Vector Unsigned Minimum (word) | + * | MIN_U.D | Vector Unsigned Minimum (doubleword) | + * +---------------+----------------------------------------------------------+ + */ + +/* TODO: insert Int Max Min group helpers here */ + + +/* + * Int Modulo + * ---------- + * + * +---------------+----------------------------------------------------------+ + * | MOD_S.B | Vector Signed Modulo (byte) | + * | MOD_S.H | Vector Signed Modulo (halfword) | + * | MOD_S.W | Vector Signed Modulo (word) | + * | MOD_S.D | Vector Signed Modulo (doubleword) | + * | MOD_U.B | Vector Unsigned Modulo (byte) | + * | MOD_U.H | Vector Unsigned Modulo (halfword) | + * | MOD_U.W | Vector Unsigned Modulo (word) | + * | MOD_U.D | Vector Unsigned Modulo (doubleword) | + * +---------------+----------------------------------------------------------+ + */ + +/* TODO: insert Int Modulo group helpers here */ + + +/* + * Int Multiply + * ------------ + * + * +---------------+----------------------------------------------------------+ + * | MADDV.B | Vector Multiply and Add (byte) | + * | MADDV.H | Vector Multiply and Add (halfword) | + * | MADDV.W | Vector Multiply and Add (word) | + * | MADDV.D | Vector Multiply and Add (doubleword) | + * | MSUBV.B | Vector Multiply and Subtract (byte) | + * | MSUBV.H | Vector Multiply and Subtract (halfword) | + * | MSUBV.W | Vector Multiply and Subtract (word) | + * | MSUBV.D | Vector Multiply and Subtract (doubleword) | + * | MULV.B | Vector Multiply (byte) | + * | MULV.H | Vector Multiply (halfword) | + * | MULV.W | Vector Multiply (word) | + * | MULV.D | Vector Multiply (doubleword) | + * +---------------+----------------------------------------------------------+ + */ + +/* TODO: insert Int Multiply group helpers here */ + + +/* + * Int Subtract + * ------------ + * + * +---------------+----------------------------------------------------------+ + * | ASUB_S.B | Vector Absolute Values of Signed Subtract (byte) | + * | ASUB_S.H | Vector Absolute Values of Signed Subtract (halfword) | + * | ASUB_S.W | Vector Absolute Values of Signed Subtract (word) | + * | ASUB_S.D | Vector Absolute Values of Signed Subtract (doubleword) | + * | ASUB_U.B | Vector Absolute Values of Unsigned Subtract (byte) | + * | ASUB_U.H | Vector Absolute Values of Unsigned Subtract (halfword) | + * | ASUB_U.W | Vector Absolute Values of Unsigned Subtract (word) | + * | ASUB_U.D | Vector Absolute Values of Unsigned Subtract (doubleword) | + * | HSUB_S.H | Vector Signed Horizontal Subtract (halfword) | + * | HSUB_S.W | Vector Signed Horizontal Subtract (word) | + * | HSUB_S.D | Vector Signed Horizontal Subtract (doubleword) | + * | HSUB_U.H | Vector Unigned Horizontal Subtract (halfword) | + * | HSUB_U.W | Vector Unigned Horizontal Subtract (word) | + * | HSUB_U.D | Vector Unigned Horizontal Subtract (doubleword) | + * | SUBS_S.B | Vector Signed Saturated Subtract (of Signed) (byte) | + * | SUBS_S.H | Vector Signed Saturated Subtract (of Signed) (halfword) | + * | SUBS_S.W | Vector Signed Saturated Subtract (of Signed) (word) | + * | SUBS_S.D | Vector Signed Saturated Subtract (of Signed) (doubleword)| + * | SUBS_U.B | Vector Unsigned Saturated Subtract (of Uns.) (byte) | + * | SUBS_U.H | Vector Unsigned Saturated Subtract (of Uns.) (halfword) | + * | SUBS_U.W | Vector Unsigned Saturated Subtract (of Uns.) (word) | + * | SUBS_U.D | Vector Unsigned Saturated Subtract (of Uns.) (doubleword)| + * | SUBSUS_S.B | Vector Uns. Sat. Subtract (of S. from Uns.) (byte) | + * | SUBSUS_S.H | Vector Uns. Sat. Subtract (of S. from Uns.) (halfword) | + * | SUBSUS_S.W | Vector Uns. Sat. Subtract (of S. from Uns.) (word) | + * | SUBSUS_S.D | Vector Uns. Sat. Subtract (of S. from Uns.) (doubleword) | + * | SUBSUU_U.B | Vector Signed Saturated Subtract (of Uns.) (byte) | + * | SUBSUU_U.H | Vector Signed Saturated Subtract (of Uns.) (halfword) | + * | SUBSUU_U.W | Vector Signed Saturated Subtract (of Uns.) (word) | + * | SUBSUU_U.D | Vector Signed Saturated Subtract (of Uns.) (doubleword) | + * | SUBV.B | Vector Subtract (byte) | + * | SUBV.H | Vector Subtract (halfword) | + * | SUBV.W | Vector Subtract (word) | + * | SUBV.D | Vector Subtract (doubleword) | + * +---------------+----------------------------------------------------------+ + */ + +/* TODO: insert Int Subtract group helpers here */ + + +/* + * Interleave + * ---------- + * + * +---------------+----------------------------------------------------------+ + * | ILVEV.B | Vector Interleave Even (byte) | + * | ILVEV.H | Vector Interleave Even (halfword) | + * | ILVEV.W | Vector Interleave Even (word) | + * | ILVEV.D | Vector Interleave Even (doubleword) | + * | ILVOD.B | Vector Interleave Odd (byte) | + * | ILVOD.H | Vector Interleave Odd (halfword) | + * | ILVOD.W | Vector Interleave Odd (word) | + * | ILVOD.D | Vector Interleave Odd (doubleword) | + * | ILVL.B | Vector Interleave Left (byte) | + * | ILVL.H | Vector Interleave Left (halfword) | + * | ILVL.W | Vector Interleave Left (word) | + * | ILVL.D | Vector Interleave Left (doubleword) | + * | ILVR.B | Vector Interleave Right (byte) | + * | ILVR.H | Vector Interleave Right (halfword) | + * | ILVR.W | Vector Interleave Right (word) | + * | ILVR.D | Vector Interleave Right (doubleword) | + * +---------------+----------------------------------------------------------+ + */ + +/* TODO: insert Interleave group helpers here */ + + +/* + * Logic + * ----- + * + * +---------------+----------------------------------------------------------+ + * | AND.V | Vector Logical And | + * | NOR.V | Vector Logical Negated Or | + * | OR.V | Vector Logical Or | + * | XOR.V | Vector Logical Exclusive Or | + * +---------------+----------------------------------------------------------+ + */ + +/* TODO: insert Logic group helpers here */ + + +/* + * Pack + * ---- + * + * +---------------+----------------------------------------------------------+ + * | PCKEV.B | Vector Pack Even (byte) | + * | PCKEV.H | Vector Pack Even (halfword) | + * | PCKEV.W | Vector Pack Even (word) | + * | PCKEV.D | Vector Pack Even (doubleword) | + * | PCKOD.B | Vector Pack Odd (byte) | + * | PCKOD.H | Vector Pack Odd (halfword) | + * | PCKOD.W | Vector Pack Odd (word) | + * | PCKOD.D | Vector Pack Odd (doubleword) | + * | VSHF.B | Vector Data Preserving Shuffle (byte) | + * | VSHF.H | Vector Data Preserving Shuffle (halfword) | + * | VSHF.W | Vector Data Preserving Shuffle (word) | + * | VSHF.D | Vector Data Preserving Shuffle (doubleword) | + * +---------------+----------------------------------------------------------+ + */ + +/* TODO: insert Pack group helpers here */ + + +/* + * Shift + * ----- + * + * +---------------+----------------------------------------------------------+ + * | SLL.B | Vector Shift Left (byte) | + * | SLL.H | Vector Shift Left (halfword) | + * | SLL.W | Vector Shift Left (word) | + * | SLL.D | Vector Shift Left (doubleword) | + * | SRA.B | Vector Shift Right Arithmetic (byte) | + * | SRA.H | Vector Shift Right Arithmetic (halfword) | + * | SRA.W | Vector Shift Right Arithmetic (word) | + * | SRA.D | Vector Shift Right Arithmetic (doubleword) | + * | SRAR.B | Vector Shift Right Arithmetic Rounded (byte) | + * | SRAR.H | Vector Shift Right Arithmetic Rounded (halfword) | + * | SRAR.W | Vector Shift Right Arithmetic Rounded (word) | + * | SRAR.D | Vector Shift Right Arithmetic Rounded (doubleword) | + * | SRL.B | Vector Shift Right Logical (byte) | + * | SRL.H | Vector Shift Right Logical (halfword) | + * | SRL.W | Vector Shift Right Logical (word) | + * | SRL.D | Vector Shift Right Logical (doubleword) | + * | SRLR.B | Vector Shift Right Logical Rounded (byte) | + * | SRLR.H | Vector Shift Right Logical Rounded (halfword) | + * | SRLR.W | Vector Shift Right Logical Rounded (word) | + * | SRLR.D | Vector Shift Right Logical Rounded (doubleword) | + * +---------------+----------------------------------------------------------+ + */ + +/* TODO: insert Shift group helpers here */ + + static inline void msa_move_v(wr_t *pwd, wr_t *pws) { uint32_t i; @@ -130,10 +591,6 @@ void helper_msa_ ## FUNC(CPUMIPSState *env, uint32_t wd, uint32_t ws, \ } \ } -MSA_FN_VECTOR(and_v, pwd->d[i], pws->d[i] & pwt->d[i]) -MSA_FN_VECTOR(or_v, pwd->d[i], pws->d[i] | pwt->d[i]) -MSA_FN_VECTOR(nor_v, pwd->d[i], ~(pws->d[i] | pwt->d[i])) -MSA_FN_VECTOR(xor_v, pwd->d[i], pws->d[i] ^ pwt->d[i]) MSA_FN_VECTOR(bmnz_v, pwd->d[i], BIT_MOVE_IF_NOT_ZERO(pwd->d[i], pws->d[i], pwt->d[i], DF_DOUBLE)) MSA_FN_VECTOR(bmz_v, pwd->d[i], @@ -145,6 +602,46 @@ MSA_FN_VECTOR(bsel_v, pwd->d[i], #undef BIT_SELECT #undef MSA_FN_VECTOR +void helper_msa_and_v(CPUMIPSState *env, uint32_t wd, uint32_t ws, uint32_t wt) +{ + wr_t *pwd = &(env->active_fpu.fpr[wd].wr); + wr_t *pws = &(env->active_fpu.fpr[ws].wr); + wr_t *pwt = &(env->active_fpu.fpr[wt].wr); + + pwd->d[0] = pws->d[0] & pwt->d[0]; + pwd->d[1] = pws->d[1] & pwt->d[1]; +} + +void helper_msa_or_v(CPUMIPSState *env, uint32_t wd, uint32_t ws, uint32_t wt) +{ + wr_t *pwd = &(env->active_fpu.fpr[wd].wr); + wr_t *pws = &(env->active_fpu.fpr[ws].wr); + wr_t *pwt = &(env->active_fpu.fpr[wt].wr); + + pwd->d[0] = pws->d[0] | pwt->d[0]; + pwd->d[1] = pws->d[1] | pwt->d[1]; +} + +void helper_msa_nor_v(CPUMIPSState *env, uint32_t wd, uint32_t ws, uint32_t wt) +{ + wr_t *pwd = &(env->active_fpu.fpr[wd].wr); + wr_t *pws = &(env->active_fpu.fpr[ws].wr); + wr_t *pwt = &(env->active_fpu.fpr[wt].wr); + + pwd->d[0] = ~(pws->d[0] | pwt->d[0]); + pwd->d[1] = ~(pws->d[1] | pwt->d[1]); +} + +void helper_msa_xor_v(CPUMIPSState *env, uint32_t wd, uint32_t ws, uint32_t wt) +{ + wr_t *pwd = &(env->active_fpu.fpr[wd].wr); + wr_t *pws = &(env->active_fpu.fpr[ws].wr); + wr_t *pwt = &(env->active_fpu.fpr[wt].wr); + + pwd->d[0] = pws->d[0] ^ pwt->d[0]; + pwd->d[1] = pws->d[1] ^ pwt->d[1]; +} + static inline int64_t msa_addv_df(uint32_t df, int64_t arg1, int64_t arg2) { return arg1 + arg2; @@ -360,16 +857,16 @@ static inline int64_t msa_binsr_df(uint32_t df, int64_t dest, int64_t arg1, static inline int64_t msa_sat_s_df(uint32_t df, int64_t arg, uint32_t m) { - return arg < M_MIN_INT(m+1) ? M_MIN_INT(m+1) : - arg > M_MAX_INT(m+1) ? M_MAX_INT(m+1) : - arg; + return arg < M_MIN_INT(m + 1) ? M_MIN_INT(m + 1) : + arg > M_MAX_INT(m + 1) ? M_MAX_INT(m + 1) : + arg; } static inline int64_t msa_sat_u_df(uint32_t df, int64_t arg, uint32_t m) { uint64_t u_arg = UNSIGNED(arg, df); - return u_arg < M_MAX_UINT(m+1) ? u_arg : - M_MAX_UINT(m+1); + return u_arg < M_MAX_UINT(m + 1) ? u_arg : + M_MAX_UINT(m + 1); } static inline int64_t msa_srar_df(uint32_t df, int64_t arg1, int64_t arg2) @@ -641,14 +1138,15 @@ static inline int64_t msa_div_s_df(uint32_t df, int64_t arg1, int64_t arg2) if (arg1 == DF_MIN_INT(df) && arg2 == -1) { return DF_MIN_INT(df); } - return arg2 ? arg1 / arg2 : 0; + return arg2 ? arg1 / arg2 + : arg1 >= 0 ? -1 : 1; } static inline int64_t msa_div_u_df(uint32_t df, int64_t arg1, int64_t arg2) { uint64_t u_arg1 = UNSIGNED(arg1, df); uint64_t u_arg2 = UNSIGNED(arg2, df); - return u_arg2 ? u_arg1 / u_arg2 : 0; + return arg2 ? u_arg1 / u_arg2 : -1; } static inline int64_t msa_mod_s_df(uint32_t df, int64_t arg1, int64_t arg2) @@ -656,27 +1154,27 @@ static inline int64_t msa_mod_s_df(uint32_t df, int64_t arg1, int64_t arg2) if (arg1 == DF_MIN_INT(df) && arg2 == -1) { return 0; } - return arg2 ? arg1 % arg2 : 0; + return arg2 ? arg1 % arg2 : arg1; } static inline int64_t msa_mod_u_df(uint32_t df, int64_t arg1, int64_t arg2) { uint64_t u_arg1 = UNSIGNED(arg1, df); uint64_t u_arg2 = UNSIGNED(arg2, df); - return u_arg2 ? u_arg1 % u_arg2 : 0; + return u_arg2 ? u_arg1 % u_arg2 : u_arg1; } #define SIGNED_EVEN(a, df) \ - ((((int64_t)(a)) << (64 - DF_BITS(df)/2)) >> (64 - DF_BITS(df)/2)) + ((((int64_t)(a)) << (64 - DF_BITS(df) / 2)) >> (64 - DF_BITS(df) / 2)) #define UNSIGNED_EVEN(a, df) \ - ((((uint64_t)(a)) << (64 - DF_BITS(df)/2)) >> (64 - DF_BITS(df)/2)) + ((((uint64_t)(a)) << (64 - DF_BITS(df) / 2)) >> (64 - DF_BITS(df) / 2)) #define SIGNED_ODD(a, df) \ - ((((int64_t)(a)) << (64 - DF_BITS(df))) >> (64 - DF_BITS(df)/2)) + ((((int64_t)(a)) << (64 - DF_BITS(df))) >> (64 - DF_BITS(df) / 2)) #define UNSIGNED_ODD(a, df) \ - ((((uint64_t)(a)) << (64 - DF_BITS(df))) >> (64 - DF_BITS(df)/2)) + ((((uint64_t)(a)) << (64 - DF_BITS(df))) >> (64 - DF_BITS(df) / 2)) #define SIGNED_EXTRACT(e, o, a, df) \ do { \ @@ -804,28 +1302,45 @@ void helper_msa_ ## func ## _df(CPUMIPSState *env, uint32_t df, \ wr_t *pwd = &(env->active_fpu.fpr[wd].wr); \ wr_t *pws = &(env->active_fpu.fpr[ws].wr); \ wr_t *pwt = &(env->active_fpu.fpr[wt].wr); \ - uint32_t i; \ \ switch (df) { \ case DF_BYTE: \ - for (i = 0; i < DF_ELEMENTS(DF_BYTE); i++) { \ - pwd->b[i] = msa_ ## func ## _df(df, pws->b[i], pwt->b[i]); \ - } \ + pwd->b[0] = msa_ ## func ## _df(df, pws->b[0], pwt->b[0]); \ + pwd->b[1] = msa_ ## func ## _df(df, pws->b[1], pwt->b[1]); \ + pwd->b[2] = msa_ ## func ## _df(df, pws->b[2], pwt->b[2]); \ + pwd->b[3] = msa_ ## func ## _df(df, pws->b[3], pwt->b[3]); \ + pwd->b[4] = msa_ ## func ## _df(df, pws->b[4], pwt->b[4]); \ + pwd->b[5] = msa_ ## func ## _df(df, pws->b[5], pwt->b[5]); \ + pwd->b[6] = msa_ ## func ## _df(df, pws->b[6], pwt->b[6]); \ + pwd->b[7] = msa_ ## func ## _df(df, pws->b[7], pwt->b[7]); \ + pwd->b[8] = msa_ ## func ## _df(df, pws->b[8], pwt->b[8]); \ + pwd->b[9] = msa_ ## func ## _df(df, pws->b[9], pwt->b[9]); \ + pwd->b[10] = msa_ ## func ## _df(df, pws->b[10], pwt->b[10]); \ + pwd->b[11] = msa_ ## func ## _df(df, pws->b[11], pwt->b[11]); \ + pwd->b[12] = msa_ ## func ## _df(df, pws->b[12], pwt->b[12]); \ + pwd->b[13] = msa_ ## func ## _df(df, pws->b[13], pwt->b[13]); \ + pwd->b[14] = msa_ ## func ## _df(df, pws->b[14], pwt->b[14]); \ + pwd->b[15] = msa_ ## func ## _df(df, pws->b[15], pwt->b[15]); \ break; \ case DF_HALF: \ - for (i = 0; i < DF_ELEMENTS(DF_HALF); i++) { \ - pwd->h[i] = msa_ ## func ## _df(df, pws->h[i], pwt->h[i]); \ - } \ + pwd->h[0] = msa_ ## func ## _df(df, pws->h[0], pwt->h[0]); \ + pwd->h[1] = msa_ ## func ## _df(df, pws->h[1], pwt->h[1]); \ + pwd->h[2] = msa_ ## func ## _df(df, pws->h[2], pwt->h[2]); \ + pwd->h[3] = msa_ ## func ## _df(df, pws->h[3], pwt->h[3]); \ + pwd->h[4] = msa_ ## func ## _df(df, pws->h[4], pwt->h[4]); \ + pwd->h[5] = msa_ ## func ## _df(df, pws->h[5], pwt->h[5]); \ + pwd->h[6] = msa_ ## func ## _df(df, pws->h[6], pwt->h[6]); \ + pwd->h[7] = msa_ ## func ## _df(df, pws->h[7], pwt->h[7]); \ break; \ case DF_WORD: \ - for (i = 0; i < DF_ELEMENTS(DF_WORD); i++) { \ - pwd->w[i] = msa_ ## func ## _df(df, pws->w[i], pwt->w[i]); \ - } \ + pwd->w[0] = msa_ ## func ## _df(df, pws->w[0], pwt->w[0]); \ + pwd->w[1] = msa_ ## func ## _df(df, pws->w[1], pwt->w[1]); \ + pwd->w[2] = msa_ ## func ## _df(df, pws->w[2], pwt->w[2]); \ + pwd->w[3] = msa_ ## func ## _df(df, pws->w[3], pwt->w[3]); \ break; \ case DF_DOUBLE: \ - for (i = 0; i < DF_ELEMENTS(DF_DOUBLE); i++) { \ - pwd->d[i] = msa_ ## func ## _df(df, pws->d[i], pwt->d[i]); \ - } \ + pwd->d[0] = msa_ ## func ## _df(df, pws->d[0], pwt->d[0]); \ + pwd->d[1] = msa_ ## func ## _df(df, pws->d[1], pwt->d[1]); \ break; \ default: \ assert(0); \ @@ -1011,42 +1526,71 @@ static inline int64_t msa_msubr_q_df(uint32_t df, int64_t dest, int64_t arg1, } #define MSA_TEROP_DF(func) \ -void helper_msa_ ## func ## _df(CPUMIPSState *env, uint32_t df, uint32_t wd, \ - uint32_t ws, uint32_t wt) \ -{ \ - wr_t *pwd = &(env->active_fpu.fpr[wd].wr); \ - wr_t *pws = &(env->active_fpu.fpr[ws].wr); \ - wr_t *pwt = &(env->active_fpu.fpr[wt].wr); \ - uint32_t i; \ - \ - switch (df) { \ - case DF_BYTE: \ - for (i = 0; i < DF_ELEMENTS(DF_BYTE); i++) { \ - pwd->b[i] = msa_ ## func ## _df(df, pwd->b[i], pws->b[i], \ - pwt->b[i]); \ - } \ - break; \ - case DF_HALF: \ - for (i = 0; i < DF_ELEMENTS(DF_HALF); i++) { \ - pwd->h[i] = msa_ ## func ## _df(df, pwd->h[i], pws->h[i], \ - pwt->h[i]); \ - } \ - break; \ - case DF_WORD: \ - for (i = 0; i < DF_ELEMENTS(DF_WORD); i++) { \ - pwd->w[i] = msa_ ## func ## _df(df, pwd->w[i], pws->w[i], \ - pwt->w[i]); \ - } \ - break; \ - case DF_DOUBLE: \ - for (i = 0; i < DF_ELEMENTS(DF_DOUBLE); i++) { \ - pwd->d[i] = msa_ ## func ## _df(df, pwd->d[i], pws->d[i], \ - pwt->d[i]); \ - } \ - break; \ - default: \ - assert(0); \ - } \ +void helper_msa_ ## func ## _df(CPUMIPSState *env, uint32_t df, uint32_t wd, \ + uint32_t ws, uint32_t wt) \ +{ \ + wr_t *pwd = &(env->active_fpu.fpr[wd].wr); \ + wr_t *pws = &(env->active_fpu.fpr[ws].wr); \ + wr_t *pwt = &(env->active_fpu.fpr[wt].wr); \ + \ + switch (df) { \ + case DF_BYTE: \ + pwd->b[0] = msa_ ## func ## _df(df, pwd->b[0], pws->b[0], \ + pwt->b[0]); \ + pwd->b[1] = msa_ ## func ## _df(df, pwd->b[1], pws->b[1], \ + pwt->b[1]); \ + pwd->b[2] = msa_ ## func ## _df(df, pwd->b[2], pws->b[2], \ + pwt->b[2]); \ + pwd->b[3] = msa_ ## func ## _df(df, pwd->b[3], pws->b[3], \ + pwt->b[3]); \ + pwd->b[4] = msa_ ## func ## _df(df, pwd->b[4], pws->b[4], \ + pwt->b[4]); \ + pwd->b[5] = msa_ ## func ## _df(df, pwd->b[5], pws->b[5], \ + pwt->b[5]); \ + pwd->b[6] = msa_ ## func ## _df(df, pwd->b[6], pws->b[6], \ + pwt->b[6]); \ + pwd->b[7] = msa_ ## func ## _df(df, pwd->b[7], pws->b[7], \ + pwt->b[7]); \ + pwd->b[8] = msa_ ## func ## _df(df, pwd->b[8], pws->b[8], \ + pwt->b[8]); \ + pwd->b[9] = msa_ ## func ## _df(df, pwd->b[9], pws->b[9], \ + pwt->b[9]); \ + pwd->b[10] = msa_ ## func ## _df(df, pwd->b[10], pws->b[10], \ + pwt->b[10]); \ + pwd->b[11] = msa_ ## func ## _df(df, pwd->b[11], pws->b[11], \ + pwt->b[11]); \ + pwd->b[12] = msa_ ## func ## _df(df, pwd->b[12], pws->b[12], \ + pwt->b[12]); \ + pwd->b[13] = msa_ ## func ## _df(df, pwd->b[13], pws->b[13], \ + pwt->b[13]); \ + pwd->b[14] = msa_ ## func ## _df(df, pwd->b[14], pws->b[14], \ + pwt->b[14]); \ + pwd->b[15] = msa_ ## func ## _df(df, pwd->b[15], pws->b[15], \ + pwt->b[15]); \ + break; \ + case DF_HALF: \ + pwd->h[0] = msa_ ## func ## _df(df, pwd->h[0], pws->h[0], pwt->h[0]); \ + pwd->h[1] = msa_ ## func ## _df(df, pwd->h[1], pws->h[1], pwt->h[1]); \ + pwd->h[2] = msa_ ## func ## _df(df, pwd->h[2], pws->h[2], pwt->h[2]); \ + pwd->h[3] = msa_ ## func ## _df(df, pwd->h[3], pws->h[3], pwt->h[3]); \ + pwd->h[4] = msa_ ## func ## _df(df, pwd->h[4], pws->h[4], pwt->h[4]); \ + pwd->h[5] = msa_ ## func ## _df(df, pwd->h[5], pws->h[5], pwt->h[5]); \ + pwd->h[6] = msa_ ## func ## _df(df, pwd->h[6], pws->h[6], pwt->h[6]); \ + pwd->h[7] = msa_ ## func ## _df(df, pwd->h[7], pws->h[7], pwt->h[7]); \ + break; \ + case DF_WORD: \ + pwd->w[0] = msa_ ## func ## _df(df, pwd->w[0], pws->w[0], pwt->w[0]); \ + pwd->w[1] = msa_ ## func ## _df(df, pwd->w[1], pws->w[1], pwt->w[1]); \ + pwd->w[2] = msa_ ## func ## _df(df, pwd->w[2], pws->w[2], pwt->w[2]); \ + pwd->w[3] = msa_ ## func ## _df(df, pwd->w[3], pws->w[3], pwt->w[3]); \ + break; \ + case DF_DOUBLE: \ + pwd->d[0] = msa_ ## func ## _df(df, pwd->d[0], pws->d[0], pwt->d[0]); \ + pwd->d[1] = msa_ ## func ## _df(df, pwd->d[1], pws->d[1], pwt->d[1]); \ + break; \ + default: \ + assert(0); \ + } \ } MSA_TEROP_DF(maddv) @@ -1158,61 +1702,14 @@ void helper_msa_##FUNC(CPUMIPSState *env, uint32_t df, uint32_t wd, \ (DF_ELEMENTS(DF) / 2) #define Rb(pwr, i) (pwr->b[i]) -#define Lb(pwr, i) (pwr->b[i + DF_ELEMENTS(DF_BYTE)/2]) +#define Lb(pwr, i) (pwr->b[i + DF_ELEMENTS(DF_BYTE) / 2]) #define Rh(pwr, i) (pwr->h[i]) -#define Lh(pwr, i) (pwr->h[i + DF_ELEMENTS(DF_HALF)/2]) +#define Lh(pwr, i) (pwr->h[i + DF_ELEMENTS(DF_HALF) / 2]) #define Rw(pwr, i) (pwr->w[i]) -#define Lw(pwr, i) (pwr->w[i + DF_ELEMENTS(DF_WORD)/2]) +#define Lw(pwr, i) (pwr->w[i + DF_ELEMENTS(DF_WORD) / 2]) #define Rd(pwr, i) (pwr->d[i]) -#define Ld(pwr, i) (pwr->d[i + DF_ELEMENTS(DF_DOUBLE)/2]) +#define Ld(pwr, i) (pwr->d[i + DF_ELEMENTS(DF_DOUBLE) / 2]) -#define MSA_DO(DF) \ - do { \ - R##DF(pwx, i) = pwt->DF[2*i]; \ - L##DF(pwx, i) = pws->DF[2*i]; \ - } while (0) -MSA_FN_DF(pckev_df) -#undef MSA_DO - -#define MSA_DO(DF) \ - do { \ - R##DF(pwx, i) = pwt->DF[2*i+1]; \ - L##DF(pwx, i) = pws->DF[2*i+1]; \ - } while (0) -MSA_FN_DF(pckod_df) -#undef MSA_DO - -#define MSA_DO(DF) \ - do { \ - pwx->DF[2*i] = L##DF(pwt, i); \ - pwx->DF[2*i+1] = L##DF(pws, i); \ - } while (0) -MSA_FN_DF(ilvl_df) -#undef MSA_DO - -#define MSA_DO(DF) \ - do { \ - pwx->DF[2*i] = R##DF(pwt, i); \ - pwx->DF[2*i+1] = R##DF(pws, i); \ - } while (0) -MSA_FN_DF(ilvr_df) -#undef MSA_DO - -#define MSA_DO(DF) \ - do { \ - pwx->DF[2*i] = pwt->DF[2*i]; \ - pwx->DF[2*i+1] = pws->DF[2*i]; \ - } while (0) -MSA_FN_DF(ilvev_df) -#undef MSA_DO - -#define MSA_DO(DF) \ - do { \ - pwx->DF[2*i] = pwt->DF[2*i+1]; \ - pwx->DF[2*i+1] = pws->DF[2*i+1]; \ - } while (0) -MSA_FN_DF(ilvod_df) -#undef MSA_DO #undef MSA_LOOP_COND #define MSA_LOOP_COND(DF) \ @@ -1230,98 +1727,480 @@ MSA_FN_DF(vshf_df) #undef MSA_LOOP_COND #undef MSA_FN_DF -void helper_msa_sldi_df(CPUMIPSState *env, uint32_t df, uint32_t wd, - uint32_t ws, uint32_t n) + +void helper_msa_ilvev_df(CPUMIPSState *env, uint32_t df, uint32_t wd, + uint32_t ws, uint32_t wt) { wr_t *pwd = &(env->active_fpu.fpr[wd].wr); wr_t *pws = &(env->active_fpu.fpr[ws].wr); + wr_t *pwt = &(env->active_fpu.fpr[wt].wr); - msa_sld_df(df, pwd, pws, n); + switch (df) { + case DF_BYTE: + pwd->b[15] = pws->b[14]; + pwd->b[14] = pwt->b[14]; + pwd->b[13] = pws->b[12]; + pwd->b[12] = pwt->b[12]; + pwd->b[11] = pws->b[10]; + pwd->b[10] = pwt->b[10]; + pwd->b[9] = pws->b[8]; + pwd->b[8] = pwt->b[8]; + pwd->b[7] = pws->b[6]; + pwd->b[6] = pwt->b[6]; + pwd->b[5] = pws->b[4]; + pwd->b[4] = pwt->b[4]; + pwd->b[3] = pws->b[2]; + pwd->b[2] = pwt->b[2]; + pwd->b[1] = pws->b[0]; + pwd->b[0] = pwt->b[0]; + break; + case DF_HALF: + pwd->h[7] = pws->h[6]; + pwd->h[6] = pwt->h[6]; + pwd->h[5] = pws->h[4]; + pwd->h[4] = pwt->h[4]; + pwd->h[3] = pws->h[2]; + pwd->h[2] = pwt->h[2]; + pwd->h[1] = pws->h[0]; + pwd->h[0] = pwt->h[0]; + break; + case DF_WORD: + pwd->w[3] = pws->w[2]; + pwd->w[2] = pwt->w[2]; + pwd->w[1] = pws->w[0]; + pwd->w[0] = pwt->w[0]; + break; + case DF_DOUBLE: + pwd->d[1] = pws->d[0]; + pwd->d[0] = pwt->d[0]; + break; + default: + assert(0); + } } -void helper_msa_splati_df(CPUMIPSState *env, uint32_t df, uint32_t wd, - uint32_t ws, uint32_t n) +void helper_msa_ilvod_df(CPUMIPSState *env, uint32_t df, uint32_t wd, + uint32_t ws, uint32_t wt) { wr_t *pwd = &(env->active_fpu.fpr[wd].wr); wr_t *pws = &(env->active_fpu.fpr[ws].wr); + wr_t *pwt = &(env->active_fpu.fpr[wt].wr); - msa_splat_df(df, pwd, pws, n); + switch (df) { + case DF_BYTE: + pwd->b[0] = pwt->b[1]; + pwd->b[1] = pws->b[1]; + pwd->b[2] = pwt->b[3]; + pwd->b[3] = pws->b[3]; + pwd->b[4] = pwt->b[5]; + pwd->b[5] = pws->b[5]; + pwd->b[6] = pwt->b[7]; + pwd->b[7] = pws->b[7]; + pwd->b[8] = pwt->b[9]; + pwd->b[9] = pws->b[9]; + pwd->b[10] = pwt->b[11]; + pwd->b[11] = pws->b[11]; + pwd->b[12] = pwt->b[13]; + pwd->b[13] = pws->b[13]; + pwd->b[14] = pwt->b[15]; + pwd->b[15] = pws->b[15]; + break; + case DF_HALF: + pwd->h[0] = pwt->h[1]; + pwd->h[1] = pws->h[1]; + pwd->h[2] = pwt->h[3]; + pwd->h[3] = pws->h[3]; + pwd->h[4] = pwt->h[5]; + pwd->h[5] = pws->h[5]; + pwd->h[6] = pwt->h[7]; + pwd->h[7] = pws->h[7]; + break; + case DF_WORD: + pwd->w[0] = pwt->w[1]; + pwd->w[1] = pws->w[1]; + pwd->w[2] = pwt->w[3]; + pwd->w[3] = pws->w[3]; + break; + case DF_DOUBLE: + pwd->d[0] = pwt->d[1]; + pwd->d[1] = pws->d[1]; + break; + default: + assert(0); + } } -void helper_msa_copy_s_df(CPUMIPSState *env, uint32_t df, uint32_t rd, - uint32_t ws, uint32_t n) +void helper_msa_ilvl_df(CPUMIPSState *env, uint32_t df, uint32_t wd, + uint32_t ws, uint32_t wt) { - n %= DF_ELEMENTS(df); + wr_t *pwd = &(env->active_fpu.fpr[wd].wr); + wr_t *pws = &(env->active_fpu.fpr[ws].wr); + wr_t *pwt = &(env->active_fpu.fpr[wt].wr); switch (df) { case DF_BYTE: - env->active_tc.gpr[rd] = (int8_t)env->active_fpu.fpr[ws].wr.b[n]; + pwd->b[0] = pwt->b[8]; + pwd->b[1] = pws->b[8]; + pwd->b[2] = pwt->b[9]; + pwd->b[3] = pws->b[9]; + pwd->b[4] = pwt->b[10]; + pwd->b[5] = pws->b[10]; + pwd->b[6] = pwt->b[11]; + pwd->b[7] = pws->b[11]; + pwd->b[8] = pwt->b[12]; + pwd->b[9] = pws->b[12]; + pwd->b[10] = pwt->b[13]; + pwd->b[11] = pws->b[13]; + pwd->b[12] = pwt->b[14]; + pwd->b[13] = pws->b[14]; + pwd->b[14] = pwt->b[15]; + pwd->b[15] = pws->b[15]; break; case DF_HALF: - env->active_tc.gpr[rd] = (int16_t)env->active_fpu.fpr[ws].wr.h[n]; + pwd->h[0] = pwt->h[4]; + pwd->h[1] = pws->h[4]; + pwd->h[2] = pwt->h[5]; + pwd->h[3] = pws->h[5]; + pwd->h[4] = pwt->h[6]; + pwd->h[5] = pws->h[6]; + pwd->h[6] = pwt->h[7]; + pwd->h[7] = pws->h[7]; break; case DF_WORD: - env->active_tc.gpr[rd] = (int32_t)env->active_fpu.fpr[ws].wr.w[n]; + pwd->w[0] = pwt->w[2]; + pwd->w[1] = pws->w[2]; + pwd->w[2] = pwt->w[3]; + pwd->w[3] = pws->w[3]; break; -#ifdef TARGET_MIPS64 case DF_DOUBLE: - env->active_tc.gpr[rd] = (int64_t)env->active_fpu.fpr[ws].wr.d[n]; + pwd->d[0] = pwt->d[1]; + pwd->d[1] = pws->d[1]; break; -#endif default: assert(0); } } -void helper_msa_copy_u_df(CPUMIPSState *env, uint32_t df, uint32_t rd, - uint32_t ws, uint32_t n) +void helper_msa_ilvr_df(CPUMIPSState *env, uint32_t df, uint32_t wd, + uint32_t ws, uint32_t wt) { - n %= DF_ELEMENTS(df); + wr_t *pwd = &(env->active_fpu.fpr[wd].wr); + wr_t *pws = &(env->active_fpu.fpr[ws].wr); + wr_t *pwt = &(env->active_fpu.fpr[wt].wr); switch (df) { case DF_BYTE: - env->active_tc.gpr[rd] = (uint8_t)env->active_fpu.fpr[ws].wr.b[n]; + pwd->b[15] = pws->b[7]; + pwd->b[14] = pwt->b[7]; + pwd->b[13] = pws->b[6]; + pwd->b[12] = pwt->b[6]; + pwd->b[11] = pws->b[5]; + pwd->b[10] = pwt->b[5]; + pwd->b[9] = pws->b[4]; + pwd->b[8] = pwt->b[4]; + pwd->b[7] = pws->b[3]; + pwd->b[6] = pwt->b[3]; + pwd->b[5] = pws->b[2]; + pwd->b[4] = pwt->b[2]; + pwd->b[3] = pws->b[1]; + pwd->b[2] = pwt->b[1]; + pwd->b[1] = pws->b[0]; + pwd->b[0] = pwt->b[0]; break; case DF_HALF: - env->active_tc.gpr[rd] = (uint16_t)env->active_fpu.fpr[ws].wr.h[n]; + pwd->h[7] = pws->h[3]; + pwd->h[6] = pwt->h[3]; + pwd->h[5] = pws->h[2]; + pwd->h[4] = pwt->h[2]; + pwd->h[3] = pws->h[1]; + pwd->h[2] = pwt->h[1]; + pwd->h[1] = pws->h[0]; + pwd->h[0] = pwt->h[0]; break; case DF_WORD: - env->active_tc.gpr[rd] = (uint32_t)env->active_fpu.fpr[ws].wr.w[n]; + pwd->w[3] = pws->w[1]; + pwd->w[2] = pwt->w[1]; + pwd->w[1] = pws->w[0]; + pwd->w[0] = pwt->w[0]; break; -#ifdef TARGET_MIPS64 case DF_DOUBLE: - env->active_tc.gpr[rd] = (uint64_t)env->active_fpu.fpr[ws].wr.d[n]; + pwd->d[1] = pws->d[0]; + pwd->d[0] = pwt->d[0]; break; -#endif default: assert(0); } } -void helper_msa_insert_df(CPUMIPSState *env, uint32_t df, uint32_t wd, - uint32_t rs_num, uint32_t n) +void helper_msa_pckev_df(CPUMIPSState *env, uint32_t df, uint32_t wd, + uint32_t ws, uint32_t wt) { wr_t *pwd = &(env->active_fpu.fpr[wd].wr); - target_ulong rs = env->active_tc.gpr[rs_num]; + wr_t *pws = &(env->active_fpu.fpr[ws].wr); + wr_t *pwt = &(env->active_fpu.fpr[wt].wr); switch (df) { case DF_BYTE: - pwd->b[n] = (int8_t)rs; + pwd->b[15] = pws->b[14]; + pwd->b[13] = pws->b[10]; + pwd->b[11] = pws->b[6]; + pwd->b[9] = pws->b[2]; + pwd->b[7] = pwt->b[14]; + pwd->b[5] = pwt->b[10]; + pwd->b[3] = pwt->b[6]; + pwd->b[1] = pwt->b[2]; + pwd->b[14] = pws->b[12]; + pwd->b[10] = pws->b[4]; + pwd->b[6] = pwt->b[12]; + pwd->b[2] = pwt->b[4]; + pwd->b[12] = pws->b[8]; + pwd->b[4] = pwt->b[8]; + pwd->b[8] = pws->b[0]; + pwd->b[0] = pwt->b[0]; break; case DF_HALF: - pwd->h[n] = (int16_t)rs; + pwd->h[7] = pws->h[6]; + pwd->h[5] = pws->h[2]; + pwd->h[3] = pwt->h[6]; + pwd->h[1] = pwt->h[2]; + pwd->h[6] = pws->h[4]; + pwd->h[2] = pwt->h[4]; + pwd->h[4] = pws->h[0]; + pwd->h[0] = pwt->h[0]; break; case DF_WORD: - pwd->w[n] = (int32_t)rs; + pwd->w[3] = pws->w[2]; + pwd->w[1] = pwt->w[2]; + pwd->w[2] = pws->w[0]; + pwd->w[0] = pwt->w[0]; break; case DF_DOUBLE: - pwd->d[n] = (int64_t)rs; + pwd->d[1] = pws->d[0]; + pwd->d[0] = pwt->d[0]; break; default: assert(0); } } +void helper_msa_pckod_df(CPUMIPSState *env, uint32_t df, uint32_t wd, + uint32_t ws, uint32_t wt) +{ + wr_t *pwd = &(env->active_fpu.fpr[wd].wr); + wr_t *pws = &(env->active_fpu.fpr[ws].wr); + wr_t *pwt = &(env->active_fpu.fpr[wt].wr); + + switch (df) { + case DF_BYTE: + pwd->b[0] = pwt->b[1]; + pwd->b[2] = pwt->b[5]; + pwd->b[4] = pwt->b[9]; + pwd->b[6] = pwt->b[13]; + pwd->b[8] = pws->b[1]; + pwd->b[10] = pws->b[5]; + pwd->b[12] = pws->b[9]; + pwd->b[14] = pws->b[13]; + pwd->b[1] = pwt->b[3]; + pwd->b[5] = pwt->b[11]; + pwd->b[9] = pws->b[3]; + pwd->b[13] = pws->b[11]; + pwd->b[3] = pwt->b[7]; + pwd->b[11] = pws->b[7]; + pwd->b[7] = pwt->b[15]; + pwd->b[15] = pws->b[15]; + break; + case DF_HALF: + pwd->h[0] = pwt->h[1]; + pwd->h[2] = pwt->h[5]; + pwd->h[4] = pws->h[1]; + pwd->h[6] = pws->h[5]; + pwd->h[1] = pwt->h[3]; + pwd->h[5] = pws->h[3]; + pwd->h[3] = pwt->h[7]; + pwd->h[7] = pws->h[7]; + break; + case DF_WORD: + pwd->w[0] = pwt->w[1]; + pwd->w[2] = pws->w[1]; + pwd->w[1] = pwt->w[3]; + pwd->w[3] = pws->w[3]; + break; + case DF_DOUBLE: + pwd->d[0] = pwt->d[1]; + pwd->d[1] = pws->d[1]; + break; + default: + assert(0); + } +} + + +void helper_msa_sldi_df(CPUMIPSState *env, uint32_t df, uint32_t wd, + uint32_t ws, uint32_t n) +{ + wr_t *pwd = &(env->active_fpu.fpr[wd].wr); + wr_t *pws = &(env->active_fpu.fpr[ws].wr); + + msa_sld_df(df, pwd, pws, n); +} + +void helper_msa_splati_df(CPUMIPSState *env, uint32_t df, uint32_t wd, + uint32_t ws, uint32_t n) +{ + wr_t *pwd = &(env->active_fpu.fpr[wd].wr); + wr_t *pws = &(env->active_fpu.fpr[ws].wr); + + msa_splat_df(df, pwd, pws, n); +} + +void helper_msa_copy_s_b(CPUMIPSState *env, uint32_t rd, + uint32_t ws, uint32_t n) +{ + n %= 16; +#if defined(HOST_WORDS_BIGENDIAN) + if (n < 8) { + n = 8 - n - 1; + } else { + n = 24 - n - 1; + } +#endif + env->active_tc.gpr[rd] = (int8_t)env->active_fpu.fpr[ws].wr.b[n]; +} + +void helper_msa_copy_s_h(CPUMIPSState *env, uint32_t rd, + uint32_t ws, uint32_t n) +{ + n %= 8; +#if defined(HOST_WORDS_BIGENDIAN) + if (n < 4) { + n = 4 - n - 1; + } else { + n = 12 - n - 1; + } +#endif + env->active_tc.gpr[rd] = (int16_t)env->active_fpu.fpr[ws].wr.h[n]; +} + +void helper_msa_copy_s_w(CPUMIPSState *env, uint32_t rd, + uint32_t ws, uint32_t n) +{ + n %= 4; +#if defined(HOST_WORDS_BIGENDIAN) + if (n < 2) { + n = 2 - n - 1; + } else { + n = 6 - n - 1; + } +#endif + env->active_tc.gpr[rd] = (int32_t)env->active_fpu.fpr[ws].wr.w[n]; +} + +void helper_msa_copy_s_d(CPUMIPSState *env, uint32_t rd, + uint32_t ws, uint32_t n) +{ + n %= 2; + env->active_tc.gpr[rd] = (int64_t)env->active_fpu.fpr[ws].wr.d[n]; +} + +void helper_msa_copy_u_b(CPUMIPSState *env, uint32_t rd, + uint32_t ws, uint32_t n) +{ + n %= 16; +#if defined(HOST_WORDS_BIGENDIAN) + if (n < 8) { + n = 8 - n - 1; + } else { + n = 24 - n - 1; + } +#endif + env->active_tc.gpr[rd] = (uint8_t)env->active_fpu.fpr[ws].wr.b[n]; +} + +void helper_msa_copy_u_h(CPUMIPSState *env, uint32_t rd, + uint32_t ws, uint32_t n) +{ + n %= 8; +#if defined(HOST_WORDS_BIGENDIAN) + if (n < 4) { + n = 4 - n - 1; + } else { + n = 12 - n - 1; + } +#endif + env->active_tc.gpr[rd] = (uint16_t)env->active_fpu.fpr[ws].wr.h[n]; +} + +void helper_msa_copy_u_w(CPUMIPSState *env, uint32_t rd, + uint32_t ws, uint32_t n) +{ + n %= 4; +#if defined(HOST_WORDS_BIGENDIAN) + if (n < 2) { + n = 2 - n - 1; + } else { + n = 6 - n - 1; + } +#endif + env->active_tc.gpr[rd] = (uint32_t)env->active_fpu.fpr[ws].wr.w[n]; +} + +void helper_msa_insert_b(CPUMIPSState *env, uint32_t wd, + uint32_t rs_num, uint32_t n) +{ + wr_t *pwd = &(env->active_fpu.fpr[wd].wr); + target_ulong rs = env->active_tc.gpr[rs_num]; + n %= 16; +#if defined(HOST_WORDS_BIGENDIAN) + if (n < 8) { + n = 8 - n - 1; + } else { + n = 24 - n - 1; + } +#endif + pwd->b[n] = (int8_t)rs; +} + +void helper_msa_insert_h(CPUMIPSState *env, uint32_t wd, + uint32_t rs_num, uint32_t n) +{ + wr_t *pwd = &(env->active_fpu.fpr[wd].wr); + target_ulong rs = env->active_tc.gpr[rs_num]; + n %= 8; +#if defined(HOST_WORDS_BIGENDIAN) + if (n < 4) { + n = 4 - n - 1; + } else { + n = 12 - n - 1; + } +#endif + pwd->h[n] = (int16_t)rs; +} + +void helper_msa_insert_w(CPUMIPSState *env, uint32_t wd, + uint32_t rs_num, uint32_t n) +{ + wr_t *pwd = &(env->active_fpu.fpr[wd].wr); + target_ulong rs = env->active_tc.gpr[rs_num]; + n %= 4; +#if defined(HOST_WORDS_BIGENDIAN) + if (n < 2) { + n = 2 - n - 1; + } else { + n = 6 - n - 1; + } +#endif + pwd->w[n] = (int32_t)rs; +} + +void helper_msa_insert_d(CPUMIPSState *env, uint32_t wd, + uint32_t rs_num, uint32_t n) +{ + wr_t *pwd = &(env->active_fpu.fpr[wd].wr); + target_ulong rs = env->active_tc.gpr[rs_num]; + n %= 2; + pwd->d[n] = (int64_t)rs; +} + void helper_msa_insve_df(CPUMIPSState *env, uint32_t df, uint32_t wd, uint32_t ws, uint32_t n) { @@ -1462,28 +2341,45 @@ void helper_msa_ ## func ## _df(CPUMIPSState *env, uint32_t df, \ { \ wr_t *pwd = &(env->active_fpu.fpr[wd].wr); \ wr_t *pws = &(env->active_fpu.fpr[ws].wr); \ - uint32_t i; \ \ switch (df) { \ case DF_BYTE: \ - for (i = 0; i < DF_ELEMENTS(DF_BYTE); i++) { \ - pwd->b[i] = msa_ ## func ## _df(df, pws->b[i]); \ - } \ + pwd->b[0] = msa_ ## func ## _df(df, pws->b[0]); \ + pwd->b[1] = msa_ ## func ## _df(df, pws->b[1]); \ + pwd->b[2] = msa_ ## func ## _df(df, pws->b[2]); \ + pwd->b[3] = msa_ ## func ## _df(df, pws->b[3]); \ + pwd->b[4] = msa_ ## func ## _df(df, pws->b[4]); \ + pwd->b[5] = msa_ ## func ## _df(df, pws->b[5]); \ + pwd->b[6] = msa_ ## func ## _df(df, pws->b[6]); \ + pwd->b[7] = msa_ ## func ## _df(df, pws->b[7]); \ + pwd->b[8] = msa_ ## func ## _df(df, pws->b[8]); \ + pwd->b[9] = msa_ ## func ## _df(df, pws->b[9]); \ + pwd->b[10] = msa_ ## func ## _df(df, pws->b[10]); \ + pwd->b[11] = msa_ ## func ## _df(df, pws->b[11]); \ + pwd->b[12] = msa_ ## func ## _df(df, pws->b[12]); \ + pwd->b[13] = msa_ ## func ## _df(df, pws->b[13]); \ + pwd->b[14] = msa_ ## func ## _df(df, pws->b[14]); \ + pwd->b[15] = msa_ ## func ## _df(df, pws->b[15]); \ break; \ case DF_HALF: \ - for (i = 0; i < DF_ELEMENTS(DF_HALF); i++) { \ - pwd->h[i] = msa_ ## func ## _df(df, pws->h[i]); \ - } \ + pwd->h[0] = msa_ ## func ## _df(df, pws->h[0]); \ + pwd->h[1] = msa_ ## func ## _df(df, pws->h[1]); \ + pwd->h[2] = msa_ ## func ## _df(df, pws->h[2]); \ + pwd->h[3] = msa_ ## func ## _df(df, pws->h[3]); \ + pwd->h[4] = msa_ ## func ## _df(df, pws->h[4]); \ + pwd->h[5] = msa_ ## func ## _df(df, pws->h[5]); \ + pwd->h[6] = msa_ ## func ## _df(df, pws->h[6]); \ + pwd->h[7] = msa_ ## func ## _df(df, pws->h[7]); \ break; \ case DF_WORD: \ - for (i = 0; i < DF_ELEMENTS(DF_WORD); i++) { \ - pwd->w[i] = msa_ ## func ## _df(df, pws->w[i]); \ - } \ + pwd->w[0] = msa_ ## func ## _df(df, pws->w[0]); \ + pwd->w[1] = msa_ ## func ## _df(df, pws->w[1]); \ + pwd->w[2] = msa_ ## func ## _df(df, pws->w[2]); \ + pwd->w[3] = msa_ ## func ## _df(df, pws->w[3]); \ break; \ case DF_DOUBLE: \ - for (i = 0; i < DF_ELEMENTS(DF_DOUBLE); i++) { \ - pwd->d[i] = msa_ ## func ## _df(df, pws->d[i]); \ - } \ + pwd->d[0] = msa_ ## func ## _df(df, pws->d[0]); \ + pwd->d[1] = msa_ ## func ## _df(df, pws->d[1]); \ break; \ default: \ assert(0); \ @@ -1576,8 +2472,10 @@ static inline int update_msacsr(CPUMIPSState *env, int action, int denormal) c &= ~FP_UNDERFLOW; } - /* Reciprocal operations set only Inexact when valid and not - divide by zero */ + /* + * Reciprocal operations set only Inexact when valid and not + * divide by zero + */ if ((action & RECIPROCAL_INEXACT) && (c & (FP_INVALID | FP_DIV0)) == 0) { c = FP_INEXACT; @@ -1586,15 +2484,19 @@ static inline int update_msacsr(CPUMIPSState *env, int action, int denormal) cause = c & enable; /* all current enabled exceptions */ if (cause == 0) { - /* No enabled exception, update the MSACSR Cause - with all current exceptions */ + /* + * No enabled exception, update the MSACSR Cause + * with all current exceptions + */ SET_FP_CAUSE(env->active_tc.msacsr, (GET_FP_CAUSE(env->active_tc.msacsr) | c)); } else { /* Current exceptions are enabled */ if ((env->active_tc.msacsr & MSACSR_NX_MASK) == 0) { - /* Exception(s) will trap, update MSACSR Cause - with all enabled exceptions */ + /* + * Exception(s) will trap, update MSACSR Cause + * with all enabled exceptions + */ SET_FP_CAUSE(env->active_tc.msacsr, (GET_FP_CAUSE(env->active_tc.msacsr) | c)); } @@ -2660,9 +3562,11 @@ void helper_msa_fexdo_df(CPUMIPSState *env, uint32_t df, uint32_t wd, switch (df) { case DF_WORD: for (i = 0; i < DF_ELEMENTS(DF_WORD); i++) { - /* Half precision floats come in two formats: standard - IEEE and "ARM" format. The latter gains extra exponent - range by omitting the NaN/Inf encodings. */ + /* + * Half precision floats come in two formats: standard + * IEEE and "ARM" format. The latter gains extra exponent + * range by omitting the NaN/Inf encodings. + */ flag ieee = 1; MSA_FLOAT_BINOP(Lh(pwx, i), from_float32, pws->w[i], ieee, 16); @@ -2921,7 +3825,7 @@ void helper_msa_fmax_a_df(CPUMIPSState *env, uint32_t df, uint32_t wd, void helper_msa_fclass_df(CPUMIPSState *env, uint32_t df, uint32_t wd, uint32_t ws) { - float_status* status = &env->active_tc.msa_fp_status; + float_status *status = &env->active_tc.msa_fp_status; wr_t *pwd = &(env->active_fpu.fpr[wd].wr); wr_t *pws = &(env->active_fpu.fpr[ws].wr); @@ -3218,9 +4122,11 @@ void helper_msa_fexupl_df(CPUMIPSState *env, uint32_t df, uint32_t wd, switch (df) { case DF_WORD: for (i = 0; i < DF_ELEMENTS(DF_WORD); i++) { - /* Half precision floats come in two formats: standard - IEEE and "ARM" format. The latter gains extra exponent - range by omitting the NaN/Inf encodings. */ + /* + * Half precision floats come in two formats: standard + * IEEE and "ARM" format. The latter gains extra exponent + * range by omitting the NaN/Inf encodings. + */ flag ieee = 1; MSA_FLOAT_BINOP(pwx->w[i], from_float16, Lh(pws, i), ieee, 32); @@ -3252,9 +4158,11 @@ void helper_msa_fexupr_df(CPUMIPSState *env, uint32_t df, uint32_t wd, switch (df) { case DF_WORD: for (i = 0; i < DF_ELEMENTS(DF_WORD); i++) { - /* Half precision floats come in two formats: standard - IEEE and "ARM" format. The latter gains extra exponent - range by omitting the NaN/Inf encodings. */ + /* + * Half precision floats come in two formats: standard + * IEEE and "ARM" format. The latter gains extra exponent + * range by omitting the NaN/Inf encodings. + */ flag ieee = 1; MSA_FLOAT_BINOP(pwx->w[i], from_float16, Rh(pws, i), ieee, 32); diff --git a/target/mips/op_helper.c b/target/mips/op_helper.c index 6d86912958..39180275b5 100644 --- a/target/mips/op_helper.c +++ b/target/mips/op_helper.c @@ -4356,31 +4356,179 @@ FOP_CONDN_S(sne, (float32_lt(fst1, fst0, &env->active_fpu.fp_status) #define MEMOP_IDX(DF) #endif -#define MSA_LD_DF(DF, TYPE, LD_INSN, ...) \ -void helper_msa_ld_ ## TYPE(CPUMIPSState *env, uint32_t wd, \ - target_ulong addr) \ -{ \ - wr_t *pwd = &(env->active_fpu.fpr[wd].wr); \ - wr_t wx; \ - int i; \ - MEMOP_IDX(DF) \ - for (i = 0; i < DF_ELEMENTS(DF); i++) { \ - wx.TYPE[i] = LD_INSN(env, addr + (i << DF), ##__VA_ARGS__); \ - } \ - memcpy(pwd, &wx, sizeof(wr_t)); \ +void helper_msa_ld_b(CPUMIPSState *env, uint32_t wd, + target_ulong addr) +{ + wr_t *pwd = &(env->active_fpu.fpr[wd].wr); + MEMOP_IDX(DF_BYTE) +#if !defined(CONFIG_USER_ONLY) +#if !defined(HOST_WORDS_BIGENDIAN) + pwd->b[0] = helper_ret_ldub_mmu(env, addr + (0 << DF_BYTE), oi, GETPC()); + pwd->b[1] = helper_ret_ldub_mmu(env, addr + (1 << DF_BYTE), oi, GETPC()); + pwd->b[2] = helper_ret_ldub_mmu(env, addr + (2 << DF_BYTE), oi, GETPC()); + pwd->b[3] = helper_ret_ldub_mmu(env, addr + (3 << DF_BYTE), oi, GETPC()); + pwd->b[4] = helper_ret_ldub_mmu(env, addr + (4 << DF_BYTE), oi, GETPC()); + pwd->b[5] = helper_ret_ldub_mmu(env, addr + (5 << DF_BYTE), oi, GETPC()); + pwd->b[6] = helper_ret_ldub_mmu(env, addr + (6 << DF_BYTE), oi, GETPC()); + pwd->b[7] = helper_ret_ldub_mmu(env, addr + (7 << DF_BYTE), oi, GETPC()); + pwd->b[8] = helper_ret_ldub_mmu(env, addr + (8 << DF_BYTE), oi, GETPC()); + pwd->b[9] = helper_ret_ldub_mmu(env, addr + (9 << DF_BYTE), oi, GETPC()); + pwd->b[10] = helper_ret_ldub_mmu(env, addr + (10 << DF_BYTE), oi, GETPC()); + pwd->b[11] = helper_ret_ldub_mmu(env, addr + (11 << DF_BYTE), oi, GETPC()); + pwd->b[12] = helper_ret_ldub_mmu(env, addr + (12 << DF_BYTE), oi, GETPC()); + pwd->b[13] = helper_ret_ldub_mmu(env, addr + (13 << DF_BYTE), oi, GETPC()); + pwd->b[14] = helper_ret_ldub_mmu(env, addr + (14 << DF_BYTE), oi, GETPC()); + pwd->b[15] = helper_ret_ldub_mmu(env, addr + (15 << DF_BYTE), oi, GETPC()); +#else + pwd->b[0] = helper_ret_ldub_mmu(env, addr + (7 << DF_BYTE), oi, GETPC()); + pwd->b[1] = helper_ret_ldub_mmu(env, addr + (6 << DF_BYTE), oi, GETPC()); + pwd->b[2] = helper_ret_ldub_mmu(env, addr + (5 << DF_BYTE), oi, GETPC()); + pwd->b[3] = helper_ret_ldub_mmu(env, addr + (4 << DF_BYTE), oi, GETPC()); + pwd->b[4] = helper_ret_ldub_mmu(env, addr + (3 << DF_BYTE), oi, GETPC()); + pwd->b[5] = helper_ret_ldub_mmu(env, addr + (2 << DF_BYTE), oi, GETPC()); + pwd->b[6] = helper_ret_ldub_mmu(env, addr + (1 << DF_BYTE), oi, GETPC()); + pwd->b[7] = helper_ret_ldub_mmu(env, addr + (0 << DF_BYTE), oi, GETPC()); + pwd->b[8] = helper_ret_ldub_mmu(env, addr + (15 << DF_BYTE), oi, GETPC()); + pwd->b[9] = helper_ret_ldub_mmu(env, addr + (14 << DF_BYTE), oi, GETPC()); + pwd->b[10] = helper_ret_ldub_mmu(env, addr + (13 << DF_BYTE), oi, GETPC()); + pwd->b[11] = helper_ret_ldub_mmu(env, addr + (12 << DF_BYTE), oi, GETPC()); + pwd->b[12] = helper_ret_ldub_mmu(env, addr + (11 << DF_BYTE), oi, GETPC()); + pwd->b[13] = helper_ret_ldub_mmu(env, addr + (10 << DF_BYTE), oi, GETPC()); + pwd->b[14] = helper_ret_ldub_mmu(env, addr + (9 << DF_BYTE), oi, GETPC()); + pwd->b[15] = helper_ret_ldub_mmu(env, addr + (8 << DF_BYTE), oi, GETPC()); +#endif +#else +#if !defined(HOST_WORDS_BIGENDIAN) + pwd->b[0] = cpu_ldub_data(env, addr + (0 << DF_BYTE)); + pwd->b[1] = cpu_ldub_data(env, addr + (1 << DF_BYTE)); + pwd->b[2] = cpu_ldub_data(env, addr + (2 << DF_BYTE)); + pwd->b[3] = cpu_ldub_data(env, addr + (3 << DF_BYTE)); + pwd->b[4] = cpu_ldub_data(env, addr + (4 << DF_BYTE)); + pwd->b[5] = cpu_ldub_data(env, addr + (5 << DF_BYTE)); + pwd->b[6] = cpu_ldub_data(env, addr + (6 << DF_BYTE)); + pwd->b[7] = cpu_ldub_data(env, addr + (7 << DF_BYTE)); + pwd->b[8] = cpu_ldub_data(env, addr + (8 << DF_BYTE)); + pwd->b[9] = cpu_ldub_data(env, addr + (9 << DF_BYTE)); + pwd->b[10] = cpu_ldub_data(env, addr + (10 << DF_BYTE)); + pwd->b[11] = cpu_ldub_data(env, addr + (11 << DF_BYTE)); + pwd->b[12] = cpu_ldub_data(env, addr + (12 << DF_BYTE)); + pwd->b[13] = cpu_ldub_data(env, addr + (13 << DF_BYTE)); + pwd->b[14] = cpu_ldub_data(env, addr + (14 << DF_BYTE)); + pwd->b[15] = cpu_ldub_data(env, addr + (15 << DF_BYTE)); +#else + pwd->b[0] = cpu_ldub_data(env, addr + (7 << DF_BYTE)); + pwd->b[1] = cpu_ldub_data(env, addr + (6 << DF_BYTE)); + pwd->b[2] = cpu_ldub_data(env, addr + (5 << DF_BYTE)); + pwd->b[3] = cpu_ldub_data(env, addr + (4 << DF_BYTE)); + pwd->b[4] = cpu_ldub_data(env, addr + (3 << DF_BYTE)); + pwd->b[5] = cpu_ldub_data(env, addr + (2 << DF_BYTE)); + pwd->b[6] = cpu_ldub_data(env, addr + (1 << DF_BYTE)); + pwd->b[7] = cpu_ldub_data(env, addr + (0 << DF_BYTE)); + pwd->b[8] = cpu_ldub_data(env, addr + (15 << DF_BYTE)); + pwd->b[9] = cpu_ldub_data(env, addr + (14 << DF_BYTE)); + pwd->b[10] = cpu_ldub_data(env, addr + (13 << DF_BYTE)); + pwd->b[11] = cpu_ldub_data(env, addr + (12 << DF_BYTE)); + pwd->b[12] = cpu_ldub_data(env, addr + (11 << DF_BYTE)); + pwd->b[13] = cpu_ldub_data(env, addr + (10 << DF_BYTE)); + pwd->b[14] = cpu_ldub_data(env, addr + (9 << DF_BYTE)); + pwd->b[15] = cpu_ldub_data(env, addr + (8 << DF_BYTE)); +#endif +#endif +} + +void helper_msa_ld_h(CPUMIPSState *env, uint32_t wd, + target_ulong addr) +{ + wr_t *pwd = &(env->active_fpu.fpr[wd].wr); + MEMOP_IDX(DF_HALF) +#if !defined(CONFIG_USER_ONLY) +#if !defined(HOST_WORDS_BIGENDIAN) + pwd->h[0] = helper_ret_lduw_mmu(env, addr + (0 << DF_HALF), oi, GETPC()); + pwd->h[1] = helper_ret_lduw_mmu(env, addr + (1 << DF_HALF), oi, GETPC()); + pwd->h[2] = helper_ret_lduw_mmu(env, addr + (2 << DF_HALF), oi, GETPC()); + pwd->h[3] = helper_ret_lduw_mmu(env, addr + (3 << DF_HALF), oi, GETPC()); + pwd->h[4] = helper_ret_lduw_mmu(env, addr + (4 << DF_HALF), oi, GETPC()); + pwd->h[5] = helper_ret_lduw_mmu(env, addr + (5 << DF_HALF), oi, GETPC()); + pwd->h[6] = helper_ret_lduw_mmu(env, addr + (6 << DF_HALF), oi, GETPC()); + pwd->h[7] = helper_ret_lduw_mmu(env, addr + (7 << DF_HALF), oi, GETPC()); +#else + pwd->h[0] = helper_ret_lduw_mmu(env, addr + (3 << DF_HALF), oi, GETPC()); + pwd->h[1] = helper_ret_lduw_mmu(env, addr + (2 << DF_HALF), oi, GETPC()); + pwd->h[2] = helper_ret_lduw_mmu(env, addr + (1 << DF_HALF), oi, GETPC()); + pwd->h[3] = helper_ret_lduw_mmu(env, addr + (0 << DF_HALF), oi, GETPC()); + pwd->h[4] = helper_ret_lduw_mmu(env, addr + (7 << DF_HALF), oi, GETPC()); + pwd->h[5] = helper_ret_lduw_mmu(env, addr + (6 << DF_HALF), oi, GETPC()); + pwd->h[6] = helper_ret_lduw_mmu(env, addr + (5 << DF_HALF), oi, GETPC()); + pwd->h[7] = helper_ret_lduw_mmu(env, addr + (4 << DF_HALF), oi, GETPC()); +#endif +#else +#if !defined(HOST_WORDS_BIGENDIAN) + pwd->h[0] = cpu_lduw_data(env, addr + (0 << DF_HALF)); + pwd->h[1] = cpu_lduw_data(env, addr + (1 << DF_HALF)); + pwd->h[2] = cpu_lduw_data(env, addr + (2 << DF_HALF)); + pwd->h[3] = cpu_lduw_data(env, addr + (3 << DF_HALF)); + pwd->h[4] = cpu_lduw_data(env, addr + (4 << DF_HALF)); + pwd->h[5] = cpu_lduw_data(env, addr + (5 << DF_HALF)); + pwd->h[6] = cpu_lduw_data(env, addr + (6 << DF_HALF)); + pwd->h[7] = cpu_lduw_data(env, addr + (7 << DF_HALF)); +#else + pwd->h[0] = cpu_lduw_data(env, addr + (3 << DF_HALF)); + pwd->h[1] = cpu_lduw_data(env, addr + (2 << DF_HALF)); + pwd->h[2] = cpu_lduw_data(env, addr + (1 << DF_HALF)); + pwd->h[3] = cpu_lduw_data(env, addr + (0 << DF_HALF)); + pwd->h[4] = cpu_lduw_data(env, addr + (7 << DF_HALF)); + pwd->h[5] = cpu_lduw_data(env, addr + (6 << DF_HALF)); + pwd->h[6] = cpu_lduw_data(env, addr + (5 << DF_HALF)); + pwd->h[7] = cpu_lduw_data(env, addr + (4 << DF_HALF)); +#endif +#endif } +void helper_msa_ld_w(CPUMIPSState *env, uint32_t wd, + target_ulong addr) +{ + wr_t *pwd = &(env->active_fpu.fpr[wd].wr); + MEMOP_IDX(DF_WORD) #if !defined(CONFIG_USER_ONLY) -MSA_LD_DF(DF_BYTE, b, helper_ret_ldub_mmu, oi, GETPC()) -MSA_LD_DF(DF_HALF, h, helper_ret_lduw_mmu, oi, GETPC()) -MSA_LD_DF(DF_WORD, w, helper_ret_ldul_mmu, oi, GETPC()) -MSA_LD_DF(DF_DOUBLE, d, helper_ret_ldq_mmu, oi, GETPC()) +#if !defined(HOST_WORDS_BIGENDIAN) + pwd->w[0] = helper_ret_ldul_mmu(env, addr + (0 << DF_WORD), oi, GETPC()); + pwd->w[1] = helper_ret_ldul_mmu(env, addr + (1 << DF_WORD), oi, GETPC()); + pwd->w[2] = helper_ret_ldul_mmu(env, addr + (2 << DF_WORD), oi, GETPC()); + pwd->w[3] = helper_ret_ldul_mmu(env, addr + (3 << DF_WORD), oi, GETPC()); #else -MSA_LD_DF(DF_BYTE, b, cpu_ldub_data) -MSA_LD_DF(DF_HALF, h, cpu_lduw_data) -MSA_LD_DF(DF_WORD, w, cpu_ldl_data) -MSA_LD_DF(DF_DOUBLE, d, cpu_ldq_data) + pwd->w[0] = helper_ret_ldul_mmu(env, addr + (1 << DF_WORD), oi, GETPC()); + pwd->w[1] = helper_ret_ldul_mmu(env, addr + (0 << DF_WORD), oi, GETPC()); + pwd->w[2] = helper_ret_ldul_mmu(env, addr + (3 << DF_WORD), oi, GETPC()); + pwd->w[3] = helper_ret_ldul_mmu(env, addr + (2 << DF_WORD), oi, GETPC()); #endif +#else +#if !defined(HOST_WORDS_BIGENDIAN) + pwd->w[0] = cpu_ldl_data(env, addr + (0 << DF_WORD)); + pwd->w[1] = cpu_ldl_data(env, addr + (1 << DF_WORD)); + pwd->w[2] = cpu_ldl_data(env, addr + (2 << DF_WORD)); + pwd->w[3] = cpu_ldl_data(env, addr + (3 << DF_WORD)); +#else + pwd->w[0] = cpu_ldl_data(env, addr + (1 << DF_WORD)); + pwd->w[1] = cpu_ldl_data(env, addr + (0 << DF_WORD)); + pwd->w[2] = cpu_ldl_data(env, addr + (3 << DF_WORD)); + pwd->w[3] = cpu_ldl_data(env, addr + (2 << DF_WORD)); +#endif +#endif +} + +void helper_msa_ld_d(CPUMIPSState *env, uint32_t wd, + target_ulong addr) +{ + wr_t *pwd = &(env->active_fpu.fpr[wd].wr); + MEMOP_IDX(DF_DOUBLE) +#if !defined(CONFIG_USER_ONLY) + pwd->d[0] = helper_ret_ldq_mmu(env, addr + (0 << DF_DOUBLE), oi, GETPC()); + pwd->d[1] = helper_ret_ldq_mmu(env, addr + (1 << DF_DOUBLE), oi, GETPC()); +#else + pwd->d[0] = cpu_ldq_data(env, addr + (0 << DF_DOUBLE)); + pwd->d[1] = cpu_ldq_data(env, addr + (1 << DF_DOUBLE)); +#endif +} #define MSA_PAGESPAN(x) \ ((((x) & ~TARGET_PAGE_MASK) + MSA_WRLEN/8 - 1) >= TARGET_PAGE_SIZE) @@ -4402,31 +4550,191 @@ static inline void ensure_writable_pages(CPUMIPSState *env, #endif } -#define MSA_ST_DF(DF, TYPE, ST_INSN, ...) \ -void helper_msa_st_ ## TYPE(CPUMIPSState *env, uint32_t wd, \ - target_ulong addr) \ -{ \ - wr_t *pwd = &(env->active_fpu.fpr[wd].wr); \ - int mmu_idx = cpu_mmu_index(env, false); \ - int i; \ - MEMOP_IDX(DF) \ - ensure_writable_pages(env, addr, mmu_idx, GETPC()); \ - for (i = 0; i < DF_ELEMENTS(DF); i++) { \ - ST_INSN(env, addr + (i << DF), pwd->TYPE[i], ##__VA_ARGS__); \ - } \ +void helper_msa_st_b(CPUMIPSState *env, uint32_t wd, + target_ulong addr) +{ + wr_t *pwd = &(env->active_fpu.fpr[wd].wr); + int mmu_idx = cpu_mmu_index(env, false); + + MEMOP_IDX(DF_BYTE) + ensure_writable_pages(env, addr, mmu_idx, GETPC()); +#if !defined(CONFIG_USER_ONLY) +#if !defined(HOST_WORDS_BIGENDIAN) + helper_ret_stb_mmu(env, addr + (0 << DF_BYTE), pwd->b[0], oi, GETPC()); + helper_ret_stb_mmu(env, addr + (1 << DF_BYTE), pwd->b[1], oi, GETPC()); + helper_ret_stb_mmu(env, addr + (2 << DF_BYTE), pwd->b[2], oi, GETPC()); + helper_ret_stb_mmu(env, addr + (3 << DF_BYTE), pwd->b[3], oi, GETPC()); + helper_ret_stb_mmu(env, addr + (4 << DF_BYTE), pwd->b[4], oi, GETPC()); + helper_ret_stb_mmu(env, addr + (5 << DF_BYTE), pwd->b[5], oi, GETPC()); + helper_ret_stb_mmu(env, addr + (6 << DF_BYTE), pwd->b[6], oi, GETPC()); + helper_ret_stb_mmu(env, addr + (7 << DF_BYTE), pwd->b[7], oi, GETPC()); + helper_ret_stb_mmu(env, addr + (8 << DF_BYTE), pwd->b[8], oi, GETPC()); + helper_ret_stb_mmu(env, addr + (9 << DF_BYTE), pwd->b[9], oi, GETPC()); + helper_ret_stb_mmu(env, addr + (10 << DF_BYTE), pwd->b[10], oi, GETPC()); + helper_ret_stb_mmu(env, addr + (11 << DF_BYTE), pwd->b[11], oi, GETPC()); + helper_ret_stb_mmu(env, addr + (12 << DF_BYTE), pwd->b[12], oi, GETPC()); + helper_ret_stb_mmu(env, addr + (13 << DF_BYTE), pwd->b[13], oi, GETPC()); + helper_ret_stb_mmu(env, addr + (14 << DF_BYTE), pwd->b[14], oi, GETPC()); + helper_ret_stb_mmu(env, addr + (15 << DF_BYTE), pwd->b[15], oi, GETPC()); +#else + helper_ret_stb_mmu(env, addr + (7 << DF_BYTE), pwd->b[0], oi, GETPC()); + helper_ret_stb_mmu(env, addr + (6 << DF_BYTE), pwd->b[1], oi, GETPC()); + helper_ret_stb_mmu(env, addr + (5 << DF_BYTE), pwd->b[2], oi, GETPC()); + helper_ret_stb_mmu(env, addr + (4 << DF_BYTE), pwd->b[3], oi, GETPC()); + helper_ret_stb_mmu(env, addr + (3 << DF_BYTE), pwd->b[4], oi, GETPC()); + helper_ret_stb_mmu(env, addr + (2 << DF_BYTE), pwd->b[5], oi, GETPC()); + helper_ret_stb_mmu(env, addr + (1 << DF_BYTE), pwd->b[6], oi, GETPC()); + helper_ret_stb_mmu(env, addr + (0 << DF_BYTE), pwd->b[7], oi, GETPC()); + helper_ret_stb_mmu(env, addr + (15 << DF_BYTE), pwd->b[8], oi, GETPC()); + helper_ret_stb_mmu(env, addr + (14 << DF_BYTE), pwd->b[9], oi, GETPC()); + helper_ret_stb_mmu(env, addr + (13 << DF_BYTE), pwd->b[10], oi, GETPC()); + helper_ret_stb_mmu(env, addr + (12 << DF_BYTE), pwd->b[11], oi, GETPC()); + helper_ret_stb_mmu(env, addr + (11 << DF_BYTE), pwd->b[12], oi, GETPC()); + helper_ret_stb_mmu(env, addr + (10 << DF_BYTE), pwd->b[13], oi, GETPC()); + helper_ret_stb_mmu(env, addr + (9 << DF_BYTE), pwd->b[14], oi, GETPC()); + helper_ret_stb_mmu(env, addr + (8 << DF_BYTE), pwd->b[15], oi, GETPC()); +#endif +#else +#if !defined(HOST_WORDS_BIGENDIAN) + cpu_stb_data(env, addr + (0 << DF_BYTE), pwd->b[0]); + cpu_stb_data(env, addr + (1 << DF_BYTE), pwd->b[1]); + cpu_stb_data(env, addr + (2 << DF_BYTE), pwd->b[2]); + cpu_stb_data(env, addr + (3 << DF_BYTE), pwd->b[3]); + cpu_stb_data(env, addr + (4 << DF_BYTE), pwd->b[4]); + cpu_stb_data(env, addr + (5 << DF_BYTE), pwd->b[5]); + cpu_stb_data(env, addr + (6 << DF_BYTE), pwd->b[6]); + cpu_stb_data(env, addr + (7 << DF_BYTE), pwd->b[7]); + cpu_stb_data(env, addr + (8 << DF_BYTE), pwd->b[8]); + cpu_stb_data(env, addr + (9 << DF_BYTE), pwd->b[9]); + cpu_stb_data(env, addr + (10 << DF_BYTE), pwd->b[10]); + cpu_stb_data(env, addr + (11 << DF_BYTE), pwd->b[11]); + cpu_stb_data(env, addr + (12 << DF_BYTE), pwd->b[12]); + cpu_stb_data(env, addr + (13 << DF_BYTE), pwd->b[13]); + cpu_stb_data(env, addr + (14 << DF_BYTE), pwd->b[14]); + cpu_stb_data(env, addr + (15 << DF_BYTE), pwd->b[15]); +#else + cpu_stb_data(env, addr + (7 << DF_BYTE), pwd->b[0]); + cpu_stb_data(env, addr + (6 << DF_BYTE), pwd->b[1]); + cpu_stb_data(env, addr + (5 << DF_BYTE), pwd->b[2]); + cpu_stb_data(env, addr + (4 << DF_BYTE), pwd->b[3]); + cpu_stb_data(env, addr + (3 << DF_BYTE), pwd->b[4]); + cpu_stb_data(env, addr + (2 << DF_BYTE), pwd->b[5]); + cpu_stb_data(env, addr + (1 << DF_BYTE), pwd->b[6]); + cpu_stb_data(env, addr + (0 << DF_BYTE), pwd->b[7]); + cpu_stb_data(env, addr + (15 << DF_BYTE), pwd->b[8]); + cpu_stb_data(env, addr + (14 << DF_BYTE), pwd->b[9]); + cpu_stb_data(env, addr + (13 << DF_BYTE), pwd->b[10]); + cpu_stb_data(env, addr + (12 << DF_BYTE), pwd->b[11]); + cpu_stb_data(env, addr + (11 << DF_BYTE), pwd->b[12]); + cpu_stb_data(env, addr + (10 << DF_BYTE), pwd->b[13]); + cpu_stb_data(env, addr + (9 << DF_BYTE), pwd->b[14]); + cpu_stb_data(env, addr + (8 << DF_BYTE), pwd->b[15]); +#endif +#endif +} + +void helper_msa_st_h(CPUMIPSState *env, uint32_t wd, + target_ulong addr) +{ + wr_t *pwd = &(env->active_fpu.fpr[wd].wr); + int mmu_idx = cpu_mmu_index(env, false); + + MEMOP_IDX(DF_HALF) + ensure_writable_pages(env, addr, mmu_idx, GETPC()); +#if !defined(CONFIG_USER_ONLY) +#if !defined(HOST_WORDS_BIGENDIAN) + helper_ret_stw_mmu(env, addr + (0 << DF_HALF), pwd->h[0], oi, GETPC()); + helper_ret_stw_mmu(env, addr + (1 << DF_HALF), pwd->h[1], oi, GETPC()); + helper_ret_stw_mmu(env, addr + (2 << DF_HALF), pwd->h[2], oi, GETPC()); + helper_ret_stw_mmu(env, addr + (3 << DF_HALF), pwd->h[3], oi, GETPC()); + helper_ret_stw_mmu(env, addr + (4 << DF_HALF), pwd->h[4], oi, GETPC()); + helper_ret_stw_mmu(env, addr + (5 << DF_HALF), pwd->h[5], oi, GETPC()); + helper_ret_stw_mmu(env, addr + (6 << DF_HALF), pwd->h[6], oi, GETPC()); + helper_ret_stw_mmu(env, addr + (7 << DF_HALF), pwd->h[7], oi, GETPC()); +#else + helper_ret_stw_mmu(env, addr + (3 << DF_HALF), pwd->h[0], oi, GETPC()); + helper_ret_stw_mmu(env, addr + (2 << DF_HALF), pwd->h[1], oi, GETPC()); + helper_ret_stw_mmu(env, addr + (1 << DF_HALF), pwd->h[2], oi, GETPC()); + helper_ret_stw_mmu(env, addr + (0 << DF_HALF), pwd->h[3], oi, GETPC()); + helper_ret_stw_mmu(env, addr + (7 << DF_HALF), pwd->h[4], oi, GETPC()); + helper_ret_stw_mmu(env, addr + (6 << DF_HALF), pwd->h[5], oi, GETPC()); + helper_ret_stw_mmu(env, addr + (5 << DF_HALF), pwd->h[6], oi, GETPC()); + helper_ret_stw_mmu(env, addr + (4 << DF_HALF), pwd->h[7], oi, GETPC()); +#endif +#else +#if !defined(HOST_WORDS_BIGENDIAN) + cpu_stw_data(env, addr + (0 << DF_HALF), pwd->h[0]); + cpu_stw_data(env, addr + (1 << DF_HALF), pwd->h[1]); + cpu_stw_data(env, addr + (2 << DF_HALF), pwd->h[2]); + cpu_stw_data(env, addr + (3 << DF_HALF), pwd->h[3]); + cpu_stw_data(env, addr + (4 << DF_HALF), pwd->h[4]); + cpu_stw_data(env, addr + (5 << DF_HALF), pwd->h[5]); + cpu_stw_data(env, addr + (6 << DF_HALF), pwd->h[6]); + cpu_stw_data(env, addr + (7 << DF_HALF), pwd->h[7]); +#else + cpu_stw_data(env, addr + (3 << DF_HALF), pwd->h[0]); + cpu_stw_data(env, addr + (2 << DF_HALF), pwd->h[1]); + cpu_stw_data(env, addr + (1 << DF_HALF), pwd->h[2]); + cpu_stw_data(env, addr + (0 << DF_HALF), pwd->h[3]); + cpu_stw_data(env, addr + (7 << DF_HALF), pwd->h[4]); + cpu_stw_data(env, addr + (6 << DF_HALF), pwd->h[5]); + cpu_stw_data(env, addr + (5 << DF_HALF), pwd->h[6]); + cpu_stw_data(env, addr + (4 << DF_HALF), pwd->h[7]); +#endif +#endif } +void helper_msa_st_w(CPUMIPSState *env, uint32_t wd, + target_ulong addr) +{ + wr_t *pwd = &(env->active_fpu.fpr[wd].wr); + int mmu_idx = cpu_mmu_index(env, false); + + MEMOP_IDX(DF_WORD) + ensure_writable_pages(env, addr, mmu_idx, GETPC()); #if !defined(CONFIG_USER_ONLY) -MSA_ST_DF(DF_BYTE, b, helper_ret_stb_mmu, oi, GETPC()) -MSA_ST_DF(DF_HALF, h, helper_ret_stw_mmu, oi, GETPC()) -MSA_ST_DF(DF_WORD, w, helper_ret_stl_mmu, oi, GETPC()) -MSA_ST_DF(DF_DOUBLE, d, helper_ret_stq_mmu, oi, GETPC()) +#if !defined(HOST_WORDS_BIGENDIAN) + helper_ret_stl_mmu(env, addr + (0 << DF_WORD), oi, GETPC(), pwd->w[0]); + helper_ret_stl_mmu(env, addr + (1 << DF_WORD), oi, GETPC(), pwd->w[1]); + helper_ret_stl_mmu(env, addr + (2 << DF_WORD), oi, GETPC(), pwd->w[2]); + helper_ret_stl_mmu(env, addr + (3 << DF_WORD), oi, GETPC(), pwd->w[3]); #else -MSA_ST_DF(DF_BYTE, b, cpu_stb_data) -MSA_ST_DF(DF_HALF, h, cpu_stw_data) -MSA_ST_DF(DF_WORD, w, cpu_stl_data) -MSA_ST_DF(DF_DOUBLE, d, cpu_stq_data) + helper_ret_stl_mmu(env, addr + (1 << DF_WORD), oi, GETPC(), pwd->w[0]); + helper_ret_stl_mmu(env, addr + (0 << DF_WORD), oi, GETPC(), pwd->w[1]); + helper_ret_stl_mmu(env, addr + (3 << DF_WORD), oi, GETPC(), pwd->w[2]); + helper_ret_stl_mmu(env, addr + (2 << DF_WORD), oi, GETPC(), pwd->w[3]); +#endif +#else +#if !defined(HOST_WORDS_BIGENDIAN) + cpu_stl_data(env, addr + (0 << DF_WORD), pwd->w[0]); + cpu_stl_data(env, addr + (1 << DF_WORD), pwd->w[1]); + cpu_stl_data(env, addr + (2 << DF_WORD), pwd->w[2]); + cpu_stl_data(env, addr + (3 << DF_WORD), pwd->w[3]); +#else + cpu_stl_data(env, addr + (1 << DF_WORD), pwd->w[0]); + cpu_stl_data(env, addr + (0 << DF_WORD), pwd->w[1]); + cpu_stl_data(env, addr + (3 << DF_WORD), pwd->w[2]); + cpu_stl_data(env, addr + (2 << DF_WORD), pwd->w[3]); +#endif #endif +} + +void helper_msa_st_d(CPUMIPSState *env, uint32_t wd, + target_ulong addr) +{ + wr_t *pwd = &(env->active_fpu.fpr[wd].wr); + int mmu_idx = cpu_mmu_index(env, false); + + MEMOP_IDX(DF_DOUBLE) + ensure_writable_pages(env, addr, mmu_idx, GETPC()); +#if !defined(CONFIG_USER_ONLY) + helper_ret_stq_mmu(env, addr + (0 << DF_DOUBLE), pwd->d[0], oi, GETPC()); + helper_ret_stq_mmu(env, addr + (1 << DF_DOUBLE), pwd->d[1], oi, GETPC()); +#else + cpu_stq_data(env, addr + (0 << DF_DOUBLE), pwd->d[0]); + cpu_stq_data(env, addr + (1 << DF_DOUBLE), pwd->d[1]); +#endif +} void helper_cache(CPUMIPSState *env, target_ulong addr, uint32_t op) { diff --git a/target/mips/translate.c b/target/mips/translate.c index f96c0d01ef..e37722dfff 100644 --- a/target/mips/translate.c +++ b/target/mips/translate.c @@ -32,7 +32,7 @@ #include "exec/helper-proto.h" #include "exec/helper-gen.h" -#include "exec/semihost.h" +#include "hw/semihosting/semihost.h" #include "target/mips/trace.h" #include "trace-tcg.h" @@ -13726,6 +13726,14 @@ static inline bool is_uhi(int sdbbp_code) #endif } +#ifdef CONFIG_USER_ONLY +/* The above should dead-code away any calls to this..*/ +static inline void gen_helper_do_semihosting(void *env) +{ + g_assert_not_reached(); +} +#endif + static int decode_mips16_opc (CPUMIPSState *env, DisasContext *ctx) { int rx, ry; @@ -24349,6 +24357,146 @@ static void decode_opc_special(CPUMIPSState *env, DisasContext *ctx) * PEXTUW */ +/* + * PCPYH rd, rt + * + * Parallel Copy Halfword + * + * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 + * +-----------+---------+---------+---------+---------+-----------+ + * | MMI |0 0 0 0 0| rt | rd | PCPYH | MMI3 | + * +-----------+---------+---------+---------+---------+-----------+ + */ +static void gen_mmi_pcpyh(DisasContext *ctx) +{ + uint32_t pd, rt, rd; + uint32_t opcode; + + opcode = ctx->opcode; + + pd = extract32(opcode, 21, 5); + rt = extract32(opcode, 16, 5); + rd = extract32(opcode, 11, 5); + + if (unlikely(pd != 0)) { + generate_exception_end(ctx, EXCP_RI); + } else if (rd == 0) { + /* nop */ + } else if (rt == 0) { + tcg_gen_movi_i64(cpu_gpr[rd], 0); + tcg_gen_movi_i64(cpu_mmr[rd], 0); + } else { + TCGv_i64 t0 = tcg_temp_new(); + TCGv_i64 t1 = tcg_temp_new(); + uint64_t mask = (1ULL << 16) - 1; + + tcg_gen_andi_i64(t0, cpu_gpr[rt], mask); + tcg_gen_movi_i64(t1, 0); + tcg_gen_or_i64(t1, t0, t1); + tcg_gen_shli_i64(t0, t0, 16); + tcg_gen_or_i64(t1, t0, t1); + tcg_gen_shli_i64(t0, t0, 16); + tcg_gen_or_i64(t1, t0, t1); + tcg_gen_shli_i64(t0, t0, 16); + tcg_gen_or_i64(t1, t0, t1); + + tcg_gen_mov_i64(cpu_gpr[rd], t1); + + tcg_gen_andi_i64(t0, cpu_mmr[rt], mask); + tcg_gen_movi_i64(t1, 0); + tcg_gen_or_i64(t1, t0, t1); + tcg_gen_shli_i64(t0, t0, 16); + tcg_gen_or_i64(t1, t0, t1); + tcg_gen_shli_i64(t0, t0, 16); + tcg_gen_or_i64(t1, t0, t1); + tcg_gen_shli_i64(t0, t0, 16); + tcg_gen_or_i64(t1, t0, t1); + + tcg_gen_mov_i64(cpu_mmr[rd], t1); + + tcg_temp_free(t0); + tcg_temp_free(t1); + } +} + +/* + * PCPYLD rd, rs, rt + * + * Parallel Copy Lower Doubleword + * + * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 + * +-----------+---------+---------+---------+---------+-----------+ + * | MMI | rs | rt | rd | PCPYLD | MMI2 | + * +-----------+---------+---------+---------+---------+-----------+ + */ +static void gen_mmi_pcpyld(DisasContext *ctx) +{ + uint32_t rs, rt, rd; + uint32_t opcode; + + opcode = ctx->opcode; + + rs = extract32(opcode, 21, 5); + rt = extract32(opcode, 16, 5); + rd = extract32(opcode, 11, 5); + + if (rd == 0) { + /* nop */ + } else { + if (rs == 0) { + tcg_gen_movi_i64(cpu_mmr[rd], 0); + } else { + tcg_gen_mov_i64(cpu_mmr[rd], cpu_gpr[rs]); + } + if (rt == 0) { + tcg_gen_movi_i64(cpu_gpr[rd], 0); + } else { + if (rd != rt) { + tcg_gen_mov_i64(cpu_gpr[rd], cpu_gpr[rt]); + } + } + } +} + +/* + * PCPYUD rd, rs, rt + * + * Parallel Copy Upper Doubleword + * + * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 + * +-----------+---------+---------+---------+---------+-----------+ + * | MMI | rs | rt | rd | PCPYUD | MMI3 | + * +-----------+---------+---------+---------+---------+-----------+ + */ +static void gen_mmi_pcpyud(DisasContext *ctx) +{ + uint32_t rs, rt, rd; + uint32_t opcode; + + opcode = ctx->opcode; + + rs = extract32(opcode, 21, 5); + rt = extract32(opcode, 16, 5); + rd = extract32(opcode, 11, 5); + + if (rd == 0) { + /* nop */ + } else { + if (rs == 0) { + tcg_gen_movi_i64(cpu_gpr[rd], 0); + } else { + tcg_gen_mov_i64(cpu_gpr[rd], cpu_mmr[rs]); + } + if (rt == 0) { + tcg_gen_movi_i64(cpu_mmr[rd], 0); + } else { + if (rd != rt) { + tcg_gen_mov_i64(cpu_mmr[rd], cpu_mmr[rt]); + } + } + } +} + #endif @@ -27363,7 +27511,6 @@ static void decode_mmi2(CPUMIPSState *env, DisasContext *ctx) case MMI_OPC_2_PINTH: /* TODO: MMI_OPC_2_PINTH */ case MMI_OPC_2_PMULTW: /* TODO: MMI_OPC_2_PMULTW */ case MMI_OPC_2_PDIVW: /* TODO: MMI_OPC_2_PDIVW */ - case MMI_OPC_2_PCPYLD: /* TODO: MMI_OPC_2_PCPYLD */ case MMI_OPC_2_PMADDH: /* TODO: MMI_OPC_2_PMADDH */ case MMI_OPC_2_PHMADH: /* TODO: MMI_OPC_2_PHMADH */ case MMI_OPC_2_PAND: /* TODO: MMI_OPC_2_PAND */ @@ -27378,6 +27525,9 @@ static void decode_mmi2(CPUMIPSState *env, DisasContext *ctx) case MMI_OPC_2_PROT3W: /* TODO: MMI_OPC_2_PROT3W */ generate_exception_end(ctx, EXCP_RI); /* TODO: MMI_OPC_CLASS_MMI2 */ break; + case MMI_OPC_2_PCPYLD: + gen_mmi_pcpyld(ctx); + break; default: MIPS_INVAL("TX79 MMI class MMI2"); generate_exception_end(ctx, EXCP_RI); @@ -27397,14 +27547,18 @@ static void decode_mmi3(CPUMIPSState *env, DisasContext *ctx) case MMI_OPC_3_PINTEH: /* TODO: MMI_OPC_3_PINTEH */ case MMI_OPC_3_PMULTUW: /* TODO: MMI_OPC_3_PMULTUW */ case MMI_OPC_3_PDIVUW: /* TODO: MMI_OPC_3_PDIVUW */ - case MMI_OPC_3_PCPYUD: /* TODO: MMI_OPC_3_PCPYUD */ case MMI_OPC_3_POR: /* TODO: MMI_OPC_3_POR */ case MMI_OPC_3_PNOR: /* TODO: MMI_OPC_3_PNOR */ case MMI_OPC_3_PEXCH: /* TODO: MMI_OPC_3_PEXCH */ - case MMI_OPC_3_PCPYH: /* TODO: MMI_OPC_3_PCPYH */ case MMI_OPC_3_PEXCW: /* TODO: MMI_OPC_3_PEXCW */ generate_exception_end(ctx, EXCP_RI); /* TODO: MMI_OPC_CLASS_MMI3 */ break; + case MMI_OPC_3_PCPYH: + gen_mmi_pcpyh(ctx); + break; + case MMI_OPC_3_PCPYUD: + gen_mmi_pcpyud(ctx); + break; default: MIPS_INVAL("TX79 MMI class MMI3"); generate_exception_end(ctx, EXCP_RI); @@ -28297,20 +28451,73 @@ static void gen_msa_elm_df(CPUMIPSState *env, DisasContext *ctx, uint32_t df, generate_exception_end(ctx, EXCP_RI); break; } + if ((MASK_MSA_ELM(ctx->opcode) == OPC_COPY_U_df) && + (df == DF_WORD)) { + generate_exception_end(ctx, EXCP_RI); + break; + } #endif switch (MASK_MSA_ELM(ctx->opcode)) { case OPC_COPY_S_df: if (likely(wd != 0)) { - gen_helper_msa_copy_s_df(cpu_env, tdf, twd, tws, tn); + switch (df) { + case DF_BYTE: + gen_helper_msa_copy_s_b(cpu_env, twd, tws, tn); + break; + case DF_HALF: + gen_helper_msa_copy_s_h(cpu_env, twd, tws, tn); + break; + case DF_WORD: + gen_helper_msa_copy_s_w(cpu_env, twd, tws, tn); + break; +#if defined(TARGET_MIPS64) + case DF_DOUBLE: + gen_helper_msa_copy_s_d(cpu_env, twd, tws, tn); + break; +#endif + default: + assert(0); + } } break; case OPC_COPY_U_df: if (likely(wd != 0)) { - gen_helper_msa_copy_u_df(cpu_env, tdf, twd, tws, tn); + switch (df) { + case DF_BYTE: + gen_helper_msa_copy_u_b(cpu_env, twd, tws, tn); + break; + case DF_HALF: + gen_helper_msa_copy_u_h(cpu_env, twd, tws, tn); + break; +#if defined(TARGET_MIPS64) + case DF_WORD: + gen_helper_msa_copy_u_w(cpu_env, twd, tws, tn); + break; +#endif + default: + assert(0); + } } break; case OPC_INSERT_df: - gen_helper_msa_insert_df(cpu_env, tdf, twd, tws, tn); + switch (df) { + case DF_BYTE: + gen_helper_msa_insert_b(cpu_env, twd, tws, tn); + break; + case DF_HALF: + gen_helper_msa_insert_h(cpu_env, twd, tws, tn); + break; + case DF_WORD: + gen_helper_msa_insert_w(cpu_env, twd, tws, tn); + break; +#if defined(TARGET_MIPS64) + case DF_DOUBLE: + gen_helper_msa_insert_d(cpu_env, twd, tws, tn); + break; +#endif + default: + assert(0); + } break; } break; diff --git a/target/nios2/helper.c b/target/nios2/helper.c index ffb83fc104..57c97bde3c 100644 --- a/target/nios2/helper.c +++ b/target/nios2/helper.c @@ -26,7 +26,7 @@ #include "exec/cpu_ldst.h" #include "exec/log.h" #include "exec/helper-proto.h" -#include "exec/semihost.h" +#include "hw/semihosting/semihost.h" #if defined(CONFIG_USER_ONLY) diff --git a/target/ppc/helper.h b/target/ppc/helper.h index 638a6e99c4..02b67a333e 100644 --- a/target/ppc/helper.h +++ b/target/ppc/helper.h @@ -180,18 +180,6 @@ DEF_HELPER_3(vmuloub, void, avr, avr, avr) DEF_HELPER_3(vmulouh, void, avr, avr, avr) DEF_HELPER_3(vmulouw, void, avr, avr, avr) DEF_HELPER_3(vmuluwm, void, avr, avr, avr) -DEF_HELPER_3(vsrab, void, avr, avr, avr) -DEF_HELPER_3(vsrah, void, avr, avr, avr) -DEF_HELPER_3(vsraw, void, avr, avr, avr) -DEF_HELPER_3(vsrad, void, avr, avr, avr) -DEF_HELPER_3(vsrb, void, avr, avr, avr) -DEF_HELPER_3(vsrh, void, avr, avr, avr) -DEF_HELPER_3(vsrw, void, avr, avr, avr) -DEF_HELPER_3(vsrd, void, avr, avr, avr) -DEF_HELPER_3(vslb, void, avr, avr, avr) -DEF_HELPER_3(vslh, void, avr, avr, avr) -DEF_HELPER_3(vslw, void, avr, avr, avr) -DEF_HELPER_3(vsld, void, avr, avr, avr) DEF_HELPER_3(vslo, void, avr, avr, avr) DEF_HELPER_3(vsro, void, avr, avr, avr) DEF_HELPER_3(vsrv, void, avr, avr, avr) diff --git a/target/ppc/int_helper.c b/target/ppc/int_helper.c index 9af779ad38..8ce89f2ad9 100644 --- a/target/ppc/int_helper.c +++ b/target/ppc/int_helper.c @@ -1791,23 +1791,6 @@ VSHIFT(l, 1) VSHIFT(r, 0) #undef VSHIFT -#define VSL(suffix, element, mask) \ - void helper_vsl##suffix(ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b) \ - { \ - int i; \ - \ - for (i = 0; i < ARRAY_SIZE(r->element); i++) { \ - unsigned int shift = b->element[i] & mask; \ - \ - r->element[i] = a->element[i] << shift; \ - } \ - } -VSL(b, u8, 0x7) -VSL(h, u16, 0x0F) -VSL(w, u32, 0x1F) -VSL(d, u64, 0x3F) -#undef VSL - void helper_vslv(ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b) { int i; @@ -1815,10 +1798,10 @@ void helper_vslv(ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b) size = ARRAY_SIZE(r->u8); for (i = 0; i < size; i++) { - shift = b->u8[i] & 0x7; /* extract shift value */ - bytes = (a->u8[i] << 8) + /* extract adjacent bytes */ - (((i + 1) < size) ? a->u8[i + 1] : 0); - r->u8[i] = (bytes << shift) >> 8; /* shift and store result */ + shift = b->VsrB(i) & 0x7; /* extract shift value */ + bytes = (a->VsrB(i) << 8) + /* extract adjacent bytes */ + (((i + 1) < size) ? a->VsrB(i + 1) : 0); + r->VsrB(i) = (bytes << shift) >> 8; /* shift and store result */ } } @@ -1833,10 +1816,10 @@ void helper_vsrv(ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b) * order will guarantee that computed result is not fed back. */ for (i = ARRAY_SIZE(r->u8) - 1; i >= 0; i--) { - shift = b->u8[i] & 0x7; /* extract shift value */ - bytes = ((i ? a->u8[i - 1] : 0) << 8) + a->u8[i]; + shift = b->VsrB(i) & 0x7; /* extract shift value */ + bytes = ((i ? a->VsrB(i - 1) : 0) << 8) + a->VsrB(i); /* extract adjacent bytes */ - r->u8[i] = (bytes >> shift) & 0xFF; /* shift and store result */ + r->VsrB(i) = (bytes >> shift) & 0xFF; /* shift and store result */ } } @@ -1980,26 +1963,6 @@ VNEG(vnegw, s32) VNEG(vnegd, s64) #undef VNEG -#define VSR(suffix, element, mask) \ - void helper_vsr##suffix(ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b) \ - { \ - int i; \ - \ - for (i = 0; i < ARRAY_SIZE(r->element); i++) { \ - unsigned int shift = b->element[i] & mask; \ - r->element[i] = a->element[i] >> shift; \ - } \ - } -VSR(ab, s8, 0x7) -VSR(ah, s16, 0xF) -VSR(aw, s32, 0x1F) -VSR(ad, s64, 0x3F) -VSR(b, u8, 0x7) -VSR(h, u16, 0xF) -VSR(w, u32, 0x1F) -VSR(d, u64, 0x3F) -#undef VSR - void helper_vsro(ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b) { int sh = (b->VsrB(0xf) >> 3) & 0xf; @@ -2053,7 +2016,7 @@ void helper_vsum2sws(CPUPPCState *env, ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b) for (i = 0; i < ARRAY_SIZE(r->u64); i++) { int64_t t = (int64_t)b->VsrSW(upper + i * 2); - result.VsrW(i) = 0; + result.VsrD(i) = 0; for (j = 0; j < ARRAY_SIZE(r->u64); j++) { t += a->VsrSW(2 * i + j); } diff --git a/target/ppc/kvm.c b/target/ppc/kvm.c index 02e22e2017..3bf0a46c33 100644 --- a/target/ppc/kvm.c +++ b/target/ppc/kvm.c @@ -75,6 +75,7 @@ static int cap_fixup_hcalls; static int cap_htm; /* Hardware transactional memory support */ static int cap_mmu_radix; static int cap_mmu_hash_v3; +static int cap_xive; static int cap_resize_hpt; static int cap_ppc_pvr_compat; static int cap_ppc_safe_cache; @@ -146,6 +147,7 @@ int kvm_arch_init(MachineState *ms, KVMState *s) cap_htm = kvm_vm_check_extension(s, KVM_CAP_PPC_HTM); cap_mmu_radix = kvm_vm_check_extension(s, KVM_CAP_PPC_MMU_RADIX); cap_mmu_hash_v3 = kvm_vm_check_extension(s, KVM_CAP_PPC_MMU_HASH_V3); + cap_xive = kvm_vm_check_extension(s, KVM_CAP_PPC_IRQ_XIVE); cap_resize_hpt = kvm_vm_check_extension(s, KVM_CAP_SPAPR_RESIZE_HPT); kvmppc_get_cpu_characteristics(s); cap_ppc_nested_kvm_hv = kvm_vm_check_extension(s, KVM_CAP_PPC_NESTED_HV); @@ -1721,7 +1723,7 @@ int kvm_arch_handle_exit(CPUState *cs, struct kvm_run *run) trace_kvm_handle_dcr_write(); ret = kvmppc_handle_dcr_write(env, run->dcr.dcrn, run->dcr.data); } else { - trace_kvm_handle_drc_read(); + trace_kvm_handle_dcr_read(); ret = kvmppc_handle_dcr_read(env, run->dcr.dcrn, &run->dcr.data); } break; @@ -2478,6 +2480,11 @@ static int parse_cap_ppc_count_cache_flush_assist(struct kvm_ppc_cpu_char c) return 0; } +bool kvmppc_has_cap_xive(void) +{ + return cap_xive; +} + static void kvmppc_get_cpu_characteristics(KVMState *s) { struct kvm_ppc_cpu_char c; diff --git a/target/ppc/kvm_ppc.h b/target/ppc/kvm_ppc.h index 22385134b4..45776cad79 100644 --- a/target/ppc/kvm_ppc.h +++ b/target/ppc/kvm_ppc.h @@ -60,6 +60,7 @@ bool kvmppc_has_cap_fixup_hcalls(void); bool kvmppc_has_cap_htm(void); bool kvmppc_has_cap_mmu_radix(void); bool kvmppc_has_cap_mmu_hash_v3(void); +bool kvmppc_has_cap_xive(void); int kvmppc_get_cap_safe_cache(void); int kvmppc_get_cap_safe_bounds_check(void); int kvmppc_get_cap_safe_indirect_branch(void); @@ -316,6 +317,11 @@ static inline bool kvmppc_has_cap_mmu_hash_v3(void) return false; } +static inline bool kvmppc_has_cap_xive(void) +{ + return false; +} + static inline int kvmppc_get_cap_safe_cache(void) { return 0; diff --git a/target/ppc/trace-events b/target/ppc/trace-events index 7b3cfe11fd..3dc6740706 100644 --- a/target/ppc/trace-events +++ b/target/ppc/trace-events @@ -22,7 +22,7 @@ kvm_failed_put_vpa(void) "Warning: Unable to set VPA information to KVM" kvm_failed_get_vpa(void) "Warning: Unable to get VPA information from KVM" kvm_injected_interrupt(int irq) "injected interrupt %d" kvm_handle_dcr_write(void) "handle dcr write" -kvm_handle_drc_read(void) "handle dcr read" +kvm_handle_dcr_read(void) "handle dcr read" kvm_handle_halt(void) "handle halt" kvm_handle_papr_hcall(void) "handle PAPR hypercall" kvm_handle_epr(void) "handle epr" diff --git a/target/ppc/translate/vmx-impl.inc.c b/target/ppc/translate/vmx-impl.inc.c index 6861f4c5b9..663275b729 100644 --- a/target/ppc/translate/vmx-impl.inc.c +++ b/target/ppc/translate/vmx-impl.inc.c @@ -530,21 +530,21 @@ GEN_VXFORM(vmuleuw, 4, 10); GEN_VXFORM(vmulesb, 4, 12); GEN_VXFORM(vmulesh, 4, 13); GEN_VXFORM(vmulesw, 4, 14); -GEN_VXFORM(vslb, 2, 4); -GEN_VXFORM(vslh, 2, 5); -GEN_VXFORM(vslw, 2, 6); +GEN_VXFORM_V(vslb, MO_8, tcg_gen_gvec_shlv, 2, 4); +GEN_VXFORM_V(vslh, MO_16, tcg_gen_gvec_shlv, 2, 5); +GEN_VXFORM_V(vslw, MO_32, tcg_gen_gvec_shlv, 2, 6); GEN_VXFORM(vrlwnm, 2, 6); GEN_VXFORM_DUAL(vslw, PPC_ALTIVEC, PPC_NONE, \ vrlwnm, PPC_NONE, PPC2_ISA300) -GEN_VXFORM(vsld, 2, 23); -GEN_VXFORM(vsrb, 2, 8); -GEN_VXFORM(vsrh, 2, 9); -GEN_VXFORM(vsrw, 2, 10); -GEN_VXFORM(vsrd, 2, 27); -GEN_VXFORM(vsrab, 2, 12); -GEN_VXFORM(vsrah, 2, 13); -GEN_VXFORM(vsraw, 2, 14); -GEN_VXFORM(vsrad, 2, 15); +GEN_VXFORM_V(vsld, MO_64, tcg_gen_gvec_shlv, 2, 23); +GEN_VXFORM_V(vsrb, MO_8, tcg_gen_gvec_shrv, 2, 8); +GEN_VXFORM_V(vsrh, MO_16, tcg_gen_gvec_shrv, 2, 9); +GEN_VXFORM_V(vsrw, MO_32, tcg_gen_gvec_shrv, 2, 10); +GEN_VXFORM_V(vsrd, MO_64, tcg_gen_gvec_shrv, 2, 27); +GEN_VXFORM_V(vsrab, MO_8, tcg_gen_gvec_sarv, 2, 12); +GEN_VXFORM_V(vsrah, MO_16, tcg_gen_gvec_sarv, 2, 13); +GEN_VXFORM_V(vsraw, MO_32, tcg_gen_gvec_sarv, 2, 14); +GEN_VXFORM_V(vsrad, MO_64, tcg_gen_gvec_sarv, 2, 15); GEN_VXFORM(vsrv, 2, 28); GEN_VXFORM(vslv, 2, 29); GEN_VXFORM(vslo, 6, 16); diff --git a/target/ppc/translate/vsx-impl.inc.c b/target/ppc/translate/vsx-impl.inc.c index 11d9b75d01..199d22da97 100644 --- a/target/ppc/translate/vsx-impl.inc.c +++ b/target/ppc/translate/vsx-impl.inc.c @@ -227,7 +227,7 @@ static void gen_lxvb16x(DisasContext *ctx) tcg_temp_free_i64(xtl); } -#define VSX_VECTOR_LOAD_STORE(name, op, indexed) \ +#define VSX_VECTOR_LOAD(name, op, indexed) \ static void gen_##name(DisasContext *ctx) \ { \ int xt; \ @@ -254,8 +254,6 @@ static void gen_##name(DisasContext *ctx) \ } \ xth = tcg_temp_new_i64(); \ xtl = tcg_temp_new_i64(); \ - get_cpu_vsrh(xth, xt); \ - get_cpu_vsrl(xtl, xt); \ gen_set_access_type(ctx, ACCESS_INT); \ EA = tcg_temp_new(); \ if (indexed) { \ @@ -281,10 +279,61 @@ static void gen_##name(DisasContext *ctx) \ tcg_temp_free_i64(xtl); \ } -VSX_VECTOR_LOAD_STORE(lxv, ld_i64, 0) -VSX_VECTOR_LOAD_STORE(stxv, st_i64, 0) -VSX_VECTOR_LOAD_STORE(lxvx, ld_i64, 1) -VSX_VECTOR_LOAD_STORE(stxvx, st_i64, 1) +VSX_VECTOR_LOAD(lxv, ld_i64, 0) +VSX_VECTOR_LOAD(lxvx, ld_i64, 1) + +#define VSX_VECTOR_STORE(name, op, indexed) \ +static void gen_##name(DisasContext *ctx) \ +{ \ + int xt; \ + TCGv EA; \ + TCGv_i64 xth; \ + TCGv_i64 xtl; \ + \ + if (indexed) { \ + xt = xT(ctx->opcode); \ + } else { \ + xt = DQxT(ctx->opcode); \ + } \ + \ + if (xt < 32) { \ + if (unlikely(!ctx->vsx_enabled)) { \ + gen_exception(ctx, POWERPC_EXCP_VSXU); \ + return; \ + } \ + } else { \ + if (unlikely(!ctx->altivec_enabled)) { \ + gen_exception(ctx, POWERPC_EXCP_VPU); \ + return; \ + } \ + } \ + xth = tcg_temp_new_i64(); \ + xtl = tcg_temp_new_i64(); \ + get_cpu_vsrh(xth, xt); \ + get_cpu_vsrl(xtl, xt); \ + gen_set_access_type(ctx, ACCESS_INT); \ + EA = tcg_temp_new(); \ + if (indexed) { \ + gen_addr_reg_index(ctx, EA); \ + } else { \ + gen_addr_imm_index(ctx, EA, 0x0F); \ + } \ + if (ctx->le_mode) { \ + tcg_gen_qemu_##op(xtl, EA, ctx->mem_idx, MO_LEQ); \ + tcg_gen_addi_tl(EA, EA, 8); \ + tcg_gen_qemu_##op(xth, EA, ctx->mem_idx, MO_LEQ); \ + } else { \ + tcg_gen_qemu_##op(xth, EA, ctx->mem_idx, MO_BEQ); \ + tcg_gen_addi_tl(EA, EA, 8); \ + tcg_gen_qemu_##op(xtl, EA, ctx->mem_idx, MO_BEQ); \ + } \ + tcg_temp_free(EA); \ + tcg_temp_free_i64(xth); \ + tcg_temp_free_i64(xtl); \ +} + +VSX_VECTOR_STORE(stxv, st_i64, 0) +VSX_VECTOR_STORE(stxvx, st_i64, 1) #ifdef TARGET_PPC64 #define VSX_VECTOR_LOAD_STORE_LENGTH(name) \ @@ -329,7 +378,6 @@ static void gen_##name(DisasContext *ctx) \ return; \ } \ xth = tcg_temp_new_i64(); \ - get_cpu_vsrh(xth, rD(ctx->opcode) + 32); \ gen_set_access_type(ctx, ACCESS_INT); \ EA = tcg_temp_new(); \ gen_addr_imm_index(ctx, EA, 0x03); \ @@ -513,8 +561,8 @@ static void gen_##name(DisasContext *ctx) \ tcg_temp_free_i64(xth); \ } -VSX_LOAD_SCALAR_DS(stxsd, st64_i64) -VSX_LOAD_SCALAR_DS(stxssp, st32fs) +VSX_STORE_SCALAR_DS(stxsd, st64_i64) +VSX_STORE_SCALAR_DS(stxssp, st32fs) static void gen_mfvsrwz(DisasContext *ctx) { @@ -858,8 +906,8 @@ static void glue(gen_, name)(DisasContext *ctx) \ xbh = tcg_temp_new_i64(); \ xbl = tcg_temp_new_i64(); \ sgm = tcg_temp_new_i64(); \ - set_cpu_vsrh(xB(ctx->opcode), xbh); \ - set_cpu_vsrl(xB(ctx->opcode), xbl); \ + get_cpu_vsrh(xbh, xB(ctx->opcode)); \ + get_cpu_vsrl(xbl, xB(ctx->opcode)); \ tcg_gen_movi_i64(sgm, sgn_mask); \ switch (op) { \ case OP_ABS: { \ @@ -1192,7 +1240,7 @@ static void gen_xxbrq(DisasContext *ctx) tcg_gen_bswap64_i64(xtl, xbh); set_cpu_vsrl(xT(ctx->opcode), xtl); tcg_gen_mov_i64(xth, t0); - set_cpu_vsrl(xT(ctx->opcode), xth); + set_cpu_vsrh(xT(ctx->opcode), xth); tcg_temp_free_i64(t0); tcg_temp_free_i64(xth); @@ -1220,7 +1268,7 @@ static void gen_xxbrw(DisasContext *ctx) get_cpu_vsrl(xbl, xB(ctx->opcode)); gen_bswap32x4(xth, xtl, xbh, xbl); - set_cpu_vsrl(xT(ctx->opcode), xth); + set_cpu_vsrh(xT(ctx->opcode), xth); set_cpu_vsrl(xT(ctx->opcode), xtl); tcg_temp_free_i64(xth); @@ -1355,13 +1403,13 @@ static void gen_xxspltib(DisasContext *ctx) int rt = xT(ctx->opcode); if (rt < 32) { - if (unlikely(!ctx->altivec_enabled)) { - gen_exception(ctx, POWERPC_EXCP_VPU); + if (unlikely(!ctx->vsx_enabled)) { + gen_exception(ctx, POWERPC_EXCP_VSXU); return; } } else { - if (unlikely(!ctx->vsx_enabled)) { - gen_exception(ctx, POWERPC_EXCP_VSXU); + if (unlikely(!ctx->altivec_enabled)) { + gen_exception(ctx, POWERPC_EXCP_VPU); return; } } @@ -1820,7 +1868,7 @@ static void gen_xvxsigdp(DisasContext *ctx) tcg_gen_movi_i64(t0, 0x0010000000000000); tcg_gen_movcond_i64(TCG_COND_EQ, t0, exp, zr, zr, t0); tcg_gen_movcond_i64(TCG_COND_EQ, t0, exp, nan, zr, t0); - tcg_gen_deposit_i64(xth, t0, xbl, 0, 52); + tcg_gen_deposit_i64(xtl, t0, xbl, 0, 52); set_cpu_vsrl(xT(ctx->opcode), xtl); tcg_temp_free_i64(t0); diff --git a/target/riscv/Makefile.objs b/target/riscv/Makefile.objs index 9c6c109327..b1c79bc1d1 100644 --- a/target/riscv/Makefile.objs +++ b/target/riscv/Makefile.objs @@ -5,16 +5,19 @@ DECODETREE = $(SRC_PATH)/scripts/decodetree.py decode32-y = $(SRC_PATH)/target/riscv/insn32.decode decode32-$(TARGET_RISCV64) += $(SRC_PATH)/target/riscv/insn32-64.decode +decode16-y = $(SRC_PATH)/target/riscv/insn16.decode +decode16-$(TARGET_RISCV32) += $(SRC_PATH)/target/riscv/insn16-32.decode +decode16-$(TARGET_RISCV64) += $(SRC_PATH)/target/riscv/insn16-64.decode + target/riscv/decode_insn32.inc.c: $(decode32-y) $(DECODETREE) $(call quiet-command, \ - $(PYTHON) $(DECODETREE) -o $@ --decode decode_insn32 $(decode32-y), \ - "GEN", $(TARGET_DIR)$@) + $(PYTHON) $(DECODETREE) -o $@ --static-decode decode_insn32 \ + $(decode32-y), "GEN", $(TARGET_DIR)$@) -target/riscv/decode_insn16.inc.c: \ - $(SRC_PATH)/target/riscv/insn16.decode $(DECODETREE) +target/riscv/decode_insn16.inc.c: $(decode16-y) $(DECODETREE) $(call quiet-command, \ - $(PYTHON) $(DECODETREE) -o $@ --decode decode_insn16 --insnwidth 16 $<, \ - "GEN", $(TARGET_DIR)$@) + $(PYTHON) $(DECODETREE) -o $@ --static-decode decode_insn16 \ + --insnwidth 16 $(decode16-y), "GEN", $(TARGET_DIR)$@) target/riscv/translate.o: target/riscv/decode_insn32.inc.c \ target/riscv/decode_insn16.inc.c diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c index b7675707e0..e29879915f 100644 --- a/target/riscv/cpu.c +++ b/target/riscv/cpu.c @@ -23,6 +23,7 @@ #include "cpu.h" #include "exec/exec-all.h" #include "qapi/error.h" +#include "hw/qdev-properties.h" #include "migration/vmstate.h" /* RISC-V CPU definitions */ @@ -30,17 +31,17 @@ static const char riscv_exts[26] = "IEMAFDQCLBJTPVNSUHKORWXYZG"; const char * const riscv_int_regnames[] = { - "zero", "ra ", "sp ", "gp ", "tp ", "t0 ", "t1 ", "t2 ", - "s0 ", "s1 ", "a0 ", "a1 ", "a2 ", "a3 ", "a4 ", "a5 ", - "a6 ", "a7 ", "s2 ", "s3 ", "s4 ", "s5 ", "s6 ", "s7 ", - "s8 ", "s9 ", "s10 ", "s11 ", "t3 ", "t4 ", "t5 ", "t6 " + "zero", "ra", "sp", "gp", "tp", "t0", "t1", "t2", + "s0", "s1", "a0", "a1", "a2", "a3", "a4", "a5", + "a6", "a7", "s2", "s3", "s4", "s5", "s6", "s7", + "s8", "s9", "s10", "s11", "t3", "t4", "t5", "t6" }; const char * const riscv_fpr_regnames[] = { - "ft0 ", "ft1 ", "ft2 ", "ft3 ", "ft4 ", "ft5 ", "ft6 ", "ft7 ", - "fs0 ", "fs1 ", "fa0 ", "fa1 ", "fa2 ", "fa3 ", "fa4 ", "fa5 ", - "fa6 ", "fa7 ", "fs2 ", "fs3 ", "fs4 ", "fs5 ", "fs6 ", "fs7 ", - "fs8 ", "fs9 ", "fs10", "fs11", "ft8 ", "ft9 ", "ft10", "ft11" + "ft0", "ft1", "ft2", "ft3", "ft4", "ft5", "ft6", "ft7", + "fs0", "fs1", "fa0", "fa1", "fa2", "fa3", "fa4", "fa5", + "fa6", "fa7", "fs2", "fs3", "fs4", "fs5", "fs6", "fs7", + "fs8", "fs9", "fs10", "fs11", "ft8", "ft9", "ft10", "ft11" }; const char * const riscv_excp_names[] = { @@ -114,6 +115,12 @@ static void riscv_any_cpu_init(Object *obj) #if defined(TARGET_RISCV32) +static void riscv_base32_cpu_init(Object *obj) +{ + CPURISCVState *env = &RISCV_CPU(obj)->env; + set_misa(env, RV32 | RVI | RVM | RVA | RVF | RVD | RVC | RVS | RVU); +} + static void rv32gcsu_priv1_09_1_cpu_init(Object *obj) { CPURISCVState *env = &RISCV_CPU(obj)->env; @@ -145,6 +152,12 @@ static void rv32imacu_nommu_cpu_init(Object *obj) #elif defined(TARGET_RISCV64) +static void riscv_base64_cpu_init(Object *obj) +{ + CPURISCVState *env = &RISCV_CPU(obj)->env; + set_misa(env, RV64 | RVI | RVM | RVA | RVF | RVD | RVC | RVS | RVU); +} + static void rv64gcsu_priv1_09_1_cpu_init(Object *obj) { CPURISCVState *env = &RISCV_CPU(obj)->env; @@ -296,7 +309,11 @@ static void riscv_cpu_disas_set_info(CPUState *s, disassemble_info *info) static void riscv_cpu_realize(DeviceState *dev, Error **errp) { CPUState *cs = CPU(dev); + RISCVCPU *cpu = RISCV_CPU(dev); + CPURISCVState *env = &cpu->env; RISCVCPUClass *mcc = RISCV_CPU_GET_CLASS(dev); + int priv_version = PRIV_VERSION_1_10_0; + int user_version = USER_VERSION_2_02_0; Error *local_err = NULL; cpu_exec_realizefn(cs, &local_err); @@ -305,6 +322,41 @@ static void riscv_cpu_realize(DeviceState *dev, Error **errp) return; } + if (cpu->cfg.priv_spec) { + if (!g_strcmp0(cpu->cfg.priv_spec, "v1.10.0")) { + priv_version = PRIV_VERSION_1_10_0; + } else if (!g_strcmp0(cpu->cfg.priv_spec, "v1.9.1")) { + priv_version = PRIV_VERSION_1_09_1; + } else { + error_setg(errp, + "Unsupported privilege spec version '%s'", + cpu->cfg.priv_spec); + return; + } + } + + if (cpu->cfg.user_spec) { + if (!g_strcmp0(cpu->cfg.user_spec, "v2.02.0")) { + user_version = USER_VERSION_2_02_0; + } else { + error_setg(errp, + "Unsupported user spec version '%s'", + cpu->cfg.user_spec); + return; + } + } + + set_versions(env, user_version, priv_version); + set_resetvec(env, DEFAULT_RSTVEC); + + if (cpu->cfg.mmu) { + set_feature(env, RISCV_FEATURE_MMU); + } + + if (cpu->cfg.pmp) { + set_feature(env, RISCV_FEATURE_PMP); + } + riscv_cpu_register_gdb_regs_for_features(cs); qemu_init_vcpu(cs); @@ -326,6 +378,14 @@ static const VMStateDescription vmstate_riscv_cpu = { .unmigratable = 1, }; +static Property riscv_cpu_properties[] = { + DEFINE_PROP_STRING("priv_spec", RISCVCPU, cfg.priv_spec), + DEFINE_PROP_STRING("user_spec", RISCVCPU, cfg.user_spec), + DEFINE_PROP_BOOL("mmu", RISCVCPU, cfg.mmu, true), + DEFINE_PROP_BOOL("pmp", RISCVCPU, cfg.pmp, true), + DEFINE_PROP_END_OF_LIST(), +}; + static void riscv_cpu_class_init(ObjectClass *c, void *data) { RISCVCPUClass *mcc = RISCV_CPU_CLASS(c); @@ -365,6 +425,7 @@ static void riscv_cpu_class_init(ObjectClass *c, void *data) #endif /* For now, mark unmigratable: */ cc->vmsd = &vmstate_riscv_cpu; + dc->props = riscv_cpu_properties; } char *riscv_isa_string(RISCVCPU *cpu) @@ -430,12 +491,14 @@ static const TypeInfo riscv_cpu_type_infos[] = { }, DEFINE_CPU(TYPE_RISCV_CPU_ANY, riscv_any_cpu_init), #if defined(TARGET_RISCV32) + DEFINE_CPU(TYPE_RISCV_CPU_BASE32, riscv_base32_cpu_init), DEFINE_CPU(TYPE_RISCV_CPU_RV32GCSU_V1_09_1, rv32gcsu_priv1_09_1_cpu_init), DEFINE_CPU(TYPE_RISCV_CPU_RV32GCSU_V1_10_0, rv32gcsu_priv1_10_0_cpu_init), DEFINE_CPU(TYPE_RISCV_CPU_RV32IMACU_NOMMU, rv32imacu_nommu_cpu_init), DEFINE_CPU(TYPE_RISCV_CPU_SIFIVE_E31, rv32imacu_nommu_cpu_init), DEFINE_CPU(TYPE_RISCV_CPU_SIFIVE_U34, rv32gcsu_priv1_10_0_cpu_init) #elif defined(TARGET_RISCV64) + DEFINE_CPU(TYPE_RISCV_CPU_BASE64, riscv_base64_cpu_init), DEFINE_CPU(TYPE_RISCV_CPU_RV64GCSU_V1_09_1, rv64gcsu_priv1_09_1_cpu_init), DEFINE_CPU(TYPE_RISCV_CPU_RV64GCSU_V1_10_0, rv64gcsu_priv1_10_0_cpu_init), DEFINE_CPU(TYPE_RISCV_CPU_RV64IMACU_NOMMU, rv64imacu_nommu_cpu_init), diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h index c17184f4e4..74e726c1c9 100644 --- a/target/riscv/cpu.h +++ b/target/riscv/cpu.h @@ -48,6 +48,8 @@ #define CPU_RESOLVING_TYPE TYPE_RISCV_CPU #define TYPE_RISCV_CPU_ANY RISCV_CPU_TYPE_NAME("any") +#define TYPE_RISCV_CPU_BASE32 RISCV_CPU_TYPE_NAME("rv32") +#define TYPE_RISCV_CPU_BASE64 RISCV_CPU_TYPE_NAME("rv64") #define TYPE_RISCV_CPU_RV32GCSU_V1_09_1 RISCV_CPU_TYPE_NAME("rv32gcsu-v1.9.1") #define TYPE_RISCV_CPU_RV32GCSU_V1_10_0 RISCV_CPU_TYPE_NAME("rv32gcsu-v1.10.0") #define TYPE_RISCV_CPU_RV32IMACU_NOMMU RISCV_CPU_TYPE_NAME("rv32imacu-nommu") @@ -224,6 +226,14 @@ typedef struct RISCVCPU { CPUState parent_obj; /*< public >*/ CPURISCVState env; + + /* Configuration Settings */ + struct { + char *priv_spec; + char *user_spec; + bool mmu; + bool pmp; + } cfg; } RISCVCPU; static inline RISCVCPU *riscv_env_get_cpu(CPURISCVState *env) diff --git a/target/riscv/cpu_bits.h b/target/riscv/cpu_bits.h index 7180fccf54..dc9d53d4be 100644 --- a/target/riscv/cpu_bits.h +++ b/target/riscv/cpu_bits.h @@ -202,6 +202,23 @@ #define CSR_DPC 0x7b1 #define CSR_DSCRATCH 0x7b2 +/* Hpervisor CSRs */ +#define CSR_HSTATUS 0xa00 +#define CSR_HEDELEG 0xa02 +#define CSR_HIDELEG 0xa03 +#define CSR_HGATP 0xa80 + +#if defined(TARGET_RISCV32) +#define HGATP_MODE SATP32_MODE +#define HGATP_ASID SATP32_ASID +#define HGATP_PPN SATP32_PPN +#endif +#if defined(TARGET_RISCV64) +#define HGATP_MODE SATP64_MODE +#define HGATP_ASID SATP64_ASID +#define HGATP_PPN SATP64_PPN +#endif + /* Performance Counters */ #define CSR_MHPMCOUNTER3 0xb03 #define CSR_MHPMCOUNTER4 0xb04 @@ -292,9 +309,6 @@ #define CSR_MHPMCOUNTER31H 0xb9f /* Legacy Hypervisor Trap Setup (priv v1.9.1) */ -#define CSR_HSTATUS 0x200 -#define CSR_HEDELEG 0x202 -#define CSR_HIDELEG 0x203 #define CSR_HIE 0x204 #define CSR_HTVEC 0x205 @@ -316,14 +330,11 @@ /* mstatus CSR bits */ #define MSTATUS_UIE 0x00000001 #define MSTATUS_SIE 0x00000002 -#define MSTATUS_HIE 0x00000004 #define MSTATUS_MIE 0x00000008 #define MSTATUS_UPIE 0x00000010 #define MSTATUS_SPIE 0x00000020 -#define MSTATUS_HPIE 0x00000040 #define MSTATUS_MPIE 0x00000080 #define MSTATUS_SPP 0x00000100 -#define MSTATUS_HPP 0x00000600 #define MSTATUS_MPP 0x00001800 #define MSTATUS_FS 0x00006000 #define MSTATUS_XS 0x00018000 @@ -335,6 +346,8 @@ #define MSTATUS_TVM 0x00100000 /* since: priv-1.10 */ #define MSTATUS_TW 0x20000000 /* since: priv-1.10 */ #define MSTATUS_TSR 0x40000000 /* since: priv-1.10 */ +#define MSTATUS_MTL 0x4000000000ULL +#define MSTATUS_MPV 0x8000000000ULL #define MSTATUS64_UXL 0x0000000300000000ULL #define MSTATUS64_SXL 0x0000000C00000000ULL @@ -380,10 +393,28 @@ #define SSTATUS_SD SSTATUS64_SD #endif +/* hstatus CSR bits */ +#define HSTATUS_SPRV 0x00000001 +#define HSTATUS_STL 0x00000040 +#define HSTATUS_SPV 0x00000080 +#define HSTATUS_SP2P 0x00000100 +#define HSTATUS_SP2V 0x00000200 +#define HSTATUS_VTVM 0x00100000 +#define HSTATUS_VTSR 0x00400000 + +#define HSTATUS32_WPRI 0xFF8FF87E +#define HSTATUS64_WPRI 0xFFFFFFFFFF8FF87EULL + +#if defined(TARGET_RISCV32) +#define HSTATUS_WPRI HSTATUS32_WPRI +#elif defined(TARGET_RISCV64) +#define HSTATUS_WPRI HSTATUS64_WPRI +#endif + /* Privilege modes */ #define PRV_U 0 #define PRV_S 1 -#define PRV_H 2 +#define PRV_H 2 /* Reserved */ #define PRV_M 3 /* RV32 satp CSR field masks */ diff --git a/target/riscv/cpu_helper.c b/target/riscv/cpu_helper.c index 41d6db41c3..c577a262b8 100644 --- a/target/riscv/cpu_helper.c +++ b/target/riscv/cpu_helper.c @@ -82,10 +82,31 @@ int riscv_cpu_claim_interrupts(RISCVCPU *cpu, uint32_t interrupts) } } -/* iothread_mutex must be held */ +struct CpuAsyncInfo { + uint32_t new_mip; +}; + +static void riscv_cpu_update_mip_irqs_async(CPUState *target_cpu_state, + run_on_cpu_data data) +{ + CPURISCVState *env = &RISCV_CPU(target_cpu_state)->env; + RISCVCPU *cpu = riscv_env_get_cpu(env); + struct CpuAsyncInfo *info = (struct CpuAsyncInfo *) data.host_ptr; + + if (info->new_mip) { + cpu_interrupt(CPU(cpu), CPU_INTERRUPT_HARD); + } else { + cpu_reset_interrupt(CPU(cpu), CPU_INTERRUPT_HARD); + } + + g_free(info); +} + uint32_t riscv_cpu_update_mip(RISCVCPU *cpu, uint32_t mask, uint32_t value) { CPURISCVState *env = &cpu->env; + CPUState *cs = CPU(cpu); + struct CpuAsyncInfo *info; uint32_t old, new, cmp = atomic_read(&env->mip); do { @@ -94,11 +115,11 @@ uint32_t riscv_cpu_update_mip(RISCVCPU *cpu, uint32_t mask, uint32_t value) cmp = atomic_cmpxchg(&env->mip, old, new); } while (old != cmp); - if (new) { - cpu_interrupt(CPU(cpu), CPU_INTERRUPT_HARD); - } else { - cpu_reset_interrupt(CPU(cpu), CPU_INTERRUPT_HARD); - } + info = g_new(struct CpuAsyncInfo, 1); + info->new_mip = new; + + async_run_on_cpu(cs, riscv_cpu_update_mip_irqs_async, + RUN_ON_CPU_HOST_PTR(info)); return old; } @@ -494,7 +515,7 @@ void riscv_cpu_do_interrupt(CPUState *cs) s = set_field(s, MSTATUS_SPP, env->priv); s = set_field(s, MSTATUS_SIE, 0); env->mstatus = s; - env->scause = cause | ~(((target_ulong)-1) >> async); + env->scause = cause | ((target_ulong)async << (TARGET_LONG_BITS - 1)); env->sepc = env->pc; env->sbadaddr = tval; env->pc = (env->stvec >> 2 << 2) + diff --git a/target/riscv/csr.c b/target/riscv/csr.c index e1d91b6c60..f9e2910643 100644 --- a/target/riscv/csr.c +++ b/target/riscv/csr.c @@ -237,6 +237,7 @@ static const target_ulong sstatus_v1_9_mask = SSTATUS_SIE | SSTATUS_SPIE | static const target_ulong sstatus_v1_10_mask = SSTATUS_SIE | SSTATUS_SPIE | SSTATUS_UIE | SSTATUS_UPIE | SSTATUS_SPP | SSTATUS_FS | SSTATUS_XS | SSTATUS_SUM | SSTATUS_MXR | SSTATUS_SD; +static const target_ulong sip_writable_mask = SIP_SSIP | MIP_USIP | MIP_UEIP; #if defined(TARGET_RISCV32) static const char valid_vm_1_09[16] = { @@ -290,7 +291,6 @@ static int write_mstatus(CPURISCVState *env, int csrno, target_ulong val) { target_ulong mstatus = env->mstatus; target_ulong mask = 0; - target_ulong mpp = get_field(val, MSTATUS_MPP); /* flush tlb on mstatus fields that affect VM */ if (env->priv_ver <= PRIV_VERSION_1_09_1) { @@ -305,7 +305,7 @@ static int write_mstatus(CPURISCVState *env, int csrno, target_ulong val) MSTATUS_VM : 0); } if (env->priv_ver >= PRIV_VERSION_1_10_0) { - if ((val ^ mstatus) & (MSTATUS_MXR | MSTATUS_MPP | + if ((val ^ mstatus) & (MSTATUS_MXR | MSTATUS_MPP | MSTATUS_MPV | MSTATUS_MPRV | MSTATUS_SUM)) { tlb_flush(CPU(riscv_env_get_cpu(env))); } @@ -313,13 +313,13 @@ static int write_mstatus(CPURISCVState *env, int csrno, target_ulong val) MSTATUS_SPP | MSTATUS_FS | MSTATUS_MPRV | MSTATUS_SUM | MSTATUS_MPP | MSTATUS_MXR | MSTATUS_TVM | MSTATUS_TSR | MSTATUS_TW; - } - - /* silenty discard mstatus.mpp writes for unsupported modes */ - if (mpp == PRV_H || - (!riscv_has_ext(env, RVS) && mpp == PRV_S) || - (!riscv_has_ext(env, RVU) && mpp == PRV_U)) { - mask &= ~MSTATUS_MPP; +#if defined(TARGET_RISCV64) + /* + * RV32: MPV and MTL are not in mstatus. The current plan is to + * add them to mstatush. For now, we just don't support it. + */ + mask |= MSTATUS_MPP | MSTATUS_MPV; +#endif } mstatus = (mstatus & ~mask) | (val & mask); @@ -555,9 +555,7 @@ static int rmw_mip(CPURISCVState *env, int csrno, target_ulong *ret_value, uint32_t old_mip; if (mask) { - qemu_mutex_lock_iothread(); old_mip = riscv_cpu_update_mip(cpu, mask, (new_value & mask)); - qemu_mutex_unlock_iothread(); } else { old_mip = atomic_read(&env->mip); } @@ -685,8 +683,10 @@ static int write_sbadaddr(CPURISCVState *env, int csrno, target_ulong val) static int rmw_sip(CPURISCVState *env, int csrno, target_ulong *ret_value, target_ulong new_value, target_ulong write_mask) { - return rmw_mip(env, CSR_MSTATUS, ret_value, new_value, - write_mask & env->mideleg); + int ret = rmw_mip(env, CSR_MSTATUS, ret_value, new_value, + write_mask & env->mideleg & sip_writable_mask); + *ret_value &= env->mideleg; + return ret; } /* Supervisor Protection and Translation */ @@ -723,7 +723,9 @@ static int write_satp(CPURISCVState *env, int csrno, target_ulong val) if (env->priv == PRV_S && get_field(env->mstatus, MSTATUS_TVM)) { return -1; } else { - tlb_flush(CPU(riscv_env_get_cpu(env))); + if((val ^ env->satp) & SATP_ASID) { + tlb_flush(CPU(riscv_env_get_cpu(env))); + } env->satp = val; } } diff --git a/target/riscv/insn16-32.decode b/target/riscv/insn16-32.decode new file mode 100644 index 0000000000..0819b17028 --- /dev/null +++ b/target/riscv/insn16-32.decode @@ -0,0 +1,28 @@ +# +# RISC-V translation routines for the RVXI Base Integer Instruction Set. +# +# Copyright (c) 2018 Peer Adelt, peer.adelt@hni.uni-paderborn.de +# Bastian Koppelmann, kbastian@mail.uni-paderborn.de +# +# This program is free software; you can redistribute it and/or modify it +# under the terms and conditions of the GNU General Public License, +# version 2 or later, as published by the Free Software Foundation. +# +# This program is distributed in the hope 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, see <http://www.gnu.org/licenses/>. + +# *** RV32C Standard Extension (Quadrant 0) *** +flw 011 ... ... .. ... 00 @cl_w +fsw 111 ... ... .. ... 00 @cs_w + +# *** RV32C Standard Extension (Quadrant 1) *** +jal 001 ........... 01 @cj rd=1 # C.JAL + +# *** RV32C Standard Extension (Quadrant 2) *** +flw 011 . ..... ..... 10 @c_lwsp +fsw 111 . ..... ..... 10 @c_swsp diff --git a/target/riscv/insn16-64.decode b/target/riscv/insn16-64.decode new file mode 100644 index 0000000000..672e1e916f --- /dev/null +++ b/target/riscv/insn16-64.decode @@ -0,0 +1,36 @@ +# +# RISC-V translation routines for the RVXI Base Integer Instruction Set. +# +# Copyright (c) 2018 Peer Adelt, peer.adelt@hni.uni-paderborn.de +# Bastian Koppelmann, kbastian@mail.uni-paderborn.de +# +# This program is free software; you can redistribute it and/or modify it +# under the terms and conditions of the GNU General Public License, +# version 2 or later, as published by the Free Software Foundation. +# +# This program is distributed in the hope 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, see <http://www.gnu.org/licenses/>. + +# *** RV64C Standard Extension (Quadrant 0) *** +ld 011 ... ... .. ... 00 @cl_d +sd 111 ... ... .. ... 00 @cs_d + +# *** RV64C Standard Extension (Quadrant 1) *** +{ + illegal 001 - 00000 ----- 01 # c.addiw, RES rd=0 + addiw 001 . ..... ..... 01 @ci +} +subw 100 1 11 ... 00 ... 01 @cs_2 +addw 100 1 11 ... 01 ... 01 @cs_2 + +# *** RV64C Standard Extension (Quadrant 2) *** +{ + illegal 011 - 00000 ----- 10 # c.ldsp, RES rd=0 + ld 011 . ..... ..... 10 @c_ldsp +} +sd 111 . ..... ..... 10 @c_sdsp diff --git a/target/riscv/insn16.decode b/target/riscv/insn16.decode index 17cc52cf2a..1cb93876fe 100644 --- a/target/riscv/insn16.decode +++ b/target/riscv/insn16.decode @@ -30,7 +30,7 @@ %imm_cb 12:s1 5:2 2:1 10:2 3:2 !function=ex_shift_1 %imm_cj 12:s1 8:1 9:2 6:1 7:1 2:1 11:1 3:3 !function=ex_shift_1 -%nzuimm_6bit 12:1 2:5 +%shimm_6bit 12:1 2:5 !function=ex_rvc_shifti %uimm_6bit_ld 2:3 12:1 5:2 !function=ex_shift_3 %uimm_6bit_lw 2:2 12:1 4:3 !function=ex_shift_2 %uimm_6bit_sd 7:3 10:3 !function=ex_shift_3 @@ -40,90 +40,93 @@ %imm_lui 12:s1 2:5 !function=ex_shift_12 +# Argument sets imported from insn32.decode: +&empty !extern +&r rd rs1 rs2 !extern +&i imm rs1 rd !extern +&s imm rs1 rs2 !extern +&j imm rd !extern +&b imm rs2 rs1 !extern +&u imm rd !extern +&shift shamt rs1 rd !extern -# Argument sets: -&cl rs1 rd -&cl_dw uimm rs1 rd -&ci imm rd -&ciw nzuimm rd -&cs rs1 rs2 -&cs_dw uimm rs1 rs2 -&cb imm rs1 -&cr rd rs2 -&cj imm -&c_shift shamt rd - -&c_ld uimm rd -&c_sd uimm rs2 - -&caddi16sp_lui imm_lui imm_addi16sp rd -&cflwsp_ldsp uimm_flwsp uimm_ldsp rd -&cfswsp_sdsp uimm_fswsp uimm_sdsp rs2 # Formats 16: -@cr .... ..... ..... .. &cr rs2=%rs2_5 %rd -@ci ... . ..... ..... .. &ci imm=%imm_ci %rd -@ciw ... ........ ... .. &ciw nzuimm=%nzuimm_ciw rd=%rs2_3 -@cl_d ... ... ... .. ... .. &cl_dw uimm=%uimm_cl_d rs1=%rs1_3 rd=%rs2_3 -@cl_w ... ... ... .. ... .. &cl_dw uimm=%uimm_cl_w rs1=%rs1_3 rd=%rs2_3 -@cl ... ... ... .. ... .. &cl rs1=%rs1_3 rd=%rs2_3 -@cs ... ... ... .. ... .. &cs rs1=%rs1_3 rs2=%rs2_3 -@cs_2 ... ... ... .. ... .. &cr rd=%rs1_3 rs2=%rs2_3 -@cs_d ... ... ... .. ... .. &cs_dw uimm=%uimm_cl_d rs1=%rs1_3 rs2=%rs2_3 -@cs_w ... ... ... .. ... .. &cs_dw uimm=%uimm_cl_w rs1=%rs1_3 rs2=%rs2_3 -@cb ... ... ... .. ... .. &cb imm=%imm_cb rs1=%rs1_3 -@cj ... ........... .. &cj imm=%imm_cj - -@c_ld ... . ..... ..... .. &c_ld uimm=%uimm_6bit_ld %rd -@c_lw ... . ..... ..... .. &c_ld uimm=%uimm_6bit_lw %rd -@c_sd ... . ..... ..... .. &c_sd uimm=%uimm_6bit_sd rs2=%rs2_5 -@c_sw ... . ..... ..... .. &c_sd uimm=%uimm_6bit_sw rs2=%rs2_5 - -@c_addi16sp_lui ... . ..... ..... .. &caddi16sp_lui %imm_lui %imm_addi16sp %rd -@c_flwsp_ldsp ... . ..... ..... .. &cflwsp_ldsp uimm_flwsp=%uimm_6bit_lw \ - uimm_ldsp=%uimm_6bit_ld %rd -@c_fswsp_sdsp ... . ..... ..... .. &cfswsp_sdsp uimm_fswsp=%uimm_6bit_sw \ - uimm_sdsp=%uimm_6bit_sd rs2=%rs2_5 - -@c_shift ... . .. ... ..... .. &c_shift rd=%rs1_3 shamt=%nzuimm_6bit -@c_shift2 ... . .. ... ..... .. &c_shift rd=%rd shamt=%nzuimm_6bit - -@c_andi ... . .. ... ..... .. &ci imm=%imm_ci rd=%rs1_3 - -# *** RV64C Standard Extension (Quadrant 0) *** -c_addi4spn 000 ........ ... 00 @ciw -c_fld 001 ... ... .. ... 00 @cl_d -c_lw 010 ... ... .. ... 00 @cl_w -c_flw_ld 011 --- ... -- ... 00 @cl #Note: Must parse uimm manually -c_fsd 101 ... ... .. ... 00 @cs_d -c_sw 110 ... ... .. ... 00 @cs_w -c_fsw_sd 111 --- ... -- ... 00 @cs #Note: Must parse uimm manually - -# *** RV64C Standard Extension (Quadrant 1) *** -c_addi 000 . ..... ..... 01 @ci -c_jal_addiw 001 . ..... ..... 01 @ci #Note: parse rd and/or imm manually -c_li 010 . ..... ..... 01 @ci -c_addi16sp_lui 011 . ..... ..... 01 @c_addi16sp_lui # shares opc with C.LUI -c_srli 100 . 00 ... ..... 01 @c_shift -c_srai 100 . 01 ... ..... 01 @c_shift -c_andi 100 . 10 ... ..... 01 @c_andi -c_sub 100 0 11 ... 00 ... 01 @cs_2 -c_xor 100 0 11 ... 01 ... 01 @cs_2 -c_or 100 0 11 ... 10 ... 01 @cs_2 -c_and 100 0 11 ... 11 ... 01 @cs_2 -c_subw 100 1 11 ... 00 ... 01 @cs_2 -c_addw 100 1 11 ... 01 ... 01 @cs_2 -c_j 101 ........... 01 @cj -c_beqz 110 ... ... ..... 01 @cb -c_bnez 111 ... ... ..... 01 @cb - -# *** RV64C Standard Extension (Quadrant 2) *** -c_slli 000 . ..... ..... 10 @c_shift2 -c_fldsp 001 . ..... ..... 10 @c_ld -c_lwsp 010 . ..... ..... 10 @c_lw -c_flwsp_ldsp 011 . ..... ..... 10 @c_flwsp_ldsp #C.LDSP:RV64;C.FLWSP:RV32 -c_jr_mv 100 0 ..... ..... 10 @cr -c_ebreak_jalr_add 100 1 ..... ..... 10 @cr -c_fsdsp 101 ...... ..... 10 @c_sd -c_swsp 110 . ..... ..... 10 @c_sw -c_fswsp_sdsp 111 . ..... ..... 10 @c_fswsp_sdsp #C.SDSP:RV64;C.FSWSP:RV32 +@cr .... ..... ..... .. &r rs2=%rs2_5 rs1=%rd %rd +@ci ... . ..... ..... .. &i imm=%imm_ci rs1=%rd %rd +@cl_d ... ... ... .. ... .. &i imm=%uimm_cl_d rs1=%rs1_3 rd=%rs2_3 +@cl_w ... ... ... .. ... .. &i imm=%uimm_cl_w rs1=%rs1_3 rd=%rs2_3 +@cs_2 ... ... ... .. ... .. &r rs2=%rs2_3 rs1=%rs1_3 rd=%rs1_3 +@cs_d ... ... ... .. ... .. &s imm=%uimm_cl_d rs1=%rs1_3 rs2=%rs2_3 +@cs_w ... ... ... .. ... .. &s imm=%uimm_cl_w rs1=%rs1_3 rs2=%rs2_3 +@cj ... ........... .. &j imm=%imm_cj +@cb_z ... ... ... .. ... .. &b imm=%imm_cb rs1=%rs1_3 rs2=0 + +@c_ldsp ... . ..... ..... .. &i imm=%uimm_6bit_ld rs1=2 %rd +@c_lwsp ... . ..... ..... .. &i imm=%uimm_6bit_lw rs1=2 %rd +@c_sdsp ... . ..... ..... .. &s imm=%uimm_6bit_sd rs1=2 rs2=%rs2_5 +@c_swsp ... . ..... ..... .. &s imm=%uimm_6bit_sw rs1=2 rs2=%rs2_5 +@c_li ... . ..... ..... .. &i imm=%imm_ci rs1=0 %rd +@c_lui ... . ..... ..... .. &u imm=%imm_lui %rd +@c_jalr ... . ..... ..... .. &i imm=0 rs1=%rd +@c_mv ... . ..... ..... .. &i imm=0 rs1=%rs2_5 %rd + +@c_addi4spn ... . ..... ..... .. &i imm=%nzuimm_ciw rs1=2 rd=%rs2_3 +@c_addi16sp ... . ..... ..... .. &i imm=%imm_addi16sp rs1=2 rd=2 + +@c_shift ... . .. ... ..... .. \ + &shift rd=%rs1_3 rs1=%rs1_3 shamt=%shimm_6bit +@c_shift2 ... . .. ... ..... .. \ + &shift rd=%rd rs1=%rd shamt=%shimm_6bit + +@c_andi ... . .. ... ..... .. &i imm=%imm_ci rs1=%rs1_3 rd=%rs1_3 + +# *** RV32/64C Standard Extension (Quadrant 0) *** +{ + # Opcode of all zeros is illegal; rd != 0, nzuimm == 0 is reserved. + illegal 000 000 000 00 --- 00 + addi 000 ... ... .. ... 00 @c_addi4spn +} +fld 001 ... ... .. ... 00 @cl_d +lw 010 ... ... .. ... 00 @cl_w +fsd 101 ... ... .. ... 00 @cs_d +sw 110 ... ... .. ... 00 @cs_w + +# *** RV32/64C Standard Extension (Quadrant 1) *** +addi 000 . ..... ..... 01 @ci +addi 010 . ..... ..... 01 @c_li +{ + illegal 011 0 ----- 00000 01 # c.addi16sp and c.lui, RES nzimm=0 + addi 011 . 00010 ..... 01 @c_addi16sp + lui 011 . ..... ..... 01 @c_lui +} +srli 100 . 00 ... ..... 01 @c_shift +srai 100 . 01 ... ..... 01 @c_shift +andi 100 . 10 ... ..... 01 @c_andi +sub 100 0 11 ... 00 ... 01 @cs_2 +xor 100 0 11 ... 01 ... 01 @cs_2 +or 100 0 11 ... 10 ... 01 @cs_2 +and 100 0 11 ... 11 ... 01 @cs_2 +jal 101 ........... 01 @cj rd=0 # C.J +beq 110 ... ... ..... 01 @cb_z +bne 111 ... ... ..... 01 @cb_z + +# *** RV32/64C Standard Extension (Quadrant 2) *** +slli 000 . ..... ..... 10 @c_shift2 +fld 001 . ..... ..... 10 @c_ldsp +{ + illegal 010 - 00000 ----- 10 # c.lwsp, RES rd=0 + lw 010 . ..... ..... 10 @c_lwsp +} +{ + illegal 100 0 00000 00000 10 # c.jr, RES rs1=0 + jalr 100 0 ..... 00000 10 @c_jalr rd=0 # C.JR + addi 100 0 ..... ..... 10 @c_mv +} +{ + ebreak 100 1 00000 00000 10 + jalr 100 1 ..... 00000 10 @c_jalr rd=1 # C.JALR + add 100 1 ..... ..... 10 @cr +} +fsd 101 ...... ..... 10 @c_sdsp +sw 110 . ..... ..... 10 @c_swsp diff --git a/target/riscv/insn32.decode b/target/riscv/insn32.decode index 6f3ab7aa52..77f794ed70 100644 --- a/target/riscv/insn32.decode +++ b/target/riscv/insn32.decode @@ -34,9 +34,13 @@ %imm_u 12:s20 !function=ex_shift_12 # Argument sets: +&empty &b imm rs2 rs1 &i imm rs1 rd +&j imm rd &r rd rs1 rs2 +&s imm rs1 rs2 +&u imm rd &shift shamt rs1 rd &atomic aq rl rs2 rs1 rd @@ -44,9 +48,9 @@ @r ....... ..... ..... ... ..... ....... &r %rs2 %rs1 %rd @i ............ ..... ... ..... ....... &i imm=%imm_i %rs1 %rd @b ....... ..... ..... ... ..... ....... &b imm=%imm_b %rs2 %rs1 -@s ....... ..... ..... ... ..... ....... imm=%imm_s %rs2 %rs1 -@u .................... ..... ....... imm=%imm_u %rd -@j .................... ..... ....... imm=%imm_j %rd +@s ....... ..... ..... ... ..... ....... &s imm=%imm_s %rs2 %rs1 +@u .................... ..... ....... &u imm=%imm_u %rd +@j .................... ..... ....... &j imm=%imm_j %rd @sh ...... ...... ..... ... ..... ....... &shift shamt=%sh10 %rs1 %rd @csr ............ ..... ... ..... ....... %csr %rs1 %rd diff --git a/target/riscv/insn_trans/trans_privileged.inc.c b/target/riscv/insn_trans/trans_privileged.inc.c index acb605923e..664d6ba3f2 100644 --- a/target/riscv/insn_trans/trans_privileged.inc.c +++ b/target/riscv/insn_trans/trans_privileged.inc.c @@ -22,7 +22,7 @@ static bool trans_ecall(DisasContext *ctx, arg_ecall *a) { /* always generates U-level ECALL, fixed in do_interrupt handler */ generate_exception(ctx, RISCV_EXCP_U_ECALL); - tcg_gen_exit_tb(NULL, 0); /* no chaining */ + exit_tb(ctx); /* no chaining */ ctx->base.is_jmp = DISAS_NORETURN; return true; } @@ -30,7 +30,7 @@ static bool trans_ecall(DisasContext *ctx, arg_ecall *a) static bool trans_ebreak(DisasContext *ctx, arg_ebreak *a) { generate_exception(ctx, RISCV_EXCP_BREAKPOINT); - tcg_gen_exit_tb(NULL, 0); /* no chaining */ + exit_tb(ctx); /* no chaining */ ctx->base.is_jmp = DISAS_NORETURN; return true; } @@ -47,7 +47,7 @@ static bool trans_sret(DisasContext *ctx, arg_sret *a) if (has_ext(ctx, RVS)) { gen_helper_sret(cpu_pc, cpu_env, cpu_pc); - tcg_gen_exit_tb(NULL, 0); /* no chaining */ + exit_tb(ctx); /* no chaining */ ctx->base.is_jmp = DISAS_NORETURN; } else { return false; @@ -68,7 +68,7 @@ static bool trans_mret(DisasContext *ctx, arg_mret *a) #ifndef CONFIG_USER_ONLY tcg_gen_movi_tl(cpu_pc, ctx->base.pc_next); gen_helper_mret(cpu_pc, cpu_env, cpu_pc); - tcg_gen_exit_tb(NULL, 0); /* no chaining */ + exit_tb(ctx); /* no chaining */ ctx->base.is_jmp = DISAS_NORETURN; return true; #else diff --git a/target/riscv/insn_trans/trans_rvc.inc.c b/target/riscv/insn_trans/trans_rvc.inc.c deleted file mode 100644 index 3e5d6fd5ea..0000000000 --- a/target/riscv/insn_trans/trans_rvc.inc.c +++ /dev/null @@ -1,347 +0,0 @@ -/* - * RISC-V translation routines for the RVC Compressed Instruction Set. - * - * Copyright (c) 2016-2017 Sagar Karandikar, sagark@eecs.berkeley.edu - * Copyright (c) 2018 Peer Adelt, peer.adelt@hni.uni-paderborn.de - * Bastian Koppelmann, kbastian@mail.uni-paderborn.de - * - * This program is free software; you can redistribute it and/or modify it - * under the terms and conditions of the GNU General Public License, - * version 2 or later, as published by the Free Software Foundation. - * - * This program is distributed in the hope 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, see <http://www.gnu.org/licenses/>. - */ - -static bool trans_c_addi4spn(DisasContext *ctx, arg_c_addi4spn *a) -{ - if (a->nzuimm == 0) { - /* Reserved in ISA */ - return false; - } - arg_addi arg = { .rd = a->rd, .rs1 = 2, .imm = a->nzuimm }; - return trans_addi(ctx, &arg); -} - -static bool trans_c_fld(DisasContext *ctx, arg_c_fld *a) -{ - arg_fld arg = { .rd = a->rd, .rs1 = a->rs1, .imm = a->uimm }; - return trans_fld(ctx, &arg); -} - -static bool trans_c_lw(DisasContext *ctx, arg_c_lw *a) -{ - arg_lw arg = { .rd = a->rd, .rs1 = a->rs1, .imm = a->uimm }; - return trans_lw(ctx, &arg); -} - -static bool trans_c_flw_ld(DisasContext *ctx, arg_c_flw_ld *a) -{ -#ifdef TARGET_RISCV32 - /* C.FLW ( RV32FC-only ) */ - REQUIRE_FPU; - REQUIRE_EXT(ctx, RVF); - - arg_c_lw tmp; - decode_insn16_extract_cl_w(ctx, &tmp, ctx->opcode); - arg_flw arg = { .rd = tmp.rd, .rs1 = tmp.rs1, .imm = tmp.uimm }; - return trans_flw(ctx, &arg); -#else - /* C.LD ( RV64C/RV128C-only ) */ - arg_c_fld tmp; - decode_insn16_extract_cl_d(ctx, &tmp, ctx->opcode); - arg_ld arg = { .rd = tmp.rd, .rs1 = tmp.rs1, .imm = tmp.uimm }; - return trans_ld(ctx, &arg); -#endif -} - -static bool trans_c_fsd(DisasContext *ctx, arg_c_fsd *a) -{ - arg_fsd arg = { .rs1 = a->rs1, .rs2 = a->rs2, .imm = a->uimm }; - return trans_fsd(ctx, &arg); -} - -static bool trans_c_sw(DisasContext *ctx, arg_c_sw *a) -{ - arg_sw arg = { .rs1 = a->rs1, .rs2 = a->rs2, .imm = a->uimm }; - return trans_sw(ctx, &arg); -} - -static bool trans_c_fsw_sd(DisasContext *ctx, arg_c_fsw_sd *a) -{ -#ifdef TARGET_RISCV32 - /* C.FSW ( RV32FC-only ) */ - REQUIRE_FPU; - REQUIRE_EXT(ctx, RVF); - - arg_c_sw tmp; - decode_insn16_extract_cs_w(ctx, &tmp, ctx->opcode); - arg_fsw arg = { .rs1 = tmp.rs1, .rs2 = tmp.rs2, .imm = tmp.uimm }; - return trans_fsw(ctx, &arg); -#else - /* C.SD ( RV64C/RV128C-only ) */ - arg_c_fsd tmp; - decode_insn16_extract_cs_d(ctx, &tmp, ctx->opcode); - arg_sd arg = { .rs1 = tmp.rs1, .rs2 = tmp.rs2, .imm = tmp.uimm }; - return trans_sd(ctx, &arg); -#endif -} - -static bool trans_c_addi(DisasContext *ctx, arg_c_addi *a) -{ - if (a->imm == 0) { - /* Hint: insn is valid but does not affect state */ - return true; - } - arg_addi arg = { .rd = a->rd, .rs1 = a->rd, .imm = a->imm }; - return trans_addi(ctx, &arg); -} - -static bool trans_c_jal_addiw(DisasContext *ctx, arg_c_jal_addiw *a) -{ -#ifdef TARGET_RISCV32 - /* C.JAL */ - arg_c_j tmp; - decode_insn16_extract_cj(ctx, &tmp, ctx->opcode); - arg_jal arg = { .rd = 1, .imm = tmp.imm }; - return trans_jal(ctx, &arg); -#else - /* C.ADDIW */ - arg_addiw arg = { .rd = a->rd, .rs1 = a->rd, .imm = a->imm }; - return trans_addiw(ctx, &arg); -#endif -} - -static bool trans_c_li(DisasContext *ctx, arg_c_li *a) -{ - if (a->rd == 0) { - /* Hint: insn is valid but does not affect state */ - return true; - } - arg_addi arg = { .rd = a->rd, .rs1 = 0, .imm = a->imm }; - return trans_addi(ctx, &arg); -} - -static bool trans_c_addi16sp_lui(DisasContext *ctx, arg_c_addi16sp_lui *a) -{ - if (a->rd == 2) { - /* C.ADDI16SP */ - arg_addi arg = { .rd = 2, .rs1 = 2, .imm = a->imm_addi16sp }; - return trans_addi(ctx, &arg); - } else if (a->imm_lui != 0) { - /* C.LUI */ - if (a->rd == 0) { - /* Hint: insn is valid but does not affect state */ - return true; - } - arg_lui arg = { .rd = a->rd, .imm = a->imm_lui }; - return trans_lui(ctx, &arg); - } - return false; -} - -static bool trans_c_srli(DisasContext *ctx, arg_c_srli *a) -{ - int shamt = a->shamt; - if (shamt == 0) { - /* For RV128 a shamt of 0 means a shift by 64 */ - shamt = 64; - } - /* Ensure, that shamt[5] is zero for RV32 */ - if (shamt >= TARGET_LONG_BITS) { - return false; - } - - arg_srli arg = { .rd = a->rd, .rs1 = a->rd, .shamt = a->shamt }; - return trans_srli(ctx, &arg); -} - -static bool trans_c_srai(DisasContext *ctx, arg_c_srai *a) -{ - int shamt = a->shamt; - if (shamt == 0) { - /* For RV128 a shamt of 0 means a shift by 64 */ - shamt = 64; - } - /* Ensure, that shamt[5] is zero for RV32 */ - if (shamt >= TARGET_LONG_BITS) { - return false; - } - - arg_srai arg = { .rd = a->rd, .rs1 = a->rd, .shamt = a->shamt }; - return trans_srai(ctx, &arg); -} - -static bool trans_c_andi(DisasContext *ctx, arg_c_andi *a) -{ - arg_andi arg = { .rd = a->rd, .rs1 = a->rd, .imm = a->imm }; - return trans_andi(ctx, &arg); -} - -static bool trans_c_sub(DisasContext *ctx, arg_c_sub *a) -{ - arg_sub arg = { .rd = a->rd, .rs1 = a->rd, .rs2 = a->rs2 }; - return trans_sub(ctx, &arg); -} - -static bool trans_c_xor(DisasContext *ctx, arg_c_xor *a) -{ - arg_xor arg = { .rd = a->rd, .rs1 = a->rd, .rs2 = a->rs2 }; - return trans_xor(ctx, &arg); -} - -static bool trans_c_or(DisasContext *ctx, arg_c_or *a) -{ - arg_or arg = { .rd = a->rd, .rs1 = a->rd, .rs2 = a->rs2 }; - return trans_or(ctx, &arg); -} - -static bool trans_c_and(DisasContext *ctx, arg_c_and *a) -{ - arg_and arg = { .rd = a->rd, .rs1 = a->rd, .rs2 = a->rs2 }; - return trans_and(ctx, &arg); -} - -static bool trans_c_subw(DisasContext *ctx, arg_c_subw *a) -{ -#ifdef TARGET_RISCV64 - arg_subw arg = { .rd = a->rd, .rs1 = a->rd, .rs2 = a->rs2 }; - return trans_subw(ctx, &arg); -#else - return false; -#endif -} - -static bool trans_c_addw(DisasContext *ctx, arg_c_addw *a) -{ -#ifdef TARGET_RISCV64 - arg_addw arg = { .rd = a->rd, .rs1 = a->rd, .rs2 = a->rs2 }; - return trans_addw(ctx, &arg); -#else - return false; -#endif -} - -static bool trans_c_j(DisasContext *ctx, arg_c_j *a) -{ - arg_jal arg = { .rd = 0, .imm = a->imm }; - return trans_jal(ctx, &arg); -} - -static bool trans_c_beqz(DisasContext *ctx, arg_c_beqz *a) -{ - arg_beq arg = { .rs1 = a->rs1, .rs2 = 0, .imm = a->imm }; - return trans_beq(ctx, &arg); -} - -static bool trans_c_bnez(DisasContext *ctx, arg_c_bnez *a) -{ - arg_bne arg = { .rs1 = a->rs1, .rs2 = 0, .imm = a->imm }; - return trans_bne(ctx, &arg); -} - -static bool trans_c_slli(DisasContext *ctx, arg_c_slli *a) -{ - int shamt = a->shamt; - if (shamt == 0) { - /* For RV128 a shamt of 0 means a shift by 64 */ - shamt = 64; - } - /* Ensure, that shamt[5] is zero for RV32 */ - if (shamt >= TARGET_LONG_BITS) { - return false; - } - - arg_slli arg = { .rd = a->rd, .rs1 = a->rd, .shamt = a->shamt }; - return trans_slli(ctx, &arg); -} - -static bool trans_c_fldsp(DisasContext *ctx, arg_c_fldsp *a) -{ - arg_fld arg = { .rd = a->rd, .rs1 = 2, .imm = a->uimm }; - return trans_fld(ctx, &arg); -} - -static bool trans_c_lwsp(DisasContext *ctx, arg_c_lwsp *a) -{ - arg_lw arg = { .rd = a->rd, .rs1 = 2, .imm = a->uimm }; - return trans_lw(ctx, &arg); -} - -static bool trans_c_flwsp_ldsp(DisasContext *ctx, arg_c_flwsp_ldsp *a) -{ -#ifdef TARGET_RISCV32 - /* C.FLWSP */ - arg_flw arg_flw = { .rd = a->rd, .rs1 = 2, .imm = a->uimm_flwsp }; - return trans_flw(ctx, &arg_flw); -#else - /* C.LDSP */ - arg_ld arg_ld = { .rd = a->rd, .rs1 = 2, .imm = a->uimm_ldsp }; - return trans_ld(ctx, &arg_ld); -#endif - return false; -} - -static bool trans_c_jr_mv(DisasContext *ctx, arg_c_jr_mv *a) -{ - if (a->rd != 0 && a->rs2 == 0) { - /* C.JR */ - arg_jalr arg = { .rd = 0, .rs1 = a->rd, .imm = 0 }; - return trans_jalr(ctx, &arg); - } else if (a->rd != 0 && a->rs2 != 0) { - /* C.MV */ - arg_add arg = { .rd = a->rd, .rs1 = 0, .rs2 = a->rs2 }; - return trans_add(ctx, &arg); - } - return false; -} - -static bool trans_c_ebreak_jalr_add(DisasContext *ctx, arg_c_ebreak_jalr_add *a) -{ - if (a->rd == 0 && a->rs2 == 0) { - /* C.EBREAK */ - arg_ebreak arg = { }; - return trans_ebreak(ctx, &arg); - } else if (a->rd != 0) { - if (a->rs2 == 0) { - /* C.JALR */ - arg_jalr arg = { .rd = 1, .rs1 = a->rd, .imm = 0 }; - return trans_jalr(ctx, &arg); - } else { - /* C.ADD */ - arg_add arg = { .rd = a->rd, .rs1 = a->rd, .rs2 = a->rs2 }; - return trans_add(ctx, &arg); - } - } - return false; -} - -static bool trans_c_fsdsp(DisasContext *ctx, arg_c_fsdsp *a) -{ - arg_fsd arg = { .rs1 = 2, .rs2 = a->rs2, .imm = a->uimm }; - return trans_fsd(ctx, &arg); -} - -static bool trans_c_swsp(DisasContext *ctx, arg_c_swsp *a) -{ - arg_sw arg = { .rs1 = 2, .rs2 = a->rs2, .imm = a->uimm }; - return trans_sw(ctx, &arg); -} - -static bool trans_c_fswsp_sdsp(DisasContext *ctx, arg_c_fswsp_sdsp *a) -{ -#ifdef TARGET_RISCV32 - /* C.FSWSP */ - arg_fsw a_fsw = { .rs1 = 2, .rs2 = a->rs2, .imm = a->uimm_fswsp }; - return trans_fsw(ctx, &a_fsw); -#else - /* C.SDSP */ - arg_sd a_sd = { .rs1 = 2, .rs2 = a->rs2, .imm = a->uimm_sdsp }; - return trans_sd(ctx, &a_sd); -#endif -} diff --git a/target/riscv/insn_trans/trans_rvi.inc.c b/target/riscv/insn_trans/trans_rvi.inc.c index d420a4d8b2..6cda078ed6 100644 --- a/target/riscv/insn_trans/trans_rvi.inc.c +++ b/target/riscv/insn_trans/trans_rvi.inc.c @@ -18,6 +18,12 @@ * this program. If not, see <http://www.gnu.org/licenses/>. */ +static bool trans_illegal(DisasContext *ctx, arg_empty *a) +{ + gen_exception_illegal(ctx); + return true; +} + static bool trans_lui(DisasContext *ctx, arg_lui *a) { if (a->rd != 0) { @@ -60,7 +66,7 @@ static bool trans_jalr(DisasContext *ctx, arg_jalr *a) if (a->rd != 0) { tcg_gen_movi_tl(cpu_gpr[a->rd], ctx->pc_succ_insn); } - tcg_gen_lookup_and_goto_ptr(); + lookup_and_goto_ptr(ctx); if (misaligned) { gen_set_label(misaligned); @@ -217,7 +223,7 @@ static bool trans_sd(DisasContext *ctx, arg_sd *a) static bool trans_addi(DisasContext *ctx, arg_addi *a) { - return gen_arith_imm(ctx, a, &tcg_gen_add_tl); + return gen_arith_imm_fn(ctx, a, &tcg_gen_addi_tl); } static void gen_slt(TCGv ret, TCGv s1, TCGv s2) @@ -233,25 +239,25 @@ static void gen_sltu(TCGv ret, TCGv s1, TCGv s2) static bool trans_slti(DisasContext *ctx, arg_slti *a) { - return gen_arith_imm(ctx, a, &gen_slt); + return gen_arith_imm_tl(ctx, a, &gen_slt); } static bool trans_sltiu(DisasContext *ctx, arg_sltiu *a) { - return gen_arith_imm(ctx, a, &gen_sltu); + return gen_arith_imm_tl(ctx, a, &gen_sltu); } static bool trans_xori(DisasContext *ctx, arg_xori *a) { - return gen_arith_imm(ctx, a, &tcg_gen_xor_tl); + return gen_arith_imm_fn(ctx, a, &tcg_gen_xori_tl); } static bool trans_ori(DisasContext *ctx, arg_ori *a) { - return gen_arith_imm(ctx, a, &tcg_gen_or_tl); + return gen_arith_imm_fn(ctx, a, &tcg_gen_ori_tl); } static bool trans_andi(DisasContext *ctx, arg_andi *a) { - return gen_arith_imm(ctx, a, &tcg_gen_and_tl); + return gen_arith_imm_fn(ctx, a, &tcg_gen_andi_tl); } static bool trans_slli(DisasContext *ctx, arg_slli *a) { @@ -358,7 +364,7 @@ static bool trans_and(DisasContext *ctx, arg_and *a) #ifdef TARGET_RISCV64 static bool trans_addiw(DisasContext *ctx, arg_addiw *a) { - return gen_arith_imm(ctx, a, &gen_addw); + return gen_arith_imm_tl(ctx, a, &gen_addw); } static bool trans_slliw(DisasContext *ctx, arg_slliw *a) @@ -483,7 +489,7 @@ static bool trans_fence_i(DisasContext *ctx, arg_fence_i *a) * however we need to end the translation block */ tcg_gen_movi_tl(cpu_pc, ctx->pc_succ_insn); - tcg_gen_exit_tb(NULL, 0); + exit_tb(ctx); ctx->base.is_jmp = DISAS_NORETURN; return true; } @@ -504,7 +510,7 @@ static bool trans_fence_i(DisasContext *ctx, arg_fence_i *a) gen_io_end(); \ gen_set_gpr(a->rd, dest); \ tcg_gen_movi_tl(cpu_pc, ctx->pc_succ_insn); \ - tcg_gen_exit_tb(NULL, 0); \ + exit_tb(ctx); \ ctx->base.is_jmp = DISAS_NORETURN; \ tcg_temp_free(source1); \ tcg_temp_free(csr_store); \ diff --git a/target/riscv/op_helper.c b/target/riscv/op_helper.c index b7dc18a41e..644d0fb35f 100644 --- a/target/riscv/op_helper.c +++ b/target/riscv/op_helper.c @@ -145,9 +145,10 @@ void helper_tlb_flush(CPURISCVState *env) { RISCVCPU *cpu = riscv_env_get_cpu(env); CPUState *cs = CPU(cpu); - if (env->priv == PRV_S && - env->priv_ver >= PRIV_VERSION_1_10_0 && - get_field(env->mstatus, MSTATUS_TVM)) { + if (!(env->priv >= PRV_S) || + (env->priv == PRV_S && + env->priv_ver >= PRIV_VERSION_1_10_0 && + get_field(env->mstatus, MSTATUS_TVM))) { riscv_raise_exception(env, RISCV_EXCP_ILLEGAL_INST, GETPC()); } else { tlb_flush(cs); diff --git a/target/riscv/translate.c b/target/riscv/translate.c index 2ff6b49487..313c27b700 100644 --- a/target/riscv/translate.c +++ b/target/riscv/translate.c @@ -109,6 +109,26 @@ static void gen_exception_debug(void) tcg_temp_free_i32(helper_tmp); } +/* Wrapper around tcg_gen_exit_tb that handles single stepping */ +static void exit_tb(DisasContext *ctx) +{ + if (ctx->base.singlestep_enabled) { + gen_exception_debug(); + } else { + tcg_gen_exit_tb(NULL, 0); + } +} + +/* Wrapper around tcg_gen_lookup_and_goto_ptr that handles single stepping */ +static void lookup_and_goto_ptr(DisasContext *ctx) +{ + if (ctx->base.singlestep_enabled) { + gen_exception_debug(); + } else { + tcg_gen_lookup_and_goto_ptr(); + } +} + static void gen_exception_illegal(DisasContext *ctx) { generate_exception(ctx, RISCV_EXCP_ILLEGAL_INST); @@ -138,14 +158,14 @@ static void gen_goto_tb(DisasContext *ctx, int n, target_ulong dest) /* chaining is only allowed when the jump is to the same page */ tcg_gen_goto_tb(n); tcg_gen_movi_tl(cpu_pc, dest); + + /* No need to check for single stepping here as use_goto_tb() will + * return false in case of single stepping. + */ tcg_gen_exit_tb(ctx->base.tb, n); } else { tcg_gen_movi_tl(cpu_pc, dest); - if (ctx->base.singlestep_enabled) { - gen_exception_debug(); - } else { - tcg_gen_lookup_and_goto_ptr(); - } + lookup_and_goto_ptr(ctx); } } @@ -538,12 +558,32 @@ static int ex_rvc_register(DisasContext *ctx, int reg) return 8 + reg; } -bool decode_insn32(DisasContext *ctx, uint32_t insn); +static int ex_rvc_shifti(DisasContext *ctx, int imm) +{ + /* For RV128 a shamt of 0 means a shift by 64. */ + return imm ? imm : 64; +} + /* Include the auto-generated decoder for 32 bit insn */ #include "decode_insn32.inc.c" -static bool gen_arith_imm(DisasContext *ctx, arg_i *a, - void(*func)(TCGv, TCGv, TCGv)) +static bool gen_arith_imm_fn(DisasContext *ctx, arg_i *a, + void (*func)(TCGv, TCGv, target_long)) +{ + TCGv source1; + source1 = tcg_temp_new(); + + gen_get_gpr(source1, a->rs1); + + (*func)(source1, source1, a->imm); + + gen_set_gpr(a->rd, source1); + tcg_temp_free(source1); + return true; +} + +static bool gen_arith_imm_tl(DisasContext *ctx, arg_i *a, + void (*func)(TCGv, TCGv, TCGv)) { TCGv source1, source2; source1 = tcg_temp_new(); @@ -667,10 +707,25 @@ static bool gen_shift(DisasContext *ctx, arg_r *a, #include "insn_trans/trans_rvd.inc.c" #include "insn_trans/trans_privileged.inc.c" -bool decode_insn16(DisasContext *ctx, uint16_t insn); -/* auto-generated decoder*/ +/* + * Auto-generated decoder. + * Note that the 16-bit decoder reuses some of the trans_* functions + * initially declared by the 32-bit decoder, which results in duplicate + * declaration warnings. Suppress them. + */ +#ifdef CONFIG_PRAGMA_DIAGNOSTIC_AVAILABLE +# pragma GCC diagnostic push +# pragma GCC diagnostic ignored "-Wredundant-decls" +# ifdef __clang__ +# pragma GCC diagnostic ignored "-Wtypedef-redefinition" +# endif +#endif + #include "decode_insn16.inc.c" -#include "insn_trans/trans_rvc.inc.c" + +#ifdef CONFIG_PRAGMA_DIAGNOSTIC_AVAILABLE +# pragma GCC diagnostic pop +#endif static void decode_opc(DisasContext *ctx) { diff --git a/target/s390x/Makefile.objs b/target/s390x/Makefile.objs index 0316457880..3e2745594a 100644 --- a/target/s390x/Makefile.objs +++ b/target/s390x/Makefile.objs @@ -1,7 +1,8 @@ obj-y += cpu.o cpu_models.o cpu_features.o gdbstub.o interrupt.o helper.o obj-$(CONFIG_TCG) += translate.o cc_helper.o excp_helper.o fpu_helper.o obj-$(CONFIG_TCG) += int_helper.o mem_helper.o misc_helper.o crypto_helper.o -obj-$(CONFIG_TCG) += vec_helper.o vec_int_helper.o +obj-$(CONFIG_TCG) += vec_helper.o vec_int_helper.o vec_string_helper.o +obj-$(CONFIG_TCG) += vec_fpu_helper.o obj-$(CONFIG_SOFTMMU) += machine.o ioinst.o arch_dump.o mmu_helper.o diag.o obj-$(CONFIG_SOFTMMU) += sigp.o obj-$(CONFIG_KVM) += kvm.o diff --git a/target/s390x/arch_dump.c b/target/s390x/arch_dump.c index c9ef0a6e60..50fa0ae4b6 100644 --- a/target/s390x/arch_dump.c +++ b/target/s390x/arch_dump.c @@ -104,7 +104,7 @@ static void s390x_write_elf64_fpregset(Note *note, S390CPU *cpu, int id) note->hdr.n_type = cpu_to_be32(NT_FPREGSET); note->contents.fpregset.fpc = cpu_to_be32(cpu->env.fpc); for (i = 0; i <= 15; i++) { - note->contents.fpregset.fprs[i] = cpu_to_be64(get_freg(cs, i)->ll); + note->contents.fpregset.fprs[i] = cpu_to_be64(*get_freg(cs, i)); } } @@ -114,7 +114,7 @@ static void s390x_write_elf64_vregslo(Note *note, S390CPU *cpu, int id) note->hdr.n_type = cpu_to_be32(NT_S390_VXRS_LOW); for (i = 0; i <= 15; i++) { - note->contents.vregslo.vregs[i] = cpu_to_be64(cpu->env.vregs[i][1].ll); + note->contents.vregslo.vregs[i] = cpu_to_be64(cpu->env.vregs[i][1]); } } @@ -127,8 +127,8 @@ static void s390x_write_elf64_vregshi(Note *note, S390CPU *cpu, int id) note->hdr.n_type = cpu_to_be32(NT_S390_VXRS_HIGH); for (i = 0; i <= 15; i++) { - temp_vregshi->vregs[i][0] = cpu_to_be64(cpu->env.vregs[i + 16][0].ll); - temp_vregshi->vregs[i][1] = cpu_to_be64(cpu->env.vregs[i + 16][1].ll); + temp_vregshi->vregs[i][0] = cpu_to_be64(cpu->env.vregs[i + 16][0]); + temp_vregshi->vregs[i][1] = cpu_to_be64(cpu->env.vregs[i + 16][1]); } } diff --git a/target/s390x/cpu.c b/target/s390x/cpu.c index b1df63d82c..6af1a1530f 100644 --- a/target/s390x/cpu.c +++ b/target/s390x/cpu.c @@ -145,6 +145,9 @@ static void s390_cpu_full_reset(CPUState *s) #if defined(CONFIG_USER_ONLY) /* user mode should always be allowed to use the full FPU */ env->cregs[0] |= CR0_AFP; + if (s390_has_feat(S390_FEAT_VECTOR)) { + env->cregs[0] |= CR0_VECTOR; + } #endif /* architectured initial value for Breaking-Event-Address register */ diff --git a/target/s390x/cpu.h b/target/s390x/cpu.h index 7305cacc7b..4fc08a2c88 100644 --- a/target/s390x/cpu.h +++ b/target/s390x/cpu.h @@ -66,7 +66,7 @@ struct CPUS390XState { * The floating point registers are part of the vector registers. * vregs[0][0] -> vregs[15][0] are 16 floating point registers */ - CPU_DoubleU vregs[32][2]; /* vector registers */ + uint64_t vregs[32][2] QEMU_ALIGNED(16); /* vector registers */ uint32_t aregs[16]; /* access registers */ uint8_t riccb[64]; /* runtime instrumentation control */ uint64_t gscb[4]; /* guarded storage control */ @@ -153,7 +153,7 @@ struct CPUS390XState { }; -static inline CPU_DoubleU *get_freg(CPUS390XState *cs, int nr) +static inline uint64_t *get_freg(CPUS390XState *cs, int nr) { return &cs->vregs[nr][0]; } @@ -215,6 +215,7 @@ extern const struct VMStateDescription vmstate_s390_cpu; #define PGM_SPECIAL_OP 0x0013 #define PGM_OPERAND 0x0015 #define PGM_TRACE_TABLE 0x0016 +#define PGM_VECTOR_PROCESSING 0x001b #define PGM_SPACE_SWITCH 0x001c #define PGM_HFP_SQRT 0x001d #define PGM_PC_TRANS_SPEC 0x001f diff --git a/target/s390x/cpu_models.c b/target/s390x/cpu_models.c index 21ea819483..b5d16e4c89 100644 --- a/target/s390x/cpu_models.c +++ b/target/s390x/cpu_models.c @@ -86,8 +86,8 @@ static S390CPUDef s390_cpu_defs[] = { CPUDEF_INIT(0x8562, 15, 1, 47, 0x08000000U, "gen15b", "IBM 8562 GA1"), }; -#define QEMU_MAX_CPU_TYPE 0x2827 -#define QEMU_MAX_CPU_GEN 12 +#define QEMU_MAX_CPU_TYPE 0x2964 +#define QEMU_MAX_CPU_GEN 13 #define QEMU_MAX_CPU_EC_GA 2 static const S390FeatInit qemu_max_cpu_feat_init = { S390_FEAT_LIST_QEMU_MAX }; static S390FeatBitmap qemu_max_cpu_feat; diff --git a/target/s390x/excp_helper.c b/target/s390x/excp_helper.c index 3a467b72c5..f21bcf79ae 100644 --- a/target/s390x/excp_helper.c +++ b/target/s390x/excp_helper.c @@ -62,6 +62,21 @@ void QEMU_NORETURN tcg_s390_data_exception(CPUS390XState *env, uint32_t dxc, tcg_s390_program_interrupt(env, PGM_DATA, ILEN_AUTO, ra); } +void QEMU_NORETURN tcg_s390_vector_exception(CPUS390XState *env, uint32_t vxc, + uintptr_t ra) +{ + g_assert(vxc <= 0xff); +#if !defined(CONFIG_USER_ONLY) + /* Always store the VXC into the lowcore, without AFP it is undefined */ + stl_phys(CPU(s390_env_get_cpu(env))->as, + env->psa + offsetof(LowCore, data_exc_code), vxc); +#endif + + /* Always store the VXC into the FPC, without AFP it is undefined */ + env->fpc = deposit32(env->fpc, 8, 8, vxc); + tcg_s390_program_interrupt(env, PGM_VECTOR_PROCESSING, ILEN_AUTO, ra); +} + void HELPER(data_exception)(CPUS390XState *env, uint32_t dxc) { tcg_s390_data_exception(env, dxc, GETPC()); @@ -390,8 +405,8 @@ static int mchk_store_vregs(CPUS390XState *env, uint64_t mcesao) } for (i = 0; i < 32; i++) { - sa->vregs[i][0] = cpu_to_be64(env->vregs[i][0].ll); - sa->vregs[i][1] = cpu_to_be64(env->vregs[i][1].ll); + sa->vregs[i][0] = cpu_to_be64(env->vregs[i][0]); + sa->vregs[i][1] = cpu_to_be64(env->vregs[i][1]); } cpu_physical_memory_unmap(sa, len, 1, len); @@ -429,7 +444,7 @@ static void do_mchk_interrupt(CPUS390XState *env) lowcore->ar_access_id = 1; for (i = 0; i < 16; i++) { - lowcore->floating_pt_save_area[i] = cpu_to_be64(get_freg(env, i)->ll); + lowcore->floating_pt_save_area[i] = cpu_to_be64(*get_freg(env, i)); lowcore->gpregs_save_area[i] = cpu_to_be64(env->regs[i]); lowcore->access_regs_save_area[i] = cpu_to_be32(env->aregs[i]); lowcore->cregs_save_area[i] = cpu_to_be64(env->cregs[i]); diff --git a/target/s390x/fpu_helper.c b/target/s390x/fpu_helper.c index 1be68bafea..d2c17ed942 100644 --- a/target/s390x/fpu_helper.c +++ b/target/s390x/fpu_helper.c @@ -112,7 +112,7 @@ static void handle_exceptions(CPUS390XState *env, bool XxC, uintptr_t retaddr) } } -static inline int float_comp_to_cc(CPUS390XState *env, int float_compare) +int float_comp_to_cc(CPUS390XState *env, int float_compare) { S390CPU *cpu = s390_env_get_cpu(env); @@ -746,7 +746,7 @@ static inline uint16_t dcmask(int bit, bool neg) } #define DEF_FLOAT_DCMASK(_TYPE) \ -static uint16_t _TYPE##_dcmask(CPUS390XState *env, _TYPE f1) \ +uint16_t _TYPE##_dcmask(CPUS390XState *env, _TYPE f1) \ { \ const bool neg = _TYPE##_is_neg(f1); \ \ diff --git a/target/s390x/gdbstub.c b/target/s390x/gdbstub.c index df147596ce..9cfd8fe3e0 100644 --- a/target/s390x/gdbstub.c +++ b/target/s390x/gdbstub.c @@ -116,7 +116,7 @@ static int cpu_read_fp_reg(CPUS390XState *env, uint8_t *mem_buf, int n) case S390_FPC_REGNUM: return gdb_get_reg32(mem_buf, env->fpc); case S390_F0_REGNUM ... S390_F15_REGNUM: - return gdb_get_reg64(mem_buf, get_freg(env, n - S390_F0_REGNUM)->ll); + return gdb_get_reg64(mem_buf, *get_freg(env, n - S390_F0_REGNUM)); default: return 0; } @@ -129,7 +129,7 @@ static int cpu_write_fp_reg(CPUS390XState *env, uint8_t *mem_buf, int n) env->fpc = ldl_p(mem_buf); return 4; case S390_F0_REGNUM ... S390_F15_REGNUM: - get_freg(env, n - S390_F0_REGNUM)->ll = ldtul_p(mem_buf); + *get_freg(env, n - S390_F0_REGNUM) = ldtul_p(mem_buf); return 8; default: return 0; @@ -150,11 +150,11 @@ static int cpu_read_vreg(CPUS390XState *env, uint8_t *mem_buf, int n) switch (n) { case S390_V0L_REGNUM ... S390_V15L_REGNUM: - ret = gdb_get_reg64(mem_buf, env->vregs[n][1].ll); + ret = gdb_get_reg64(mem_buf, env->vregs[n][1]); break; case S390_V16_REGNUM ... S390_V31_REGNUM: - ret = gdb_get_reg64(mem_buf, env->vregs[n][0].ll); - ret += gdb_get_reg64(mem_buf + 8, env->vregs[n][1].ll); + ret = gdb_get_reg64(mem_buf, env->vregs[n][0]); + ret += gdb_get_reg64(mem_buf + 8, env->vregs[n][1]); break; default: ret = 0; @@ -167,11 +167,11 @@ static int cpu_write_vreg(CPUS390XState *env, uint8_t *mem_buf, int n) { switch (n) { case S390_V0L_REGNUM ... S390_V15L_REGNUM: - env->vregs[n][1].ll = ldtul_p(mem_buf + 8); + env->vregs[n][1] = ldtul_p(mem_buf + 8); return 8; case S390_V16_REGNUM ... S390_V31_REGNUM: - env->vregs[n][0].ll = ldtul_p(mem_buf); - env->vregs[n][1].ll = ldtul_p(mem_buf + 8); + env->vregs[n][0] = ldtul_p(mem_buf); + env->vregs[n][1] = ldtul_p(mem_buf + 8); return 16; default: return 0; diff --git a/target/s390x/gen-features.c b/target/s390x/gen-features.c index c346b76bdf..dc320a06c2 100644 --- a/target/s390x/gen-features.c +++ b/target/s390x/gen-features.c @@ -689,7 +689,7 @@ static uint16_t qemu_V3_1[] = { S390_FEAT_MSA_EXT_4, }; -static uint16_t qemu_LATEST[] = { +static uint16_t qemu_V4_0[] = { /* * Only BFP bits are implemented (HFP, DFP, PFPO and DIVIDE TO INTEGER not * implemented yet). @@ -698,10 +698,13 @@ static uint16_t qemu_LATEST[] = { S390_FEAT_ZPCI, }; +static uint16_t qemu_LATEST[] = { + S390_FEAT_STFLE_53, + S390_FEAT_VECTOR, +}; + /* add all new definitions before this point */ static uint16_t qemu_MAX[] = { - /* z13+ features */ - S390_FEAT_STFLE_53, /* generates a dependency warning, leave it out for now */ S390_FEAT_MSA_EXT_5, }; @@ -820,6 +823,7 @@ static FeatGroupDefSpec FeatGroupDef[] = { static FeatGroupDefSpec QemuFeatDef[] = { QEMU_FEAT_INITIALIZER(V2_11), QEMU_FEAT_INITIALIZER(V3_1), + QEMU_FEAT_INITIALIZER(V4_0), QEMU_FEAT_INITIALIZER(LATEST), QEMU_FEAT_INITIALIZER(MAX), }; diff --git a/target/s390x/helper.c b/target/s390x/helper.c index 3c8f0a7615..a69e5abf5f 100644 --- a/target/s390x/helper.c +++ b/target/s390x/helper.c @@ -249,7 +249,7 @@ int s390_store_status(S390CPU *cpu, hwaddr addr, bool store_arch) cpu_physical_memory_write(offsetof(LowCore, ar_access_id), &ar_id, 1); } for (i = 0; i < 16; ++i) { - sa->fprs[i] = cpu_to_be64(get_freg(&cpu->env, i)->ll); + sa->fprs[i] = cpu_to_be64(*get_freg(&cpu->env, i)); } for (i = 0; i < 16; ++i) { sa->grs[i] = cpu_to_be64(cpu->env.regs[i]); @@ -299,8 +299,8 @@ int s390_store_adtl_status(S390CPU *cpu, hwaddr addr, hwaddr len) if (s390_has_feat(S390_FEAT_VECTOR)) { for (i = 0; i < 32; i++) { - sa->vregs[i][0] = cpu_to_be64(cpu->env.vregs[i][0].ll); - sa->vregs[i][1] = cpu_to_be64(cpu->env.vregs[i][1].ll); + sa->vregs[i][0] = cpu_to_be64(cpu->env.vregs[i][0]); + sa->vregs[i][1] = cpu_to_be64(cpu->env.vregs[i][1]); } } if (s390_has_feat(S390_FEAT_GUARDED_STORAGE) && len >= ADTL_GS_MIN_SIZE) { @@ -341,13 +341,13 @@ void s390_cpu_dump_state(CPUState *cs, FILE *f, int flags) if (s390_has_feat(S390_FEAT_VECTOR)) { for (i = 0; i < 32; i++) { qemu_fprintf(f, "V%02d=%016" PRIx64 "%016" PRIx64 "%c", - i, env->vregs[i][0].ll, env->vregs[i][1].ll, + i, env->vregs[i][0], env->vregs[i][1], i % 2 ? '\n' : ' '); } } else { for (i = 0; i < 16; i++) { qemu_fprintf(f, "F%02d=%016" PRIx64 "%c", - i, get_freg(env, i)->ll, + i, *get_freg(env, i), (i % 4) == 3 ? '\n' : ' '); } } diff --git a/target/s390x/helper.h b/target/s390x/helper.h index 7755a96c33..e9aff83b05 100644 --- a/target/s390x/helper.h +++ b/target/s390x/helper.h @@ -211,6 +211,90 @@ DEF_HELPER_FLAGS_4(gvec_vscbi8, TCG_CALL_NO_RWG, void, ptr, cptr, cptr, i32) DEF_HELPER_FLAGS_4(gvec_vscbi16, TCG_CALL_NO_RWG, void, ptr, cptr, cptr, i32) DEF_HELPER_4(gvec_vtm, void, ptr, cptr, env, i32) +/* === Vector String Instructions === */ +DEF_HELPER_FLAGS_4(gvec_vfae8, TCG_CALL_NO_RWG, void, ptr, cptr, cptr, i32) +DEF_HELPER_FLAGS_4(gvec_vfae16, TCG_CALL_NO_RWG, void, ptr, cptr, cptr, i32) +DEF_HELPER_FLAGS_4(gvec_vfae32, TCG_CALL_NO_RWG, void, ptr, cptr, cptr, i32) +DEF_HELPER_5(gvec_vfae_cc8, void, ptr, cptr, cptr, env, i32) +DEF_HELPER_5(gvec_vfae_cc16, void, ptr, cptr, cptr, env, i32) +DEF_HELPER_5(gvec_vfae_cc32, void, ptr, cptr, cptr, env, i32) +DEF_HELPER_FLAGS_4(gvec_vfee8, TCG_CALL_NO_RWG, void, ptr, cptr, cptr, i32) +DEF_HELPER_FLAGS_4(gvec_vfee16, TCG_CALL_NO_RWG, void, ptr, cptr, cptr, i32) +DEF_HELPER_FLAGS_4(gvec_vfee32, TCG_CALL_NO_RWG, void, ptr, cptr, cptr, i32) +DEF_HELPER_5(gvec_vfee_cc8, void, ptr, cptr, cptr, env, i32) +DEF_HELPER_5(gvec_vfee_cc16, void, ptr, cptr, cptr, env, i32) +DEF_HELPER_5(gvec_vfee_cc32, void, ptr, cptr, cptr, env, i32) +DEF_HELPER_FLAGS_4(gvec_vfene8, TCG_CALL_NO_RWG, void, ptr, cptr, cptr, i32) +DEF_HELPER_FLAGS_4(gvec_vfene16, TCG_CALL_NO_RWG, void, ptr, cptr, cptr, i32) +DEF_HELPER_FLAGS_4(gvec_vfene32, TCG_CALL_NO_RWG, void, ptr, cptr, cptr, i32) +DEF_HELPER_5(gvec_vfene_cc8, void, ptr, cptr, cptr, env, i32) +DEF_HELPER_5(gvec_vfene_cc16, void, ptr, cptr, cptr, env, i32) +DEF_HELPER_5(gvec_vfene_cc32, void, ptr, cptr, cptr, env, i32) +DEF_HELPER_FLAGS_3(gvec_vistr8, TCG_CALL_NO_RWG, void, ptr, cptr, i32) +DEF_HELPER_FLAGS_3(gvec_vistr16, TCG_CALL_NO_RWG, void, ptr, cptr, i32) +DEF_HELPER_FLAGS_3(gvec_vistr32, TCG_CALL_NO_RWG, void, ptr, cptr, i32) +DEF_HELPER_4(gvec_vistr_cc8, void, ptr, cptr, env, i32) +DEF_HELPER_4(gvec_vistr_cc16, void, ptr, cptr, env, i32) +DEF_HELPER_4(gvec_vistr_cc32, void, ptr, cptr, env, i32) +DEF_HELPER_FLAGS_5(gvec_vstrc8, TCG_CALL_NO_RWG, void, ptr, cptr, cptr, cptr, i32) +DEF_HELPER_FLAGS_5(gvec_vstrc16, TCG_CALL_NO_RWG, void, ptr, cptr, cptr, cptr, i32) +DEF_HELPER_FLAGS_5(gvec_vstrc32, TCG_CALL_NO_RWG, void, ptr, cptr, cptr, cptr, i32) +DEF_HELPER_FLAGS_5(gvec_vstrc_rt8, TCG_CALL_NO_RWG, void, ptr, cptr, cptr, cptr, i32) +DEF_HELPER_FLAGS_5(gvec_vstrc_rt16, TCG_CALL_NO_RWG, void, ptr, cptr, cptr, cptr, i32) +DEF_HELPER_FLAGS_5(gvec_vstrc_rt32, TCG_CALL_NO_RWG, void, ptr, cptr, cptr, cptr, i32) +DEF_HELPER_6(gvec_vstrc_cc8, void, ptr, cptr, cptr, cptr, env, i32) +DEF_HELPER_6(gvec_vstrc_cc16, void, ptr, cptr, cptr, cptr, env, i32) +DEF_HELPER_6(gvec_vstrc_cc32, void, ptr, cptr, cptr, cptr, env, i32) +DEF_HELPER_6(gvec_vstrc_cc_rt8, void, ptr, cptr, cptr, cptr, env, i32) +DEF_HELPER_6(gvec_vstrc_cc_rt16, void, ptr, cptr, cptr, cptr, env, i32) +DEF_HELPER_6(gvec_vstrc_cc_rt32, void, ptr, cptr, cptr, cptr, env, i32) + +/* === Vector Floating-Point Instructions */ +DEF_HELPER_FLAGS_5(gvec_vfa64, TCG_CALL_NO_WG, void, ptr, cptr, cptr, env, i32) +DEF_HELPER_FLAGS_5(gvec_vfa64s, TCG_CALL_NO_WG, void, ptr, cptr, cptr, env, i32) +DEF_HELPER_4(gvec_wfc64, void, cptr, cptr, env, i32) +DEF_HELPER_4(gvec_wfk64, void, cptr, cptr, env, i32) +DEF_HELPER_FLAGS_5(gvec_vfce64, TCG_CALL_NO_WG, void, ptr, cptr, cptr, env, i32) +DEF_HELPER_FLAGS_5(gvec_vfce64s, TCG_CALL_NO_WG, void, ptr, cptr, cptr, env, i32) +DEF_HELPER_5(gvec_vfce64_cc, void, ptr, cptr, cptr, env, i32) +DEF_HELPER_5(gvec_vfce64s_cc, void, ptr, cptr, cptr, env, i32) +DEF_HELPER_FLAGS_5(gvec_vfch64, TCG_CALL_NO_WG, void, ptr, cptr, cptr, env, i32) +DEF_HELPER_FLAGS_5(gvec_vfch64s, TCG_CALL_NO_WG, void, ptr, cptr, cptr, env, i32) +DEF_HELPER_5(gvec_vfch64_cc, void, ptr, cptr, cptr, env, i32) +DEF_HELPER_5(gvec_vfch64s_cc, void, ptr, cptr, cptr, env, i32) +DEF_HELPER_FLAGS_5(gvec_vfche64, TCG_CALL_NO_WG, void, ptr, cptr, cptr, env, i32) +DEF_HELPER_FLAGS_5(gvec_vfche64s, TCG_CALL_NO_WG, void, ptr, cptr, cptr, env, i32) +DEF_HELPER_5(gvec_vfche64_cc, void, ptr, cptr, cptr, env, i32) +DEF_HELPER_5(gvec_vfche64s_cc, void, ptr, cptr, cptr, env, i32) +DEF_HELPER_FLAGS_4(gvec_vcdg64, TCG_CALL_NO_WG, void, ptr, cptr, env, i32) +DEF_HELPER_FLAGS_4(gvec_vcdg64s, TCG_CALL_NO_WG, void, ptr, cptr, env, i32) +DEF_HELPER_FLAGS_4(gvec_vcdlg64, TCG_CALL_NO_WG, void, ptr, cptr, env, i32) +DEF_HELPER_FLAGS_4(gvec_vcdlg64s, TCG_CALL_NO_WG, void, ptr, cptr, env, i32) +DEF_HELPER_FLAGS_4(gvec_vcgd64, TCG_CALL_NO_WG, void, ptr, cptr, env, i32) +DEF_HELPER_FLAGS_4(gvec_vcgd64s, TCG_CALL_NO_WG, void, ptr, cptr, env, i32) +DEF_HELPER_FLAGS_4(gvec_vclgd64, TCG_CALL_NO_WG, void, ptr, cptr, env, i32) +DEF_HELPER_FLAGS_4(gvec_vclgd64s, TCG_CALL_NO_WG, void, ptr, cptr, env, i32) +DEF_HELPER_FLAGS_5(gvec_vfd64, TCG_CALL_NO_WG, void, ptr, cptr, cptr, env, i32) +DEF_HELPER_FLAGS_5(gvec_vfd64s, TCG_CALL_NO_WG, void, ptr, cptr, cptr, env, i32) +DEF_HELPER_FLAGS_4(gvec_vfi64, TCG_CALL_NO_WG, void, ptr, cptr, env, i32) +DEF_HELPER_FLAGS_4(gvec_vfi64s, TCG_CALL_NO_WG, void, ptr, cptr, env, i32) +DEF_HELPER_FLAGS_4(gvec_vfll32, TCG_CALL_NO_WG, void, ptr, cptr, env, i32) +DEF_HELPER_FLAGS_4(gvec_vfll32s, TCG_CALL_NO_WG, void, ptr, cptr, env, i32) +DEF_HELPER_FLAGS_4(gvec_vflr64, TCG_CALL_NO_WG, void, ptr, cptr, env, i32) +DEF_HELPER_FLAGS_4(gvec_vflr64s, TCG_CALL_NO_WG, void, ptr, cptr, env, i32) +DEF_HELPER_FLAGS_5(gvec_vfm64, TCG_CALL_NO_WG, void, ptr, cptr, cptr, env, i32) +DEF_HELPER_FLAGS_5(gvec_vfm64s, TCG_CALL_NO_WG, void, ptr, cptr, cptr, env, i32) +DEF_HELPER_FLAGS_6(gvec_vfma64, TCG_CALL_NO_WG, void, ptr, cptr, cptr, cptr, env, i32) +DEF_HELPER_FLAGS_6(gvec_vfma64s, TCG_CALL_NO_WG, void, ptr, cptr, cptr, cptr, env, i32) +DEF_HELPER_FLAGS_6(gvec_vfms64, TCG_CALL_NO_WG, void, ptr, cptr, cptr, cptr, env, i32) +DEF_HELPER_FLAGS_6(gvec_vfms64s, TCG_CALL_NO_WG, void, ptr, cptr, cptr, cptr, env, i32) +DEF_HELPER_FLAGS_4(gvec_vfsq64, TCG_CALL_NO_WG, void, ptr, cptr, env, i32) +DEF_HELPER_FLAGS_4(gvec_vfsq64s, TCG_CALL_NO_WG, void, ptr, cptr, env, i32) +DEF_HELPER_FLAGS_5(gvec_vfs64, TCG_CALL_NO_WG, void, ptr, cptr, cptr, env, i32) +DEF_HELPER_FLAGS_5(gvec_vfs64s, TCG_CALL_NO_WG, void, ptr, cptr, cptr, env, i32) +DEF_HELPER_4(gvec_vftci64, void, ptr, cptr, env, i32) +DEF_HELPER_4(gvec_vftci64s, void, ptr, cptr, env, i32) + #ifndef CONFIG_USER_ONLY DEF_HELPER_3(servc, i32, env, i64, i64) DEF_HELPER_4(diag, void, env, i32, i32, i32) diff --git a/target/s390x/insn-data.def b/target/s390x/insn-data.def index e61475bdc4..f421184fcd 100644 --- a/target/s390x/insn-data.def +++ b/target/s390x/insn-data.def @@ -1191,6 +1191,64 @@ /* VECTOR TEST UNDER MASK */ F(0xe7d8, VTM, VRR_a, V, 0, 0, 0, 0, vtm, 0, IF_VEC) +/* === Vector String Instructions === */ + +/* VECTOR FIND ANY ELEMENT EQUAL */ + F(0xe782, VFAE, VRR_b, V, 0, 0, 0, 0, vfae, 0, IF_VEC) +/* VECTOR FIND ELEMENT EQUAL */ + F(0xe780, VFEE, VRR_b, V, 0, 0, 0, 0, vfee, 0, IF_VEC) +/* VECTOR FIND ELEMENT NOT EQUAL */ + F(0xe781, VFENE, VRR_b, V, 0, 0, 0, 0, vfene, 0, IF_VEC) +/* VECTOR ISOLATE STRING */ + F(0xe75c, VISTR, VRR_a, V, 0, 0, 0, 0, vistr, 0, IF_VEC) +/* VECTOR STRING RANGE COMPARE */ + F(0xe78a, VSTRC, VRR_d, V, 0, 0, 0, 0, vstrc, 0, IF_VEC) + +/* === Vector Floating-Point Instructions */ + +/* VECTOR FP ADD */ + F(0xe7e3, VFA, VRR_c, V, 0, 0, 0, 0, vfa, 0, IF_VEC) +/* VECTOR FP COMPARE SCALAR */ + F(0xe7cb, WFC, VRR_a, V, 0, 0, 0, 0, wfc, 0, IF_VEC) +/* VECTOR FP COMPARE AND SIGNAL SCALAR */ + F(0xe7ca, WFK, VRR_a, V, 0, 0, 0, 0, wfc, 0, IF_VEC) +/* VECTOR FP COMPARE EQUAL */ + F(0xe7e8, VFCE, VRR_c, V, 0, 0, 0, 0, vfc, 0, IF_VEC) +/* VECTOR FP COMPARE HIGH */ + F(0xe7eb, VFCH, VRR_c, V, 0, 0, 0, 0, vfc, 0, IF_VEC) +/* VECTOR FP COMPARE HIGH OR EQUAL */ + F(0xe7ea, VFCHE, VRR_c, V, 0, 0, 0, 0, vfc, 0, IF_VEC) +/* VECTOR FP CONVERT FROM FIXED 64-BIT */ + F(0xe7c3, VCDG, VRR_a, V, 0, 0, 0, 0, vcdg, 0, IF_VEC) +/* VECTOR FP CONVERT FROM LOGICAL 64-BIT */ + F(0xe7c1, VCDLG, VRR_a, V, 0, 0, 0, 0, vcdg, 0, IF_VEC) +/* VECTOR FP CONVERT TO FIXED 64-BIT */ + F(0xe7c2, VCGD, VRR_a, V, 0, 0, 0, 0, vcdg, 0, IF_VEC) +/* VECTOR FP CONVERT TO LOGICAL 64-BIT */ + F(0xe7c0, VCLGD, VRR_a, V, 0, 0, 0, 0, vcdg, 0, IF_VEC) +/* VECTOR FP DIVIDE */ + F(0xe7e5, VFD, VRR_c, V, 0, 0, 0, 0, vfa, 0, IF_VEC) +/* VECTOR LOAD FP INTEGER */ + F(0xe7c7, VFI, VRR_a, V, 0, 0, 0, 0, vcdg, 0, IF_VEC) +/* VECTOR LOAD LENGTHENED */ + F(0xe7c4, VFLL, VRR_a, V, 0, 0, 0, 0, vfll, 0, IF_VEC) +/* VECTOR LOAD ROUNDED */ + F(0xe7c5, VFLR, VRR_a, V, 0, 0, 0, 0, vcdg, 0, IF_VEC) +/* VECTOR FP MULTIPLY */ + F(0xe7e7, VFM, VRR_c, V, 0, 0, 0, 0, vfa, 0, IF_VEC) +/* VECTOR FP MULTIPLY AND ADD */ + F(0xe78f, VFMA, VRR_e, V, 0, 0, 0, 0, vfma, 0, IF_VEC) +/* VECTOR FP MULTIPLY AND SUBTRACT */ + F(0xe78e, VFMS, VRR_e, V, 0, 0, 0, 0, vfma, 0, IF_VEC) +/* VECTOR FP PERFORM SIGN OPERATION */ + F(0xe7cc, VFPSO, VRR_a, V, 0, 0, 0, 0, vfpso, 0, IF_VEC) +/* VECTOR FP SQUARE ROOT */ + F(0xe7ce, VFSQ, VRR_a, V, 0, 0, 0, 0, vfsq, 0, IF_VEC) +/* VECTOR FP SUBTRACT */ + F(0xe7e2, VFS, VRR_c, V, 0, 0, 0, 0, vfa, 0, IF_VEC) +/* VECTOR FP TEST DATA CLASS IMMEDIATE */ + F(0xe74a, VFTCI, VRI_e, V, 0, 0, 0, 0, vftci, 0, IF_VEC) + #ifndef CONFIG_USER_ONLY /* COMPARE AND SWAP AND PURGE */ E(0xb250, CSP, RRE, Z, r1_32u, ra2, r1_P, 0, csp, 0, MO_TEUL, IF_PRIV) diff --git a/target/s390x/internal.h b/target/s390x/internal.h index 9893fc094b..c243fa725b 100644 --- a/target/s390x/internal.h +++ b/target/s390x/internal.h @@ -285,6 +285,10 @@ uint32_t set_cc_nz_f128(float128 v); uint8_t s390_softfloat_exc_to_ieee(unsigned int exc); int s390_swap_bfp_rounding_mode(CPUS390XState *env, int m3); void s390_restore_bfp_rounding_mode(CPUS390XState *env, int old_mode); +int float_comp_to_cc(CPUS390XState *env, int float_compare); +uint16_t float32_dcmask(CPUS390XState *env, float32 f1); +uint16_t float64_dcmask(CPUS390XState *env, float64 f1); +uint16_t float128_dcmask(CPUS390XState *env, float128 f1); /* gdbstub.c */ diff --git a/target/s390x/kvm.c b/target/s390x/kvm.c index e5e2b691f2..bcec9795ec 100644 --- a/target/s390x/kvm.c +++ b/target/s390x/kvm.c @@ -418,21 +418,21 @@ int kvm_arch_put_registers(CPUState *cs, int level) if (can_sync_regs(cs, KVM_SYNC_VRS)) { for (i = 0; i < 32; i++) { - cs->kvm_run->s.regs.vrs[i][0] = env->vregs[i][0].ll; - cs->kvm_run->s.regs.vrs[i][1] = env->vregs[i][1].ll; + cs->kvm_run->s.regs.vrs[i][0] = env->vregs[i][0]; + cs->kvm_run->s.regs.vrs[i][1] = env->vregs[i][1]; } cs->kvm_run->s.regs.fpc = env->fpc; cs->kvm_run->kvm_dirty_regs |= KVM_SYNC_VRS; } else if (can_sync_regs(cs, KVM_SYNC_FPRS)) { for (i = 0; i < 16; i++) { - cs->kvm_run->s.regs.fprs[i] = get_freg(env, i)->ll; + cs->kvm_run->s.regs.fprs[i] = *get_freg(env, i); } cs->kvm_run->s.regs.fpc = env->fpc; cs->kvm_run->kvm_dirty_regs |= KVM_SYNC_FPRS; } else { /* Floating point */ for (i = 0; i < 16; i++) { - fpu.fprs[i] = get_freg(env, i)->ll; + fpu.fprs[i] = *get_freg(env, i); } fpu.fpc = env->fpc; @@ -586,13 +586,13 @@ int kvm_arch_get_registers(CPUState *cs) /* Floating point and vector registers */ if (can_sync_regs(cs, KVM_SYNC_VRS)) { for (i = 0; i < 32; i++) { - env->vregs[i][0].ll = cs->kvm_run->s.regs.vrs[i][0]; - env->vregs[i][1].ll = cs->kvm_run->s.regs.vrs[i][1]; + env->vregs[i][0] = cs->kvm_run->s.regs.vrs[i][0]; + env->vregs[i][1] = cs->kvm_run->s.regs.vrs[i][1]; } env->fpc = cs->kvm_run->s.regs.fpc; } else if (can_sync_regs(cs, KVM_SYNC_FPRS)) { for (i = 0; i < 16; i++) { - get_freg(env, i)->ll = cs->kvm_run->s.regs.fprs[i]; + *get_freg(env, i) = cs->kvm_run->s.regs.fprs[i]; } env->fpc = cs->kvm_run->s.regs.fpc; } else { @@ -601,7 +601,7 @@ int kvm_arch_get_registers(CPUState *cs) return r; } for (i = 0; i < 16; i++) { - get_freg(env, i)->ll = fpu.fprs[i]; + *get_freg(env, i) = fpu.fprs[i]; } env->fpc = fpu.fpc; } diff --git a/target/s390x/machine.c b/target/s390x/machine.c index cb792aa103..e6851a57bc 100644 --- a/target/s390x/machine.c +++ b/target/s390x/machine.c @@ -66,22 +66,22 @@ static const VMStateDescription vmstate_fpu = { .minimum_version_id = 1, .needed = fpu_needed, .fields = (VMStateField[]) { - VMSTATE_UINT64(env.vregs[0][0].ll, S390CPU), - VMSTATE_UINT64(env.vregs[1][0].ll, S390CPU), - VMSTATE_UINT64(env.vregs[2][0].ll, S390CPU), - VMSTATE_UINT64(env.vregs[3][0].ll, S390CPU), - VMSTATE_UINT64(env.vregs[4][0].ll, S390CPU), - VMSTATE_UINT64(env.vregs[5][0].ll, S390CPU), - VMSTATE_UINT64(env.vregs[6][0].ll, S390CPU), - VMSTATE_UINT64(env.vregs[7][0].ll, S390CPU), - VMSTATE_UINT64(env.vregs[8][0].ll, S390CPU), - VMSTATE_UINT64(env.vregs[9][0].ll, S390CPU), - VMSTATE_UINT64(env.vregs[10][0].ll, S390CPU), - VMSTATE_UINT64(env.vregs[11][0].ll, S390CPU), - VMSTATE_UINT64(env.vregs[12][0].ll, S390CPU), - VMSTATE_UINT64(env.vregs[13][0].ll, S390CPU), - VMSTATE_UINT64(env.vregs[14][0].ll, S390CPU), - VMSTATE_UINT64(env.vregs[15][0].ll, S390CPU), + VMSTATE_UINT64(env.vregs[0][0], S390CPU), + VMSTATE_UINT64(env.vregs[1][0], S390CPU), + VMSTATE_UINT64(env.vregs[2][0], S390CPU), + VMSTATE_UINT64(env.vregs[3][0], S390CPU), + VMSTATE_UINT64(env.vregs[4][0], S390CPU), + VMSTATE_UINT64(env.vregs[5][0], S390CPU), + VMSTATE_UINT64(env.vregs[6][0], S390CPU), + VMSTATE_UINT64(env.vregs[7][0], S390CPU), + VMSTATE_UINT64(env.vregs[8][0], S390CPU), + VMSTATE_UINT64(env.vregs[9][0], S390CPU), + VMSTATE_UINT64(env.vregs[10][0], S390CPU), + VMSTATE_UINT64(env.vregs[11][0], S390CPU), + VMSTATE_UINT64(env.vregs[12][0], S390CPU), + VMSTATE_UINT64(env.vregs[13][0], S390CPU), + VMSTATE_UINT64(env.vregs[14][0], S390CPU), + VMSTATE_UINT64(env.vregs[15][0], S390CPU), VMSTATE_UINT32(env.fpc, S390CPU), VMSTATE_END_OF_LIST() } @@ -99,54 +99,54 @@ static const VMStateDescription vmstate_vregs = { .needed = vregs_needed, .fields = (VMStateField[]) { /* vregs[0][0] -> vregs[15][0] and fregs are overlays */ - VMSTATE_UINT64(env.vregs[16][0].ll, S390CPU), - VMSTATE_UINT64(env.vregs[17][0].ll, S390CPU), - VMSTATE_UINT64(env.vregs[18][0].ll, S390CPU), - VMSTATE_UINT64(env.vregs[19][0].ll, S390CPU), - VMSTATE_UINT64(env.vregs[20][0].ll, S390CPU), - VMSTATE_UINT64(env.vregs[21][0].ll, S390CPU), - VMSTATE_UINT64(env.vregs[22][0].ll, S390CPU), - VMSTATE_UINT64(env.vregs[23][0].ll, S390CPU), - VMSTATE_UINT64(env.vregs[24][0].ll, S390CPU), - VMSTATE_UINT64(env.vregs[25][0].ll, S390CPU), - VMSTATE_UINT64(env.vregs[26][0].ll, S390CPU), - VMSTATE_UINT64(env.vregs[27][0].ll, S390CPU), - VMSTATE_UINT64(env.vregs[28][0].ll, S390CPU), - VMSTATE_UINT64(env.vregs[29][0].ll, S390CPU), - VMSTATE_UINT64(env.vregs[30][0].ll, S390CPU), - VMSTATE_UINT64(env.vregs[31][0].ll, S390CPU), - VMSTATE_UINT64(env.vregs[0][1].ll, S390CPU), - VMSTATE_UINT64(env.vregs[1][1].ll, S390CPU), - VMSTATE_UINT64(env.vregs[2][1].ll, S390CPU), - VMSTATE_UINT64(env.vregs[3][1].ll, S390CPU), - VMSTATE_UINT64(env.vregs[4][1].ll, S390CPU), - VMSTATE_UINT64(env.vregs[5][1].ll, S390CPU), - VMSTATE_UINT64(env.vregs[6][1].ll, S390CPU), - VMSTATE_UINT64(env.vregs[7][1].ll, S390CPU), - VMSTATE_UINT64(env.vregs[8][1].ll, S390CPU), - VMSTATE_UINT64(env.vregs[9][1].ll, S390CPU), - VMSTATE_UINT64(env.vregs[10][1].ll, S390CPU), - VMSTATE_UINT64(env.vregs[11][1].ll, S390CPU), - VMSTATE_UINT64(env.vregs[12][1].ll, S390CPU), - VMSTATE_UINT64(env.vregs[13][1].ll, S390CPU), - VMSTATE_UINT64(env.vregs[14][1].ll, S390CPU), - VMSTATE_UINT64(env.vregs[15][1].ll, S390CPU), - VMSTATE_UINT64(env.vregs[16][1].ll, S390CPU), - VMSTATE_UINT64(env.vregs[17][1].ll, S390CPU), - VMSTATE_UINT64(env.vregs[18][1].ll, S390CPU), - VMSTATE_UINT64(env.vregs[19][1].ll, S390CPU), - VMSTATE_UINT64(env.vregs[20][1].ll, S390CPU), - VMSTATE_UINT64(env.vregs[21][1].ll, S390CPU), - VMSTATE_UINT64(env.vregs[22][1].ll, S390CPU), - VMSTATE_UINT64(env.vregs[23][1].ll, S390CPU), - VMSTATE_UINT64(env.vregs[24][1].ll, S390CPU), - VMSTATE_UINT64(env.vregs[25][1].ll, S390CPU), - VMSTATE_UINT64(env.vregs[26][1].ll, S390CPU), - VMSTATE_UINT64(env.vregs[27][1].ll, S390CPU), - VMSTATE_UINT64(env.vregs[28][1].ll, S390CPU), - VMSTATE_UINT64(env.vregs[29][1].ll, S390CPU), - VMSTATE_UINT64(env.vregs[30][1].ll, S390CPU), - VMSTATE_UINT64(env.vregs[31][1].ll, S390CPU), + VMSTATE_UINT64(env.vregs[16][0], S390CPU), + VMSTATE_UINT64(env.vregs[17][0], S390CPU), + VMSTATE_UINT64(env.vregs[18][0], S390CPU), + VMSTATE_UINT64(env.vregs[19][0], S390CPU), + VMSTATE_UINT64(env.vregs[20][0], S390CPU), + VMSTATE_UINT64(env.vregs[21][0], S390CPU), + VMSTATE_UINT64(env.vregs[22][0], S390CPU), + VMSTATE_UINT64(env.vregs[23][0], S390CPU), + VMSTATE_UINT64(env.vregs[24][0], S390CPU), + VMSTATE_UINT64(env.vregs[25][0], S390CPU), + VMSTATE_UINT64(env.vregs[26][0], S390CPU), + VMSTATE_UINT64(env.vregs[27][0], S390CPU), + VMSTATE_UINT64(env.vregs[28][0], S390CPU), + VMSTATE_UINT64(env.vregs[29][0], S390CPU), + VMSTATE_UINT64(env.vregs[30][0], S390CPU), + VMSTATE_UINT64(env.vregs[31][0], S390CPU), + VMSTATE_UINT64(env.vregs[0][1], S390CPU), + VMSTATE_UINT64(env.vregs[1][1], S390CPU), + VMSTATE_UINT64(env.vregs[2][1], S390CPU), + VMSTATE_UINT64(env.vregs[3][1], S390CPU), + VMSTATE_UINT64(env.vregs[4][1], S390CPU), + VMSTATE_UINT64(env.vregs[5][1], S390CPU), + VMSTATE_UINT64(env.vregs[6][1], S390CPU), + VMSTATE_UINT64(env.vregs[7][1], S390CPU), + VMSTATE_UINT64(env.vregs[8][1], S390CPU), + VMSTATE_UINT64(env.vregs[9][1], S390CPU), + VMSTATE_UINT64(env.vregs[10][1], S390CPU), + VMSTATE_UINT64(env.vregs[11][1], S390CPU), + VMSTATE_UINT64(env.vregs[12][1], S390CPU), + VMSTATE_UINT64(env.vregs[13][1], S390CPU), + VMSTATE_UINT64(env.vregs[14][1], S390CPU), + VMSTATE_UINT64(env.vregs[15][1], S390CPU), + VMSTATE_UINT64(env.vregs[16][1], S390CPU), + VMSTATE_UINT64(env.vregs[17][1], S390CPU), + VMSTATE_UINT64(env.vregs[18][1], S390CPU), + VMSTATE_UINT64(env.vregs[19][1], S390CPU), + VMSTATE_UINT64(env.vregs[20][1], S390CPU), + VMSTATE_UINT64(env.vregs[21][1], S390CPU), + VMSTATE_UINT64(env.vregs[22][1], S390CPU), + VMSTATE_UINT64(env.vregs[23][1], S390CPU), + VMSTATE_UINT64(env.vregs[24][1], S390CPU), + VMSTATE_UINT64(env.vregs[25][1], S390CPU), + VMSTATE_UINT64(env.vregs[26][1], S390CPU), + VMSTATE_UINT64(env.vregs[27][1], S390CPU), + VMSTATE_UINT64(env.vregs[28][1], S390CPU), + VMSTATE_UINT64(env.vregs[29][1], S390CPU), + VMSTATE_UINT64(env.vregs[30][1], S390CPU), + VMSTATE_UINT64(env.vregs[31][1], S390CPU), VMSTATE_END_OF_LIST() } }; diff --git a/target/s390x/misc_helper.c b/target/s390x/misc_helper.c index ee67c1fa0c..10aa617cf9 100644 --- a/target/s390x/misc_helper.c +++ b/target/s390x/misc_helper.c @@ -669,7 +669,7 @@ uint32_t HELPER(stfle)(CPUS390XState *env, uint64_t addr) { const uintptr_t ra = GETPC(); const int count_bytes = ((env->regs[0] & 0xff) + 1) * 8; - const int max_bytes = ROUND_UP(used_stfl_bytes, 8); + int max_bytes; int i; if (addr & 0x7) { @@ -677,7 +677,14 @@ uint32_t HELPER(stfle)(CPUS390XState *env, uint64_t addr) } prepare_stfl(); - for (i = 0; i < count_bytes; ++i) { + max_bytes = ROUND_UP(used_stfl_bytes, 8); + + /* + * The PoP says that doublewords beyond the highest-numbered facility + * bit may or may not be stored. However, existing hardware appears to + * not store the words, and existing software depend on that. + */ + for (i = 0; i < MIN(count_bytes, max_bytes); ++i) { cpu_stb_data_ra(env, addr + i, stfl_bytes[i], ra); } diff --git a/target/s390x/tcg_s390x.h b/target/s390x/tcg_s390x.h index ab2c4ba703..2813f9d48e 100644 --- a/target/s390x/tcg_s390x.h +++ b/target/s390x/tcg_s390x.h @@ -18,5 +18,7 @@ void QEMU_NORETURN tcg_s390_program_interrupt(CPUS390XState *env, uint32_t code, int ilen, uintptr_t ra); void QEMU_NORETURN tcg_s390_data_exception(CPUS390XState *env, uint32_t dxc, uintptr_t ra); +void QEMU_NORETURN tcg_s390_vector_exception(CPUS390XState *env, uint32_t vxc, + uintptr_t ra); #endif /* TCG_S390X_H */ diff --git a/target/s390x/translate.c b/target/s390x/translate.c index fa57b7550e..ac0d8b6410 100644 --- a/target/s390x/translate.c +++ b/target/s390x/translate.c @@ -149,7 +149,7 @@ void s390x_translate_init(void) static inline int vec_full_reg_offset(uint8_t reg) { g_assert(reg < 32); - return offsetof(CPUS390XState, vregs[reg][0].d); + return offsetof(CPUS390XState, vregs[reg][0]); } static inline int vec_reg_offset(uint8_t reg, uint8_t enr, TCGMemOp es) diff --git a/target/s390x/translate_vx.inc.c b/target/s390x/translate_vx.inc.c index 7e0bfcb190..7b1d31cba5 100644 --- a/target/s390x/translate_vx.inc.c +++ b/target/s390x/translate_vx.inc.c @@ -52,6 +52,11 @@ #define ES_64 MO_64 #define ES_128 4 +/* Floating-Point Format */ +#define FPF_SHORT 2 +#define FPF_LONG 3 +#define FPF_EXT 4 + static inline bool valid_vec_element(uint8_t enr, TCGMemOp es) { return !(enr & ~(NUM_VEC_ELEMENTS(es) - 1)); @@ -188,6 +193,9 @@ static void get_vec_element_ptr_i64(TCGv_ptr ptr, uint8_t reg, TCGv_i64 enr, #define gen_gvec_2s(v1, v2, c, gen) \ tcg_gen_gvec_2s(vec_full_reg_offset(v1), vec_full_reg_offset(v2), \ 16, 16, c, gen) +#define gen_gvec_2_ool(v1, v2, data, fn) \ + tcg_gen_gvec_2_ool(vec_full_reg_offset(v1), vec_full_reg_offset(v2), \ + 16, 16, data, fn) #define gen_gvec_2i_ool(v1, v2, c, data, fn) \ tcg_gen_gvec_2i_ool(vec_full_reg_offset(v1), vec_full_reg_offset(v2), \ c, 16, 16, data, fn) @@ -214,6 +222,10 @@ static void get_vec_element_ptr_i64(TCGv_ptr ptr, uint8_t reg, TCGv_i64 enr, tcg_gen_gvec_4_ool(vec_full_reg_offset(v1), vec_full_reg_offset(v2), \ vec_full_reg_offset(v3), vec_full_reg_offset(v4), \ 16, 16, data, fn) +#define gen_gvec_4_ptr(v1, v2, v3, v4, ptr, data, fn) \ + tcg_gen_gvec_4_ptr(vec_full_reg_offset(v1), vec_full_reg_offset(v2), \ + vec_full_reg_offset(v3), vec_full_reg_offset(v4), \ + ptr, 16, 16, data, fn) #define gen_gvec_dup_i64(es, v1, c) \ tcg_gen_gvec_dup_i64(es, vec_full_reg_offset(v1), 16, 16, c) #define gen_gvec_mov(v1, v2) \ @@ -233,6 +245,9 @@ static void get_vec_element_ptr_i64(TCGv_ptr ptr, uint8_t reg, TCGv_i64 enr, #define gen_gvec_fn_3(fn, es, v1, v2, v3) \ tcg_gen_gvec_##fn(es, vec_full_reg_offset(v1), vec_full_reg_offset(v2), \ vec_full_reg_offset(v3), 16, 16) +#define gen_gvec_fn_4(fn, es, v1, v2, v3, v4) \ + tcg_gen_gvec_##fn(es, vec_full_reg_offset(v1), vec_full_reg_offset(v2), \ + vec_full_reg_offset(v3), vec_full_reg_offset(v4), 16, 16) /* * Helper to carry out a 128 bit vector computation using 2 i64 values per @@ -903,40 +918,11 @@ static DisasJumpType op_vsce(DisasContext *s, DisasOps *o) return DISAS_NEXT; } -static void gen_sel_i64(TCGv_i64 d, TCGv_i64 a, TCGv_i64 b, TCGv_i64 c) -{ - TCGv_i64 t = tcg_temp_new_i64(); - - /* bit in c not set -> copy bit from b */ - tcg_gen_andc_i64(t, b, c); - /* bit in c set -> copy bit from a */ - tcg_gen_and_i64(d, a, c); - /* merge the results */ - tcg_gen_or_i64(d, d, t); - tcg_temp_free_i64(t); -} - -static void gen_sel_vec(unsigned vece, TCGv_vec d, TCGv_vec a, TCGv_vec b, - TCGv_vec c) -{ - TCGv_vec t = tcg_temp_new_vec_matching(d); - - tcg_gen_andc_vec(vece, t, b, c); - tcg_gen_and_vec(vece, d, a, c); - tcg_gen_or_vec(vece, d, d, t); - tcg_temp_free_vec(t); -} - static DisasJumpType op_vsel(DisasContext *s, DisasOps *o) { - static const GVecGen4 gvec_op = { - .fni8 = gen_sel_i64, - .fniv = gen_sel_vec, - .prefer_i64 = TCG_TARGET_REG_BITS == 64, - }; - - gen_gvec_4(get_field(s->fields, v1), get_field(s->fields, v2), - get_field(s->fields, v3), get_field(s->fields, v4), &gvec_op); + gen_gvec_fn_4(bitsel, ES_8, get_field(s->fields, v1), + get_field(s->fields, v4), get_field(s->fields, v2), + get_field(s->fields, v3)); return DISAS_NEXT; } @@ -2353,3 +2339,460 @@ static DisasJumpType op_vtm(DisasContext *s, DisasOps *o) set_cc_static(s); return DISAS_NEXT; } + +static DisasJumpType op_vfae(DisasContext *s, DisasOps *o) +{ + const uint8_t es = get_field(s->fields, m4); + const uint8_t m5 = get_field(s->fields, m5); + static gen_helper_gvec_3 * const g[3] = { + gen_helper_gvec_vfae8, + gen_helper_gvec_vfae16, + gen_helper_gvec_vfae32, + }; + static gen_helper_gvec_3_ptr * const g_cc[3] = { + gen_helper_gvec_vfae_cc8, + gen_helper_gvec_vfae_cc16, + gen_helper_gvec_vfae_cc32, + }; + if (es > ES_32) { + gen_program_exception(s, PGM_SPECIFICATION); + return DISAS_NORETURN; + } + + if (extract32(m5, 0, 1)) { + gen_gvec_3_ptr(get_field(s->fields, v1), get_field(s->fields, v2), + get_field(s->fields, v3), cpu_env, m5, g_cc[es]); + set_cc_static(s); + } else { + gen_gvec_3_ool(get_field(s->fields, v1), get_field(s->fields, v2), + get_field(s->fields, v3), m5, g[es]); + } + return DISAS_NEXT; +} + +static DisasJumpType op_vfee(DisasContext *s, DisasOps *o) +{ + const uint8_t es = get_field(s->fields, m4); + const uint8_t m5 = get_field(s->fields, m5); + static gen_helper_gvec_3 * const g[3] = { + gen_helper_gvec_vfee8, + gen_helper_gvec_vfee16, + gen_helper_gvec_vfee32, + }; + static gen_helper_gvec_3_ptr * const g_cc[3] = { + gen_helper_gvec_vfee_cc8, + gen_helper_gvec_vfee_cc16, + gen_helper_gvec_vfee_cc32, + }; + + if (es > ES_32 || m5 & ~0x3) { + gen_program_exception(s, PGM_SPECIFICATION); + return DISAS_NORETURN; + } + + if (extract32(m5, 0, 1)) { + gen_gvec_3_ptr(get_field(s->fields, v1), get_field(s->fields, v2), + get_field(s->fields, v3), cpu_env, m5, g_cc[es]); + set_cc_static(s); + } else { + gen_gvec_3_ool(get_field(s->fields, v1), get_field(s->fields, v2), + get_field(s->fields, v3), m5, g[es]); + } + return DISAS_NEXT; +} + +static DisasJumpType op_vfene(DisasContext *s, DisasOps *o) +{ + const uint8_t es = get_field(s->fields, m4); + const uint8_t m5 = get_field(s->fields, m5); + static gen_helper_gvec_3 * const g[3] = { + gen_helper_gvec_vfene8, + gen_helper_gvec_vfene16, + gen_helper_gvec_vfene32, + }; + static gen_helper_gvec_3_ptr * const g_cc[3] = { + gen_helper_gvec_vfene_cc8, + gen_helper_gvec_vfene_cc16, + gen_helper_gvec_vfene_cc32, + }; + + if (es > ES_32 || m5 & ~0x3) { + gen_program_exception(s, PGM_SPECIFICATION); + return DISAS_NORETURN; + } + + if (extract32(m5, 0, 1)) { + gen_gvec_3_ptr(get_field(s->fields, v1), get_field(s->fields, v2), + get_field(s->fields, v3), cpu_env, m5, g_cc[es]); + set_cc_static(s); + } else { + gen_gvec_3_ool(get_field(s->fields, v1), get_field(s->fields, v2), + get_field(s->fields, v3), m5, g[es]); + } + return DISAS_NEXT; +} + +static DisasJumpType op_vistr(DisasContext *s, DisasOps *o) +{ + const uint8_t es = get_field(s->fields, m4); + const uint8_t m5 = get_field(s->fields, m5); + static gen_helper_gvec_2 * const g[3] = { + gen_helper_gvec_vistr8, + gen_helper_gvec_vistr16, + gen_helper_gvec_vistr32, + }; + static gen_helper_gvec_2_ptr * const g_cc[3] = { + gen_helper_gvec_vistr_cc8, + gen_helper_gvec_vistr_cc16, + gen_helper_gvec_vistr_cc32, + }; + + if (es > ES_32 || m5 & ~0x1) { + gen_program_exception(s, PGM_SPECIFICATION); + return DISAS_NORETURN; + } + + if (extract32(m5, 0, 1)) { + gen_gvec_2_ptr(get_field(s->fields, v1), get_field(s->fields, v2), + cpu_env, 0, g_cc[es]); + set_cc_static(s); + } else { + gen_gvec_2_ool(get_field(s->fields, v1), get_field(s->fields, v2), 0, + g[es]); + } + return DISAS_NEXT; +} + +static DisasJumpType op_vstrc(DisasContext *s, DisasOps *o) +{ + const uint8_t es = get_field(s->fields, m5); + const uint8_t m6 = get_field(s->fields, m6); + static gen_helper_gvec_4 * const g[3] = { + gen_helper_gvec_vstrc8, + gen_helper_gvec_vstrc16, + gen_helper_gvec_vstrc32, + }; + static gen_helper_gvec_4 * const g_rt[3] = { + gen_helper_gvec_vstrc_rt8, + gen_helper_gvec_vstrc_rt16, + gen_helper_gvec_vstrc_rt32, + }; + static gen_helper_gvec_4_ptr * const g_cc[3] = { + gen_helper_gvec_vstrc_cc8, + gen_helper_gvec_vstrc_cc16, + gen_helper_gvec_vstrc_cc32, + }; + static gen_helper_gvec_4_ptr * const g_cc_rt[3] = { + gen_helper_gvec_vstrc_cc_rt8, + gen_helper_gvec_vstrc_cc_rt16, + gen_helper_gvec_vstrc_cc_rt32, + }; + + if (es > ES_32) { + gen_program_exception(s, PGM_SPECIFICATION); + return DISAS_NORETURN; + } + + if (extract32(m6, 0, 1)) { + if (extract32(m6, 2, 1)) { + gen_gvec_4_ptr(get_field(s->fields, v1), get_field(s->fields, v2), + get_field(s->fields, v3), get_field(s->fields, v4), + cpu_env, m6, g_cc_rt[es]); + } else { + gen_gvec_4_ptr(get_field(s->fields, v1), get_field(s->fields, v2), + get_field(s->fields, v3), get_field(s->fields, v4), + cpu_env, m6, g_cc[es]); + } + set_cc_static(s); + } else { + if (extract32(m6, 2, 1)) { + gen_gvec_4_ool(get_field(s->fields, v1), get_field(s->fields, v2), + get_field(s->fields, v3), get_field(s->fields, v4), + m6, g_rt[es]); + } else { + gen_gvec_4_ool(get_field(s->fields, v1), get_field(s->fields, v2), + get_field(s->fields, v3), get_field(s->fields, v4), + m6, g[es]); + } + } + return DISAS_NEXT; +} + +static DisasJumpType op_vfa(DisasContext *s, DisasOps *o) +{ + const uint8_t fpf = get_field(s->fields, m4); + const uint8_t m5 = get_field(s->fields, m5); + const bool se = extract32(m5, 3, 1); + gen_helper_gvec_3_ptr *fn; + + if (fpf != FPF_LONG || extract32(m5, 0, 3)) { + gen_program_exception(s, PGM_SPECIFICATION); + return DISAS_NORETURN; + } + + switch (s->fields->op2) { + case 0xe3: + fn = se ? gen_helper_gvec_vfa64s : gen_helper_gvec_vfa64; + break; + case 0xe5: + fn = se ? gen_helper_gvec_vfd64s : gen_helper_gvec_vfd64; + break; + case 0xe7: + fn = se ? gen_helper_gvec_vfm64s : gen_helper_gvec_vfm64; + break; + case 0xe2: + fn = se ? gen_helper_gvec_vfs64s : gen_helper_gvec_vfs64; + break; + default: + g_assert_not_reached(); + } + gen_gvec_3_ptr(get_field(s->fields, v1), get_field(s->fields, v2), + get_field(s->fields, v3), cpu_env, 0, fn); + return DISAS_NEXT; +} + +static DisasJumpType op_wfc(DisasContext *s, DisasOps *o) +{ + const uint8_t fpf = get_field(s->fields, m3); + const uint8_t m4 = get_field(s->fields, m4); + + if (fpf != FPF_LONG || m4) { + gen_program_exception(s, PGM_SPECIFICATION); + return DISAS_NORETURN; + } + + if (s->fields->op2 == 0xcb) { + gen_gvec_2_ptr(get_field(s->fields, v1), get_field(s->fields, v2), + cpu_env, 0, gen_helper_gvec_wfc64); + } else { + gen_gvec_2_ptr(get_field(s->fields, v1), get_field(s->fields, v2), + cpu_env, 0, gen_helper_gvec_wfk64); + } + set_cc_static(s); + return DISAS_NEXT; +} + +static DisasJumpType op_vfc(DisasContext *s, DisasOps *o) +{ + const uint8_t fpf = get_field(s->fields, m4); + const uint8_t m5 = get_field(s->fields, m5); + const uint8_t m6 = get_field(s->fields, m6); + const bool se = extract32(m5, 3, 1); + const bool cs = extract32(m6, 0, 1); + gen_helper_gvec_3_ptr *fn; + + if (fpf != FPF_LONG || extract32(m5, 0, 3) || extract32(m6, 1, 3)) { + gen_program_exception(s, PGM_SPECIFICATION); + return DISAS_NORETURN; + } + + if (cs) { + switch (s->fields->op2) { + case 0xe8: + fn = se ? gen_helper_gvec_vfce64s_cc : gen_helper_gvec_vfce64_cc; + break; + case 0xeb: + fn = se ? gen_helper_gvec_vfch64s_cc : gen_helper_gvec_vfch64_cc; + break; + case 0xea: + fn = se ? gen_helper_gvec_vfche64s_cc : gen_helper_gvec_vfche64_cc; + break; + default: + g_assert_not_reached(); + } + } else { + switch (s->fields->op2) { + case 0xe8: + fn = se ? gen_helper_gvec_vfce64s : gen_helper_gvec_vfce64; + break; + case 0xeb: + fn = se ? gen_helper_gvec_vfch64s : gen_helper_gvec_vfch64; + break; + case 0xea: + fn = se ? gen_helper_gvec_vfche64s : gen_helper_gvec_vfche64; + break; + default: + g_assert_not_reached(); + } + } + gen_gvec_3_ptr(get_field(s->fields, v1), get_field(s->fields, v2), + get_field(s->fields, v3), cpu_env, 0, fn); + if (cs) { + set_cc_static(s); + } + return DISAS_NEXT; +} + +static DisasJumpType op_vcdg(DisasContext *s, DisasOps *o) +{ + const uint8_t fpf = get_field(s->fields, m3); + const uint8_t m4 = get_field(s->fields, m4); + const uint8_t erm = get_field(s->fields, m5); + const bool se = extract32(m4, 3, 1); + gen_helper_gvec_2_ptr *fn; + + if (fpf != FPF_LONG || extract32(m4, 0, 2) || erm > 7 || erm == 2) { + gen_program_exception(s, PGM_SPECIFICATION); + return DISAS_NORETURN; + } + + switch (s->fields->op2) { + case 0xc3: + fn = se ? gen_helper_gvec_vcdg64s : gen_helper_gvec_vcdg64; + break; + case 0xc1: + fn = se ? gen_helper_gvec_vcdlg64s : gen_helper_gvec_vcdlg64; + break; + case 0xc2: + fn = se ? gen_helper_gvec_vcgd64s : gen_helper_gvec_vcgd64; + break; + case 0xc0: + fn = se ? gen_helper_gvec_vclgd64s : gen_helper_gvec_vclgd64; + break; + case 0xc7: + fn = se ? gen_helper_gvec_vfi64s : gen_helper_gvec_vfi64; + break; + case 0xc5: + fn = se ? gen_helper_gvec_vflr64s : gen_helper_gvec_vflr64; + break; + default: + g_assert_not_reached(); + } + gen_gvec_2_ptr(get_field(s->fields, v1), get_field(s->fields, v2), cpu_env, + deposit32(m4, 4, 4, erm), fn); + return DISAS_NEXT; +} + +static DisasJumpType op_vfll(DisasContext *s, DisasOps *o) +{ + const uint8_t fpf = get_field(s->fields, m3); + const uint8_t m4 = get_field(s->fields, m4); + gen_helper_gvec_2_ptr *fn = gen_helper_gvec_vfll32; + + if (fpf != FPF_SHORT || extract32(m4, 0, 3)) { + gen_program_exception(s, PGM_SPECIFICATION); + return DISAS_NORETURN; + } + + if (extract32(m4, 3, 1)) { + fn = gen_helper_gvec_vfll32s; + } + gen_gvec_2_ptr(get_field(s->fields, v1), get_field(s->fields, v2), cpu_env, + 0, fn); + return DISAS_NEXT; +} + +static DisasJumpType op_vfma(DisasContext *s, DisasOps *o) +{ + const uint8_t m5 = get_field(s->fields, m5); + const uint8_t fpf = get_field(s->fields, m6); + const bool se = extract32(m5, 3, 1); + gen_helper_gvec_4_ptr *fn; + + if (fpf != FPF_LONG || extract32(m5, 0, 3)) { + gen_program_exception(s, PGM_SPECIFICATION); + return DISAS_NORETURN; + } + + if (s->fields->op2 == 0x8f) { + fn = se ? gen_helper_gvec_vfma64s : gen_helper_gvec_vfma64; + } else { + fn = se ? gen_helper_gvec_vfms64s : gen_helper_gvec_vfms64; + } + gen_gvec_4_ptr(get_field(s->fields, v1), get_field(s->fields, v2), + get_field(s->fields, v3), get_field(s->fields, v4), cpu_env, + 0, fn); + return DISAS_NEXT; +} + +static DisasJumpType op_vfpso(DisasContext *s, DisasOps *o) +{ + const uint8_t v1 = get_field(s->fields, v1); + const uint8_t v2 = get_field(s->fields, v2); + const uint8_t fpf = get_field(s->fields, m3); + const uint8_t m4 = get_field(s->fields, m4); + const uint8_t m5 = get_field(s->fields, m5); + TCGv_i64 tmp; + + if (fpf != FPF_LONG || extract32(m4, 0, 3) || m5 > 2) { + gen_program_exception(s, PGM_SPECIFICATION); + return DISAS_NORETURN; + } + + if (extract32(m4, 3, 1)) { + tmp = tcg_temp_new_i64(); + read_vec_element_i64(tmp, v2, 0, ES_64); + switch (m5) { + case 0: + /* sign bit is inverted (complement) */ + tcg_gen_xori_i64(tmp, tmp, 1ull << 63); + break; + case 1: + /* sign bit is set to one (negative) */ + tcg_gen_ori_i64(tmp, tmp, 1ull << 63); + break; + case 2: + /* sign bit is set to zero (positive) */ + tcg_gen_andi_i64(tmp, tmp, (1ull << 63) - 1); + break; + } + write_vec_element_i64(tmp, v1, 0, ES_64); + tcg_temp_free_i64(tmp); + } else { + switch (m5) { + case 0: + /* sign bit is inverted (complement) */ + gen_gvec_fn_2i(xori, ES_64, v1, v2, 1ull << 63); + break; + case 1: + /* sign bit is set to one (negative) */ + gen_gvec_fn_2i(ori, ES_64, v1, v2, 1ull << 63); + break; + case 2: + /* sign bit is set to zero (positive) */ + gen_gvec_fn_2i(andi, ES_64, v1, v2, (1ull << 63) - 1); + break; + } + } + return DISAS_NEXT; +} + +static DisasJumpType op_vfsq(DisasContext *s, DisasOps *o) +{ + const uint8_t fpf = get_field(s->fields, m3); + const uint8_t m4 = get_field(s->fields, m4); + gen_helper_gvec_2_ptr *fn = gen_helper_gvec_vfsq64; + + if (fpf != FPF_LONG || extract32(m4, 0, 3)) { + gen_program_exception(s, PGM_SPECIFICATION); + return DISAS_NORETURN; + } + + if (extract32(m4, 3, 1)) { + fn = gen_helper_gvec_vfsq64s; + } + gen_gvec_2_ptr(get_field(s->fields, v1), get_field(s->fields, v2), cpu_env, + 0, fn); + return DISAS_NEXT; +} + +static DisasJumpType op_vftci(DisasContext *s, DisasOps *o) +{ + const uint16_t i3 = get_field(s->fields, i3); + const uint8_t fpf = get_field(s->fields, m4); + const uint8_t m5 = get_field(s->fields, m5); + gen_helper_gvec_2_ptr *fn = gen_helper_gvec_vftci64; + + if (fpf != FPF_LONG || extract32(m5, 0, 3)) { + gen_program_exception(s, PGM_SPECIFICATION); + return DISAS_NORETURN; + } + + if (extract32(m5, 3, 1)) { + fn = gen_helper_gvec_vftci64s; + } + gen_gvec_2_ptr(get_field(s->fields, v1), get_field(s->fields, v2), cpu_env, + i3, fn); + set_cc_static(s); + return DISAS_NEXT; +} diff --git a/target/s390x/vec.h b/target/s390x/vec.h index 3313fb43ee..a6e361869b 100644 --- a/target/s390x/vec.h +++ b/target/s390x/vec.h @@ -12,6 +12,8 @@ #ifndef S390X_VEC_H #define S390X_VEC_H +#include "tcg/tcg.h" + typedef union S390Vector { uint64_t doubleword[2]; uint32_t word[4]; @@ -70,6 +72,23 @@ static inline uint64_t s390_vec_read_element64(const S390Vector *v, uint8_t enr) return v->doubleword[enr]; } +static inline uint64_t s390_vec_read_element(const S390Vector *v, uint8_t enr, + uint8_t es) +{ + switch (es) { + case MO_8: + return s390_vec_read_element8(v, enr); + case MO_16: + return s390_vec_read_element16(v, enr); + case MO_32: + return s390_vec_read_element32(v, enr); + case MO_64: + return s390_vec_read_element64(v, enr); + default: + g_assert_not_reached(); + } +} + static inline void s390_vec_write_element8(S390Vector *v, uint8_t enr, uint8_t data) { @@ -98,4 +117,25 @@ static inline void s390_vec_write_element64(S390Vector *v, uint8_t enr, v->doubleword[enr] = data; } +static inline void s390_vec_write_element(S390Vector *v, uint8_t enr, + uint8_t es, uint64_t data) +{ + switch (es) { + case MO_8: + s390_vec_write_element8(v, enr, data); + break; + case MO_16: + s390_vec_write_element16(v, enr, data); + break; + case MO_32: + s390_vec_write_element32(v, enr, data); + break; + case MO_64: + s390_vec_write_element64(v, enr, data); + break; + default: + g_assert_not_reached(); + } +} + #endif /* S390X_VEC_H */ diff --git a/target/s390x/vec_fpu_helper.c b/target/s390x/vec_fpu_helper.c new file mode 100644 index 0000000000..a48bd704bc --- /dev/null +++ b/target/s390x/vec_fpu_helper.c @@ -0,0 +1,625 @@ +/* + * QEMU TCG support -- s390x vector floating point instruction support + * + * Copyright (C) 2019 Red Hat Inc + * + * Authors: + * David Hildenbrand <david@redhat.com> + * + * This work is licensed under the terms of the GNU GPL, version 2 or later. + * See the COPYING file in the top-level directory. + */ +#include "qemu/osdep.h" +#include "qemu-common.h" +#include "cpu.h" +#include "internal.h" +#include "vec.h" +#include "tcg_s390x.h" +#include "tcg/tcg-gvec-desc.h" +#include "exec/exec-all.h" +#include "exec/helper-proto.h" +#include "fpu/softfloat.h" + +#define VIC_INVALID 0x1 +#define VIC_DIVBYZERO 0x2 +#define VIC_OVERFLOW 0x3 +#define VIC_UNDERFLOW 0x4 +#define VIC_INEXACT 0x5 + +/* returns the VEX. If the VEX is 0, there is no trap */ +static uint8_t check_ieee_exc(CPUS390XState *env, uint8_t enr, bool XxC, + uint8_t *vec_exc) +{ + uint8_t vece_exc = 0, trap_exc; + unsigned qemu_exc; + + /* Retrieve and clear the softfloat exceptions */ + qemu_exc = env->fpu_status.float_exception_flags; + if (qemu_exc == 0) { + return 0; + } + env->fpu_status.float_exception_flags = 0; + + vece_exc = s390_softfloat_exc_to_ieee(qemu_exc); + + /* Add them to the vector-wide s390x exception bits */ + *vec_exc |= vece_exc; + + /* Check for traps and construct the VXC */ + trap_exc = vece_exc & env->fpc >> 24; + if (trap_exc) { + if (trap_exc & S390_IEEE_MASK_INVALID) { + return enr << 4 | VIC_INVALID; + } else if (trap_exc & S390_IEEE_MASK_DIVBYZERO) { + return enr << 4 | VIC_DIVBYZERO; + } else if (trap_exc & S390_IEEE_MASK_OVERFLOW) { + return enr << 4 | VIC_OVERFLOW; + } else if (trap_exc & S390_IEEE_MASK_UNDERFLOW) { + return enr << 4 | VIC_UNDERFLOW; + } else if (!XxC) { + g_assert(trap_exc & S390_IEEE_MASK_INEXACT); + /* inexact has lowest priority on traps */ + return enr << 4 | VIC_INEXACT; + } + } + return 0; +} + +static void handle_ieee_exc(CPUS390XState *env, uint8_t vxc, uint8_t vec_exc, + uintptr_t retaddr) +{ + if (vxc) { + /* on traps, the fpc flags are not updated, instruction is suppressed */ + tcg_s390_vector_exception(env, vxc, retaddr); + } + if (vec_exc) { + /* indicate exceptions for all elements combined */ + env->fpc |= vec_exc << 16; + } +} + +typedef uint64_t (*vop64_2_fn)(uint64_t a, float_status *s); +static void vop64_2(S390Vector *v1, const S390Vector *v2, CPUS390XState *env, + bool s, bool XxC, uint8_t erm, vop64_2_fn fn, + uintptr_t retaddr) +{ + uint8_t vxc, vec_exc = 0; + S390Vector tmp = {}; + int i, old_mode; + + old_mode = s390_swap_bfp_rounding_mode(env, erm); + for (i = 0; i < 2; i++) { + const uint64_t a = s390_vec_read_element64(v2, i); + + s390_vec_write_element64(&tmp, i, fn(a, &env->fpu_status)); + vxc = check_ieee_exc(env, i, XxC, &vec_exc); + if (s || vxc) { + break; + } + } + s390_restore_bfp_rounding_mode(env, old_mode); + handle_ieee_exc(env, vxc, vec_exc, retaddr); + *v1 = tmp; +} + +typedef uint64_t (*vop64_3_fn)(uint64_t a, uint64_t b, float_status *s); +static void vop64_3(S390Vector *v1, const S390Vector *v2, const S390Vector *v3, + CPUS390XState *env, bool s, vop64_3_fn fn, + uintptr_t retaddr) +{ + uint8_t vxc, vec_exc = 0; + S390Vector tmp = {}; + int i; + + for (i = 0; i < 2; i++) { + const uint64_t a = s390_vec_read_element64(v2, i); + const uint64_t b = s390_vec_read_element64(v3, i); + + s390_vec_write_element64(&tmp, i, fn(a, b, &env->fpu_status)); + vxc = check_ieee_exc(env, i, false, &vec_exc); + if (s || vxc) { + break; + } + } + handle_ieee_exc(env, vxc, vec_exc, retaddr); + *v1 = tmp; +} + +static uint64_t vfa64(uint64_t a, uint64_t b, float_status *s) +{ + return float64_add(a, b, s); +} + +void HELPER(gvec_vfa64)(void *v1, const void *v2, const void *v3, + CPUS390XState *env, uint32_t desc) +{ + vop64_3(v1, v2, v3, env, false, vfa64, GETPC()); +} + +void HELPER(gvec_vfa64s)(void *v1, const void *v2, const void *v3, + CPUS390XState *env, uint32_t desc) +{ + vop64_3(v1, v2, v3, env, true, vfa64, GETPC()); +} + +static int wfc64(const S390Vector *v1, const S390Vector *v2, + CPUS390XState *env, bool signal, uintptr_t retaddr) +{ + /* only the zero-indexed elements are compared */ + const float64 a = s390_vec_read_element64(v1, 0); + const float64 b = s390_vec_read_element64(v2, 0); + uint8_t vxc, vec_exc = 0; + int cmp; + + if (signal) { + cmp = float64_compare(a, b, &env->fpu_status); + } else { + cmp = float64_compare_quiet(a, b, &env->fpu_status); + } + vxc = check_ieee_exc(env, 0, false, &vec_exc); + handle_ieee_exc(env, vxc, vec_exc, retaddr); + + return float_comp_to_cc(env, cmp); +} + +void HELPER(gvec_wfc64)(const void *v1, const void *v2, CPUS390XState *env, + uint32_t desc) +{ + env->cc_op = wfc64(v1, v2, env, false, GETPC()); +} + +void HELPER(gvec_wfk64)(const void *v1, const void *v2, CPUS390XState *env, + uint32_t desc) +{ + env->cc_op = wfc64(v1, v2, env, true, GETPC()); +} + +typedef int (*vfc64_fn)(float64 a, float64 b, float_status *status); +static int vfc64(S390Vector *v1, const S390Vector *v2, const S390Vector *v3, + CPUS390XState *env, bool s, vfc64_fn fn, uintptr_t retaddr) +{ + uint8_t vxc, vec_exc = 0; + S390Vector tmp = {}; + int match = 0; + int i; + + for (i = 0; i < 2; i++) { + const float64 a = s390_vec_read_element64(v2, i); + const float64 b = s390_vec_read_element64(v3, i); + + /* swap the order of the parameters, so we can use existing functions */ + if (fn(b, a, &env->fpu_status)) { + match++; + s390_vec_write_element64(&tmp, i, -1ull); + } + vxc = check_ieee_exc(env, i, false, &vec_exc); + if (s || vxc) { + break; + } + } + + handle_ieee_exc(env, vxc, vec_exc, retaddr); + *v1 = tmp; + if (match) { + return s || match == 2 ? 0 : 1; + } + return 3; +} + +void HELPER(gvec_vfce64)(void *v1, const void *v2, const void *v3, + CPUS390XState *env, uint32_t desc) +{ + vfc64(v1, v2, v3, env, false, float64_eq_quiet, GETPC()); +} + +void HELPER(gvec_vfce64s)(void *v1, const void *v2, const void *v3, + CPUS390XState *env, uint32_t desc) +{ + vfc64(v1, v2, v3, env, true, float64_eq_quiet, GETPC()); +} + +void HELPER(gvec_vfce64_cc)(void *v1, const void *v2, const void *v3, + CPUS390XState *env, uint32_t desc) +{ + env->cc_op = vfc64(v1, v2, v3, env, false, float64_eq_quiet, GETPC()); +} + +void HELPER(gvec_vfce64s_cc)(void *v1, const void *v2, const void *v3, + CPUS390XState *env, uint32_t desc) +{ + env->cc_op = vfc64(v1, v2, v3, env, true, float64_eq_quiet, GETPC()); +} + +void HELPER(gvec_vfch64)(void *v1, const void *v2, const void *v3, + CPUS390XState *env, uint32_t desc) +{ + vfc64(v1, v2, v3, env, false, float64_lt_quiet, GETPC()); +} + +void HELPER(gvec_vfch64s)(void *v1, const void *v2, const void *v3, + CPUS390XState *env, uint32_t desc) +{ + vfc64(v1, v2, v3, env, true, float64_lt_quiet, GETPC()); +} + +void HELPER(gvec_vfch64_cc)(void *v1, const void *v2, const void *v3, + CPUS390XState *env, uint32_t desc) +{ + env->cc_op = vfc64(v1, v2, v3, env, false, float64_lt_quiet, GETPC()); +} + +void HELPER(gvec_vfch64s_cc)(void *v1, const void *v2, const void *v3, + CPUS390XState *env, uint32_t desc) +{ + env->cc_op = vfc64(v1, v2, v3, env, true, float64_lt_quiet, GETPC()); +} + +void HELPER(gvec_vfche64)(void *v1, const void *v2, const void *v3, + CPUS390XState *env, uint32_t desc) +{ + vfc64(v1, v2, v3, env, false, float64_le_quiet, GETPC()); +} + +void HELPER(gvec_vfche64s)(void *v1, const void *v2, const void *v3, + CPUS390XState *env, uint32_t desc) +{ + vfc64(v1, v2, v3, env, true, float64_le_quiet, GETPC()); +} + +void HELPER(gvec_vfche64_cc)(void *v1, const void *v2, const void *v3, + CPUS390XState *env, uint32_t desc) +{ + env->cc_op = vfc64(v1, v2, v3, env, false, float64_le_quiet, GETPC()); +} + +void HELPER(gvec_vfche64s_cc)(void *v1, const void *v2, const void *v3, + CPUS390XState *env, uint32_t desc) +{ + env->cc_op = vfc64(v1, v2, v3, env, true, float64_le_quiet, GETPC()); +} + +static uint64_t vcdg64(uint64_t a, float_status *s) +{ + return int64_to_float64(a, s); +} + +void HELPER(gvec_vcdg64)(void *v1, const void *v2, CPUS390XState *env, + uint32_t desc) +{ + const uint8_t erm = extract32(simd_data(desc), 4, 4); + const bool XxC = extract32(simd_data(desc), 2, 1); + + vop64_2(v1, v2, env, false, XxC, erm, vcdg64, GETPC()); +} + +void HELPER(gvec_vcdg64s)(void *v1, const void *v2, CPUS390XState *env, + uint32_t desc) +{ + const uint8_t erm = extract32(simd_data(desc), 4, 4); + const bool XxC = extract32(simd_data(desc), 2, 1); + + vop64_2(v1, v2, env, true, XxC, erm, vcdg64, GETPC()); +} + +static uint64_t vcdlg64(uint64_t a, float_status *s) +{ + return uint64_to_float64(a, s); +} + +void HELPER(gvec_vcdlg64)(void *v1, const void *v2, CPUS390XState *env, + uint32_t desc) +{ + const uint8_t erm = extract32(simd_data(desc), 4, 4); + const bool XxC = extract32(simd_data(desc), 2, 1); + + vop64_2(v1, v2, env, false, XxC, erm, vcdlg64, GETPC()); +} + +void HELPER(gvec_vcdlg64s)(void *v1, const void *v2, CPUS390XState *env, + uint32_t desc) +{ + const uint8_t erm = extract32(simd_data(desc), 4, 4); + const bool XxC = extract32(simd_data(desc), 2, 1); + + vop64_2(v1, v2, env, true, XxC, erm, vcdlg64, GETPC()); +} + +static uint64_t vcgd64(uint64_t a, float_status *s) +{ + return float64_to_int64(a, s); +} + +void HELPER(gvec_vcgd64)(void *v1, const void *v2, CPUS390XState *env, + uint32_t desc) +{ + const uint8_t erm = extract32(simd_data(desc), 4, 4); + const bool XxC = extract32(simd_data(desc), 2, 1); + + vop64_2(v1, v2, env, false, XxC, erm, vcgd64, GETPC()); +} + +void HELPER(gvec_vcgd64s)(void *v1, const void *v2, CPUS390XState *env, + uint32_t desc) +{ + const uint8_t erm = extract32(simd_data(desc), 4, 4); + const bool XxC = extract32(simd_data(desc), 2, 1); + + vop64_2(v1, v2, env, true, XxC, erm, vcgd64, GETPC()); +} + +static uint64_t vclgd64(uint64_t a, float_status *s) +{ + return float64_to_uint64(a, s); +} + +void HELPER(gvec_vclgd64)(void *v1, const void *v2, CPUS390XState *env, + uint32_t desc) +{ + const uint8_t erm = extract32(simd_data(desc), 4, 4); + const bool XxC = extract32(simd_data(desc), 2, 1); + + vop64_2(v1, v2, env, false, XxC, erm, vclgd64, GETPC()); +} + +void HELPER(gvec_vclgd64s)(void *v1, const void *v2, CPUS390XState *env, + uint32_t desc) +{ + const uint8_t erm = extract32(simd_data(desc), 4, 4); + const bool XxC = extract32(simd_data(desc), 2, 1); + + vop64_2(v1, v2, env, true, XxC, erm, vclgd64, GETPC()); +} + +static uint64_t vfd64(uint64_t a, uint64_t b, float_status *s) +{ + return float64_div(a, b, s); +} + +void HELPER(gvec_vfd64)(void *v1, const void *v2, const void *v3, + CPUS390XState *env, uint32_t desc) +{ + vop64_3(v1, v2, v3, env, false, vfd64, GETPC()); +} + +void HELPER(gvec_vfd64s)(void *v1, const void *v2, const void *v3, + CPUS390XState *env, uint32_t desc) +{ + vop64_3(v1, v2, v3, env, true, vfd64, GETPC()); +} + +static uint64_t vfi64(uint64_t a, float_status *s) +{ + return float64_round_to_int(a, s); +} + +void HELPER(gvec_vfi64)(void *v1, const void *v2, CPUS390XState *env, + uint32_t desc) +{ + const uint8_t erm = extract32(simd_data(desc), 4, 4); + const bool XxC = extract32(simd_data(desc), 2, 1); + + vop64_2(v1, v2, env, false, XxC, erm, vfi64, GETPC()); +} + +void HELPER(gvec_vfi64s)(void *v1, const void *v2, CPUS390XState *env, + uint32_t desc) +{ + const uint8_t erm = extract32(simd_data(desc), 4, 4); + const bool XxC = extract32(simd_data(desc), 2, 1); + + vop64_2(v1, v2, env, true, XxC, erm, vfi64, GETPC()); +} + +static void vfll32(S390Vector *v1, const S390Vector *v2, CPUS390XState *env, + bool s, uintptr_t retaddr) +{ + uint8_t vxc, vec_exc = 0; + S390Vector tmp = {}; + int i; + + for (i = 0; i < 2; i++) { + /* load from even element */ + const float32 a = s390_vec_read_element32(v2, i * 2); + const uint64_t ret = float32_to_float64(a, &env->fpu_status); + + s390_vec_write_element64(&tmp, i, ret); + /* indicate the source element */ + vxc = check_ieee_exc(env, i * 2, false, &vec_exc); + if (s || vxc) { + break; + } + } + handle_ieee_exc(env, vxc, vec_exc, retaddr); + *v1 = tmp; +} + +void HELPER(gvec_vfll32)(void *v1, const void *v2, CPUS390XState *env, + uint32_t desc) +{ + vfll32(v1, v2, env, false, GETPC()); +} + +void HELPER(gvec_vfll32s)(void *v1, const void *v2, CPUS390XState *env, + uint32_t desc) +{ + vfll32(v1, v2, env, true, GETPC()); +} + +static void vflr64(S390Vector *v1, const S390Vector *v2, CPUS390XState *env, + bool s, bool XxC, uint8_t erm, uintptr_t retaddr) +{ + uint8_t vxc, vec_exc = 0; + S390Vector tmp = {}; + int i, old_mode; + + old_mode = s390_swap_bfp_rounding_mode(env, erm); + for (i = 0; i < 2; i++) { + float64 a = s390_vec_read_element64(v2, i); + uint32_t ret = float64_to_float32(a, &env->fpu_status); + + /* place at even element */ + s390_vec_write_element32(&tmp, i * 2, ret); + /* indicate the source element */ + vxc = check_ieee_exc(env, i, XxC, &vec_exc); + if (s || vxc) { + break; + } + } + s390_restore_bfp_rounding_mode(env, old_mode); + handle_ieee_exc(env, vxc, vec_exc, retaddr); + *v1 = tmp; +} + +void HELPER(gvec_vflr64)(void *v1, const void *v2, CPUS390XState *env, + uint32_t desc) +{ + const uint8_t erm = extract32(simd_data(desc), 4, 4); + const bool XxC = extract32(simd_data(desc), 2, 1); + + vflr64(v1, v2, env, false, XxC, erm, GETPC()); +} + +void HELPER(gvec_vflr64s)(void *v1, const void *v2, CPUS390XState *env, + uint32_t desc) +{ + const uint8_t erm = extract32(simd_data(desc), 4, 4); + const bool XxC = extract32(simd_data(desc), 2, 1); + + vflr64(v1, v2, env, true, XxC, erm, GETPC()); +} + +static uint64_t vfm64(uint64_t a, uint64_t b, float_status *s) +{ + return float64_mul(a, b, s); +} + +void HELPER(gvec_vfm64)(void *v1, const void *v2, const void *v3, + CPUS390XState *env, uint32_t desc) +{ + vop64_3(v1, v2, v3, env, false, vfm64, GETPC()); +} + +void HELPER(gvec_vfm64s)(void *v1, const void *v2, const void *v3, + CPUS390XState *env, uint32_t desc) +{ + vop64_3(v1, v2, v3, env, true, vfm64, GETPC()); +} + +static void vfma64(S390Vector *v1, const S390Vector *v2, const S390Vector *v3, + const S390Vector *v4, CPUS390XState *env, bool s, int flags, + uintptr_t retaddr) +{ + uint8_t vxc, vec_exc = 0; + S390Vector tmp = {}; + int i; + + for (i = 0; i < 2; i++) { + const uint64_t a = s390_vec_read_element64(v2, i); + const uint64_t b = s390_vec_read_element64(v3, i); + const uint64_t c = s390_vec_read_element64(v4, i); + uint64_t ret = float64_muladd(a, b, c, flags, &env->fpu_status); + + s390_vec_write_element64(&tmp, i, ret); + vxc = check_ieee_exc(env, i, false, &vec_exc); + if (s || vxc) { + break; + } + } + handle_ieee_exc(env, vxc, vec_exc, retaddr); + *v1 = tmp; +} + +void HELPER(gvec_vfma64)(void *v1, const void *v2, const void *v3, + const void *v4, CPUS390XState *env, uint32_t desc) +{ + vfma64(v1, v2, v3, v4, env, false, 0, GETPC()); +} + +void HELPER(gvec_vfma64s)(void *v1, const void *v2, const void *v3, + const void *v4, CPUS390XState *env, uint32_t desc) +{ + vfma64(v1, v2, v3, v4, env, true, 0, GETPC()); +} + +void HELPER(gvec_vfms64)(void *v1, const void *v2, const void *v3, + const void *v4, CPUS390XState *env, uint32_t desc) +{ + vfma64(v1, v2, v3, v4, env, false, float_muladd_negate_c, GETPC()); +} + +void HELPER(gvec_vfms64s)(void *v1, const void *v2, const void *v3, + const void *v4, CPUS390XState *env, uint32_t desc) +{ + vfma64(v1, v2, v3, v4, env, true, float_muladd_negate_c, GETPC()); +} + +static uint64_t vfsq64(uint64_t a, float_status *s) +{ + return float64_sqrt(a, s); +} + +void HELPER(gvec_vfsq64)(void *v1, const void *v2, CPUS390XState *env, + uint32_t desc) +{ + vop64_2(v1, v2, env, false, false, 0, vfsq64, GETPC()); +} + +void HELPER(gvec_vfsq64s)(void *v1, const void *v2, CPUS390XState *env, + uint32_t desc) +{ + vop64_2(v1, v2, env, true, false, 0, vfsq64, GETPC()); +} + +static uint64_t vfs64(uint64_t a, uint64_t b, float_status *s) +{ + return float64_sub(a, b, s); +} + +void HELPER(gvec_vfs64)(void *v1, const void *v2, const void *v3, + CPUS390XState *env, uint32_t desc) +{ + vop64_3(v1, v2, v3, env, false, vfs64, GETPC()); +} + +void HELPER(gvec_vfs64s)(void *v1, const void *v2, const void *v3, + CPUS390XState *env, uint32_t desc) +{ + vop64_3(v1, v2, v3, env, true, vfs64, GETPC()); +} + +static int vftci64(S390Vector *v1, const S390Vector *v2, CPUS390XState *env, + bool s, uint16_t i3) +{ + int i, match = 0; + + for (i = 0; i < 2; i++) { + float64 a = s390_vec_read_element64(v2, i); + + if (float64_dcmask(env, a) & i3) { + match++; + s390_vec_write_element64(v1, i, -1ull); + } else { + s390_vec_write_element64(v1, i, 0); + } + if (s) { + break; + } + } + + if (match) { + return s || match == 2 ? 0 : 1; + } + return 3; +} + +void HELPER(gvec_vftci64)(void *v1, const void *v2, CPUS390XState *env, + uint32_t desc) +{ + env->cc_op = vftci64(v1, v2, env, false, simd_data(desc)); +} + +void HELPER(gvec_vftci64s)(void *v1, const void *v2, CPUS390XState *env, + uint32_t desc) +{ + env->cc_op = vftci64(v1, v2, env, true, simd_data(desc)); +} diff --git a/target/s390x/vec_string_helper.c b/target/s390x/vec_string_helper.c new file mode 100644 index 0000000000..c516c0ceeb --- /dev/null +++ b/target/s390x/vec_string_helper.c @@ -0,0 +1,473 @@ +/* + * QEMU TCG support -- s390x vector string instruction support + * + * Copyright (C) 2019 Red Hat Inc + * + * Authors: + * David Hildenbrand <david@redhat.com> + * + * This work is licensed under the terms of the GNU GPL, version 2 or later. + * See the COPYING file in the top-level directory. + */ +#include "qemu/osdep.h" +#include "qemu-common.h" +#include "cpu.h" +#include "internal.h" +#include "vec.h" +#include "tcg/tcg.h" +#include "tcg/tcg-gvec-desc.h" +#include "exec/helper-proto.h" + +/* + * Returns a bit set in the MSB of each element that is zero, + * as defined by the mask. + */ +static inline uint64_t zero_search(uint64_t a, uint64_t mask) +{ + return ~(((a & mask) + mask) | a | mask); +} + +/* + * Returns a bit set in the MSB of each element that is not zero, + * as defined by the mask. + */ +static inline uint64_t nonzero_search(uint64_t a, uint64_t mask) +{ + return (((a & mask) + mask) | a) & ~mask; +} + +/* + * Returns the byte offset for the first match, or 16 for no match. + */ +static inline int match_index(uint64_t c0, uint64_t c1) +{ + return (c0 ? clz64(c0) : clz64(c1) + 64) >> 3; +} + +/* + * Returns the number of bits composing one element. + */ +static uint8_t get_element_bits(uint8_t es) +{ + return (1 << es) * BITS_PER_BYTE; +} + +/* + * Returns the bitmask for a single element. + */ +static uint64_t get_single_element_mask(uint8_t es) +{ + return -1ull >> (64 - get_element_bits(es)); +} + +/* + * Returns the bitmask for a single element (excluding the MSB). + */ +static uint64_t get_single_element_lsbs_mask(uint8_t es) +{ + return -1ull >> (65 - get_element_bits(es)); +} + +/* + * Returns the bitmasks for multiple elements (excluding the MSBs). + */ +static uint64_t get_element_lsbs_mask(uint8_t es) +{ + return dup_const(es, get_single_element_lsbs_mask(es)); +} + +static int vfae(void *v1, const void *v2, const void *v3, bool in, + bool rt, bool zs, uint8_t es) +{ + const uint64_t mask = get_element_lsbs_mask(es); + const int bits = get_element_bits(es); + uint64_t a0, a1, b0, b1, e0, e1, t0, t1, z0, z1; + uint64_t first_zero = 16; + uint64_t first_equal; + int i; + + a0 = s390_vec_read_element64(v2, 0); + a1 = s390_vec_read_element64(v2, 1); + b0 = s390_vec_read_element64(v3, 0); + b1 = s390_vec_read_element64(v3, 1); + e0 = 0; + e1 = 0; + /* compare against equality with every other element */ + for (i = 0; i < 64; i += bits) { + t0 = rol64(b0, i); + t1 = rol64(b1, i); + e0 |= zero_search(a0 ^ t0, mask); + e0 |= zero_search(a0 ^ t1, mask); + e1 |= zero_search(a1 ^ t0, mask); + e1 |= zero_search(a1 ^ t1, mask); + } + /* invert the result if requested - invert only the MSBs */ + if (in) { + e0 = ~e0 & ~mask; + e1 = ~e1 & ~mask; + } + first_equal = match_index(e0, e1); + + if (zs) { + z0 = zero_search(a0, mask); + z1 = zero_search(a1, mask); + first_zero = match_index(z0, z1); + } + + if (rt) { + e0 = (e0 >> (bits - 1)) * get_single_element_mask(es); + e1 = (e1 >> (bits - 1)) * get_single_element_mask(es); + s390_vec_write_element64(v1, 0, e0); + s390_vec_write_element64(v1, 1, e1); + } else { + s390_vec_write_element64(v1, 0, MIN(first_equal, first_zero)); + s390_vec_write_element64(v1, 1, 0); + } + + if (first_zero == 16 && first_equal == 16) { + return 3; /* no match */ + } else if (first_zero == 16) { + return 1; /* matching elements, no match for zero */ + } else if (first_equal < first_zero) { + return 2; /* matching elements before match for zero */ + } + return 0; /* match for zero */ +} + +#define DEF_VFAE_HELPER(BITS) \ +void HELPER(gvec_vfae##BITS)(void *v1, const void *v2, const void *v3, \ + uint32_t desc) \ +{ \ + const bool in = extract32(simd_data(desc), 3, 1); \ + const bool rt = extract32(simd_data(desc), 2, 1); \ + const bool zs = extract32(simd_data(desc), 1, 1); \ + \ + vfae(v1, v2, v3, in, rt, zs, MO_##BITS); \ +} +DEF_VFAE_HELPER(8) +DEF_VFAE_HELPER(16) +DEF_VFAE_HELPER(32) + +#define DEF_VFAE_CC_HELPER(BITS) \ +void HELPER(gvec_vfae_cc##BITS)(void *v1, const void *v2, const void *v3, \ + CPUS390XState *env, uint32_t desc) \ +{ \ + const bool in = extract32(simd_data(desc), 3, 1); \ + const bool rt = extract32(simd_data(desc), 2, 1); \ + const bool zs = extract32(simd_data(desc), 1, 1); \ + \ + env->cc_op = vfae(v1, v2, v3, in, rt, zs, MO_##BITS); \ +} +DEF_VFAE_CC_HELPER(8) +DEF_VFAE_CC_HELPER(16) +DEF_VFAE_CC_HELPER(32) + +static int vfee(void *v1, const void *v2, const void *v3, bool zs, uint8_t es) +{ + const uint64_t mask = get_element_lsbs_mask(es); + uint64_t a0, a1, b0, b1, e0, e1, z0, z1; + uint64_t first_zero = 16; + uint64_t first_equal; + + a0 = s390_vec_read_element64(v2, 0); + a1 = s390_vec_read_element64(v2, 1); + b0 = s390_vec_read_element64(v3, 0); + b1 = s390_vec_read_element64(v3, 1); + e0 = zero_search(a0 ^ b0, mask); + e1 = zero_search(a1 ^ b1, mask); + first_equal = match_index(e0, e1); + + if (zs) { + z0 = zero_search(a0, mask); + z1 = zero_search(a1, mask); + first_zero = match_index(z0, z1); + } + + s390_vec_write_element64(v1, 0, MIN(first_equal, first_zero)); + s390_vec_write_element64(v1, 1, 0); + if (first_zero == 16 && first_equal == 16) { + return 3; /* no match */ + } else if (first_zero == 16) { + return 1; /* matching elements, no match for zero */ + } else if (first_equal < first_zero) { + return 2; /* matching elements before match for zero */ + } + return 0; /* match for zero */ +} + +#define DEF_VFEE_HELPER(BITS) \ +void HELPER(gvec_vfee##BITS)(void *v1, const void *v2, const void *v3, \ + uint32_t desc) \ +{ \ + const bool zs = extract32(simd_data(desc), 1, 1); \ + \ + vfee(v1, v2, v3, zs, MO_##BITS); \ +} +DEF_VFEE_HELPER(8) +DEF_VFEE_HELPER(16) +DEF_VFEE_HELPER(32) + +#define DEF_VFEE_CC_HELPER(BITS) \ +void HELPER(gvec_vfee_cc##BITS)(void *v1, const void *v2, const void *v3, \ + CPUS390XState *env, uint32_t desc) \ +{ \ + const bool zs = extract32(simd_data(desc), 1, 1); \ + \ + env->cc_op = vfee(v1, v2, v3, zs, MO_##BITS); \ +} +DEF_VFEE_CC_HELPER(8) +DEF_VFEE_CC_HELPER(16) +DEF_VFEE_CC_HELPER(32) + +static int vfene(void *v1, const void *v2, const void *v3, bool zs, uint8_t es) +{ + const uint64_t mask = get_element_lsbs_mask(es); + uint64_t a0, a1, b0, b1, e0, e1, z0, z1; + uint64_t first_zero = 16; + uint64_t first_inequal; + bool smaller = false; + + a0 = s390_vec_read_element64(v2, 0); + a1 = s390_vec_read_element64(v2, 1); + b0 = s390_vec_read_element64(v3, 0); + b1 = s390_vec_read_element64(v3, 1); + e0 = nonzero_search(a0 ^ b0, mask); + e1 = nonzero_search(a1 ^ b1, mask); + first_inequal = match_index(e0, e1); + + /* identify the smaller element */ + if (first_inequal < 16) { + uint8_t enr = first_inequal / (1 << es); + uint32_t a = s390_vec_read_element(v2, enr, es); + uint32_t b = s390_vec_read_element(v3, enr, es); + + smaller = a < b; + } + + if (zs) { + z0 = zero_search(a0, mask); + z1 = zero_search(a1, mask); + first_zero = match_index(z0, z1); + } + + s390_vec_write_element64(v1, 0, MIN(first_inequal, first_zero)); + s390_vec_write_element64(v1, 1, 0); + if (first_zero == 16 && first_inequal == 16) { + return 3; + } else if (first_zero < first_inequal) { + return 0; + } + return smaller ? 1 : 2; +} + +#define DEF_VFENE_HELPER(BITS) \ +void HELPER(gvec_vfene##BITS)(void *v1, const void *v2, const void *v3, \ + uint32_t desc) \ +{ \ + const bool zs = extract32(simd_data(desc), 1, 1); \ + \ + vfene(v1, v2, v3, zs, MO_##BITS); \ +} +DEF_VFENE_HELPER(8) +DEF_VFENE_HELPER(16) +DEF_VFENE_HELPER(32) + +#define DEF_VFENE_CC_HELPER(BITS) \ +void HELPER(gvec_vfene_cc##BITS)(void *v1, const void *v2, const void *v3, \ + CPUS390XState *env, uint32_t desc) \ +{ \ + const bool zs = extract32(simd_data(desc), 1, 1); \ + \ + env->cc_op = vfene(v1, v2, v3, zs, MO_##BITS); \ +} +DEF_VFENE_CC_HELPER(8) +DEF_VFENE_CC_HELPER(16) +DEF_VFENE_CC_HELPER(32) + +static int vistr(void *v1, const void *v2, uint8_t es) +{ + const uint64_t mask = get_element_lsbs_mask(es); + uint64_t a0 = s390_vec_read_element64(v2, 0); + uint64_t a1 = s390_vec_read_element64(v2, 1); + uint64_t z; + int cc = 3; + + z = zero_search(a0, mask); + if (z) { + a0 &= ~(-1ull >> clz64(z)); + a1 = 0; + cc = 0; + } else { + z = zero_search(a1, mask); + if (z) { + a1 &= ~(-1ull >> clz64(z)); + cc = 0; + } + } + + s390_vec_write_element64(v1, 0, a0); + s390_vec_write_element64(v1, 1, a1); + return cc; +} + +#define DEF_VISTR_HELPER(BITS) \ +void HELPER(gvec_vistr##BITS)(void *v1, const void *v2, uint32_t desc) \ +{ \ + vistr(v1, v2, MO_##BITS); \ +} +DEF_VISTR_HELPER(8) +DEF_VISTR_HELPER(16) +DEF_VISTR_HELPER(32) + +#define DEF_VISTR_CC_HELPER(BITS) \ +void HELPER(gvec_vistr_cc##BITS)(void *v1, const void *v2, CPUS390XState *env, \ + uint32_t desc) \ +{ \ + env->cc_op = vistr(v1, v2, MO_##BITS); \ +} +DEF_VISTR_CC_HELPER(8) +DEF_VISTR_CC_HELPER(16) +DEF_VISTR_CC_HELPER(32) + +static bool element_compare(uint32_t data, uint32_t l, uint8_t c) +{ + const bool equal = extract32(c, 7, 1); + const bool lower = extract32(c, 6, 1); + const bool higher = extract32(c, 5, 1); + + if (data < l) { + return lower; + } else if (data > l) { + return higher; + } + return equal; +} + +static int vstrc(void *v1, const void *v2, const void *v3, const void *v4, + bool in, bool rt, bool zs, uint8_t es) +{ + const uint64_t mask = get_element_lsbs_mask(es); + uint64_t a0 = s390_vec_read_element64(v2, 0); + uint64_t a1 = s390_vec_read_element64(v2, 1); + int first_zero = 16, first_match = 16; + S390Vector rt_result = {}; + uint64_t z0, z1; + int i, j; + + if (zs) { + z0 = zero_search(a0, mask); + z1 = zero_search(a1, mask); + first_zero = match_index(z0, z1); + } + + for (i = 0; i < 16 / (1 << es); i++) { + const uint32_t data = s390_vec_read_element(v2, i, es); + const int cur_byte = i * (1 << es); + bool any_match = false; + + /* if we don't need a bit vector, we can stop early */ + if (cur_byte == first_zero && !rt) { + break; + } + + for (j = 0; j < 16 / (1 << es); j += 2) { + const uint32_t l1 = s390_vec_read_element(v3, j, es); + const uint32_t l2 = s390_vec_read_element(v3, j + 1, es); + /* we are only interested in the highest byte of each element */ + const uint8_t c1 = s390_vec_read_element8(v4, j * (1 << es)); + const uint8_t c2 = s390_vec_read_element8(v4, (j + 1) * (1 << es)); + + if (element_compare(data, l1, c1) && + element_compare(data, l2, c2)) { + any_match = true; + break; + } + } + /* invert the result if requested */ + any_match = in ^ any_match; + + if (any_match) { + /* indicate bit vector if requested */ + if (rt) { + const uint64_t val = -1ull; + + first_match = MIN(cur_byte, first_match); + s390_vec_write_element(&rt_result, i, es, val); + } else { + /* stop on the first match */ + first_match = cur_byte; + break; + } + } + } + + if (rt) { + *(S390Vector *)v1 = rt_result; + } else { + s390_vec_write_element64(v1, 0, MIN(first_match, first_zero)); + s390_vec_write_element64(v1, 1, 0); + } + + if (first_zero == 16 && first_match == 16) { + return 3; /* no match */ + } else if (first_zero == 16) { + return 1; /* matching elements, no match for zero */ + } else if (first_match < first_zero) { + return 2; /* matching elements before match for zero */ + } + return 0; /* match for zero */ +} + +#define DEF_VSTRC_HELPER(BITS) \ +void HELPER(gvec_vstrc##BITS)(void *v1, const void *v2, const void *v3, \ + const void *v4, uint32_t desc) \ +{ \ + const bool in = extract32(simd_data(desc), 3, 1); \ + const bool zs = extract32(simd_data(desc), 1, 1); \ + \ + vstrc(v1, v2, v3, v4, in, 0, zs, MO_##BITS); \ +} +DEF_VSTRC_HELPER(8) +DEF_VSTRC_HELPER(16) +DEF_VSTRC_HELPER(32) + +#define DEF_VSTRC_RT_HELPER(BITS) \ +void HELPER(gvec_vstrc_rt##BITS)(void *v1, const void *v2, const void *v3, \ + const void *v4, uint32_t desc) \ +{ \ + const bool in = extract32(simd_data(desc), 3, 1); \ + const bool zs = extract32(simd_data(desc), 1, 1); \ + \ + vstrc(v1, v2, v3, v4, in, 1, zs, MO_##BITS); \ +} +DEF_VSTRC_RT_HELPER(8) +DEF_VSTRC_RT_HELPER(16) +DEF_VSTRC_RT_HELPER(32) + +#define DEF_VSTRC_CC_HELPER(BITS) \ +void HELPER(gvec_vstrc_cc##BITS)(void *v1, const void *v2, const void *v3, \ + const void *v4, CPUS390XState *env, \ + uint32_t desc) \ +{ \ + const bool in = extract32(simd_data(desc), 3, 1); \ + const bool zs = extract32(simd_data(desc), 1, 1); \ + \ + env->cc_op = vstrc(v1, v2, v3, v4, in, 0, zs, MO_##BITS); \ +} +DEF_VSTRC_CC_HELPER(8) +DEF_VSTRC_CC_HELPER(16) +DEF_VSTRC_CC_HELPER(32) + +#define DEF_VSTRC_CC_RT_HELPER(BITS) \ +void HELPER(gvec_vstrc_cc_rt##BITS)(void *v1, const void *v2, const void *v3, \ + const void *v4, CPUS390XState *env, \ + uint32_t desc) \ +{ \ + const bool in = extract32(simd_data(desc), 3, 1); \ + const bool zs = extract32(simd_data(desc), 1, 1); \ + \ + env->cc_op = vstrc(v1, v2, v3, v4, in, 1, zs, MO_##BITS); \ +} +DEF_VSTRC_CC_RT_HELPER(8) +DEF_VSTRC_CC_RT_HELPER(16) +DEF_VSTRC_CC_RT_HELPER(32) diff --git a/target/xtensa/translate.c b/target/xtensa/translate.c index 53dce470c1..6f1da87875 100644 --- a/target/xtensa/translate.c +++ b/target/xtensa/translate.c @@ -38,7 +38,7 @@ #include "qemu/qemu-print.h" #include "sysemu/sysemu.h" #include "exec/cpu_ldst.h" -#include "exec/semihost.h" +#include "hw/semihosting/semihost.h" #include "exec/translator.h" #include "exec/helper-proto.h" diff --git a/target/xtensa/xtensa-semi.c b/target/xtensa/xtensa-semi.c index 5f5ce4f344..38efa3485a 100644 --- a/target/xtensa/xtensa-semi.c +++ b/target/xtensa/xtensa-semi.c @@ -29,7 +29,7 @@ #include "cpu.h" #include "chardev/char-fe.h" #include "exec/helper-proto.h" -#include "exec/semihost.h" +#include "hw/semihosting/semihost.h" #include "qapi/error.h" #include "qemu/log.h" #include "sysemu/sysemu.h" diff --git a/tests/Makefile.include b/tests/Makefile.include index 1865f6b322..0cd5f465b7 100644 --- a/tests/Makefile.include +++ b/tests/Makefile.include @@ -255,9 +255,6 @@ check-qtest-sparc64-$(CONFIG_ISA_TESTDEV) = tests/endianness-test$(EXESUF) check-qtest-sparc64-y += tests/prom-env-test$(EXESUF) check-qtest-sparc64-y += tests/boot-serial-test$(EXESUF) -check-qtest-arm-y += tests/tmp105-test$(EXESUF) -check-qtest-arm-y += tests/pca9552-test$(EXESUF) -check-qtest-arm-y += tests/ds1338-test$(EXESUF) check-qtest-arm-y += tests/microbit-test$(EXESUF) check-qtest-arm-y += tests/m25p80-test$(EXESUF) check-qtest-arm-y += tests/test-arm-mptimer$(EXESUF) @@ -267,6 +264,10 @@ check-qtest-arm-y += tests/hexloader-test$(EXESUF) check-qtest-aarch64-y = tests/numa-test$(EXESUF) check-qtest-aarch64-y += tests/boot-serial-test$(EXESUF) check-qtest-aarch64-y += tests/migration-test$(EXESUF) +# TODO: once aarch64 TCG is fixed on ARM 32 bit host, make test unconditional +ifneq ($(ARCH),arm) +check-qtest-aarch64-y += tests/bios-tables-test$(EXESUF) +endif check-qtest-microblazeel-y += $(check-qtest-microblaze-y) @@ -678,7 +679,7 @@ libqgraph-obj-y = tests/libqos/qgraph.o libqos-obj-y = $(libqgraph-obj-y) tests/libqos/pci.o tests/libqos/fw_cfg.o libqos-obj-y += tests/libqos/malloc.o -libqos-obj-y += tests/libqos/i2c.o tests/libqos/libqos.o +libqos-obj-y += tests/libqos/libqos.o libqos-spapr-obj-y = $(libqos-obj-y) tests/libqos/malloc-spapr.o libqos-spapr-obj-y += tests/libqos/libqos-spapr.o libqos-spapr-obj-y += tests/libqos/rtas.o @@ -686,14 +687,15 @@ libqos-spapr-obj-y += tests/libqos/pci-spapr.o libqos-pc-obj-y = $(libqos-obj-y) tests/libqos/pci-pc.o libqos-pc-obj-y += tests/libqos/malloc-pc.o tests/libqos/libqos-pc.o libqos-pc-obj-y += tests/libqos/ahci.o -libqos-omap-obj-y = $(libqos-obj-y) tests/libqos/i2c-omap.o -libqos-imx-obj-y = $(libqos-obj-y) tests/libqos/i2c-imx.o libqos-usb-obj-y = $(libqos-spapr-obj-y) $(libqos-pc-obj-y) tests/libqos/usb.o # Devices qos-test-obj-y = tests/qos-test.o $(libqgraph-obj-y) qos-test-obj-y += $(libqos-pc-obj-y) $(libqos-spapr-obj-y) qos-test-obj-y += tests/libqos/e1000e.o +qos-test-obj-y += tests/libqos/i2c.o +qos-test-obj-y += tests/libqos/i2c-imx.o +qos-test-obj-y += tests/libqos/i2c-omap.o qos-test-obj-y += tests/libqos/sdhci.o qos-test-obj-y += tests/libqos/tpci200.o qos-test-obj-y += tests/libqos/virtio.o @@ -709,6 +711,8 @@ qos-test-obj-y += tests/libqos/virtio-serial.o # Machines qos-test-obj-y += tests/libqos/aarch64-xlnx-zcu102-machine.o +qos-test-obj-y += tests/libqos/arm-imx25-pdk-machine.o +qos-test-obj-y += tests/libqos/arm-n800-machine.o qos-test-obj-y += tests/libqos/arm-raspi2-machine.o qos-test-obj-y += tests/libqos/arm-sabrelite-machine.o qos-test-obj-y += tests/libqos/arm-smdkc210-machine.o @@ -719,6 +723,7 @@ qos-test-obj-y += tests/libqos/x86_64_pc-machine.o # Tests qos-test-obj-y += tests/ac97-test.o +qos-test-obj-y += tests/ds1338-test.o qos-test-obj-y += tests/e1000-test.o qos-test-obj-y += tests/e1000e-test.o qos-test-obj-y += tests/eepro100-test.o @@ -727,10 +732,12 @@ qos-test-obj-y += tests/ipoctal232-test.o qos-test-obj-y += tests/megasas-test.o qos-test-obj-y += tests/ne2000-test.o qos-test-obj-y += tests/nvme-test.o +qos-test-obj-y += tests/pca9552-test.o qos-test-obj-y += tests/pci-test.o qos-test-obj-y += tests/pcnet-test.o qos-test-obj-y += tests/sdhci-test.o qos-test-obj-y += tests/spapr-phb-test.o +qos-test-obj-y += tests/tmp105-test.o qos-test-obj-y += tests/usb-hcd-ohci-test.o $(libqos-usb-obj-y) qos-test-obj-$(CONFIG_VHOST_NET_USER) += tests/vhost-user-test.o $(chardev-obj-y) $(test-io-obj-y) qos-test-obj-y += tests/virtio-test.o @@ -768,9 +775,6 @@ tests/boot-serial-test$(EXESUF): tests/boot-serial-test.o $(libqos-obj-y) tests/bios-tables-test$(EXESUF): tests/bios-tables-test.o \ tests/boot-sector.o tests/acpi-utils.o $(libqos-obj-y) tests/pxe-test$(EXESUF): tests/pxe-test.o tests/boot-sector.o $(libqos-obj-y) -tests/tmp105-test$(EXESUF): tests/tmp105-test.o $(libqos-omap-obj-y) -tests/pca9552-test$(EXESUF): tests/pca9552-test.o $(libqos-omap-obj-y) -tests/ds1338-test$(EXESUF): tests/ds1338-test.o $(libqos-imx-obj-y) tests/microbit-test$(EXESUF): tests/microbit-test.o tests/m25p80-test$(EXESUF): tests/m25p80-test.o tests/i440fx-test$(EXESUF): tests/i440fx-test.o $(libqos-pc-obj-y) @@ -904,7 +908,7 @@ check-report-unit.tap: $(check-unit-y) # Reports and overall runs check-report.tap: $(patsubst %,check-report-qtest-%.tap, $(QTEST_TARGETS)) check-report-unit.tap - $(call quiet-command,./scripts/tap-merge.py $^ > $@,"GEN","$@") + $(call quiet-command, cat $^ | scripts/tap-merge.pl >$@,"GEN","$@") # FPU Emulation tests (aka softfloat) # diff --git a/tests/acceptance/linux_ssh_mips_malta.py b/tests/acceptance/linux_ssh_mips_malta.py new file mode 100644 index 0000000000..aafb0c39f6 --- /dev/null +++ b/tests/acceptance/linux_ssh_mips_malta.py @@ -0,0 +1,230 @@ +# Functional test that boots a VM and run commands via a SSH session +# +# Copyright (c) Philippe Mathieu-Daudé <f4bug@amsat.org> +# +# This work is licensed under the terms of the GNU GPL, version 2 or +# later. See the COPYING file in the top-level directory. + +import os +import re +import base64 +import logging +import paramiko +import time + +from avocado import skipIf +from avocado_qemu import Test +from avocado.utils import process +from avocado.utils import archive + + +class LinuxSSH(Test): + + timeout = 150 # Not for 'configure --enable-debug --enable-debug-tcg' + + KERNEL_COMMON_COMMAND_LINE = 'printk.time=0 ' + VM_IP = '127.0.0.1' + + IMAGE_INFO = { + 'be': { + 'image_url': 'https://people.debian.org/~aurel32/qemu/mips/' + 'debian_wheezy_mips_standard.qcow2', + 'image_hash': '8987a63270df67345b2135a6b7a4885a35e392d5', + 'rsa_hostkey': b'AAAAB3NzaC1yc2EAAAADAQABAAABAQCca1VitiyLAdQOld' + b'zT43IOEVJZ0wHD78GJi8wDAjMiYWUzNSSn0rXGQsINHuH5' + b'IlF+kBZsHinb/FtKCAyS9a8uCHhQI4SuB4QhAb0+39MlUw' + b'Mm0CLkctgM2eUUZ6MQMQvDlqnue6CCkxN62EZYbaxmby7j' + b'CQa1125o1HRKBvdGm2zrJWxXAfA+f1v6jHLyE8Jnu83eQ+' + b'BFY25G+Vzx1PVc3zQBwJ8r0NGTRqy2//oWQP0h+bMsgeFe' + b'KH/J3RJM22vg6+I4JAdBFcxnK+l781h1FuRxOn4O/Xslbg' + b'go6WtB4V4TOsw2E/KfxI5IZ/icxF+swVcnvF46Hf3uQc/0' + b'BBqb', + }, + 'le': { + 'image_url': 'https://people.debian.org/~aurel32/qemu/mipsel/' + 'debian_wheezy_mipsel_standard.qcow2', + 'image_hash': '7866764d9de3ef536ffca24c9fb9f04ffdb45802', + 'rsa_hostkey': b'AAAAB3NzaC1yc2EAAAADAQABAAABAQClXJlBT71HL5yKvv' + b'gfC7jmxSWx5zSBCzET6CLZczwAafSIs7YKfNOy/dQTxhuk' + b'yIGFUugZFoF3E9PzdhunuyvyTd56MPoNIqFbb5rGokwU5I' + b'TOx3dBHZR0mClypL6MVrwe0bsiIb8GhF1zioNwcsaAZnAi' + b'KfXStVDtXvn/kLLq+xLABYt48CC5KYWoFaCoICskLAY+qo' + b'L+LWyAnQisj4jAH8VSaSKIImFpfkHWEXPhHcC4ZBlDKtnH' + b'po9vhfCHgnfW3Pzrqmk8BI4HysqPFVmJWkJGlGUL+sGeg3' + b'ZZolAYuDXGuBrw8ooPJq2v2dOH+z6dyD2q/ypmAbyPqj5C' + b'rc8H', + }, + } + + def wait_for_console_pattern(self, success_message, + failure_message='Oops'): + console = self.vm.console_socket.makefile() + console_logger = logging.getLogger('console') + while True: + msg = console.readline() + console_logger.debug(msg.strip()) + if success_message in msg: + break + if failure_message in msg: + fail = 'Failure message found in console: %s' % failure_message + self.fail(fail) + + def get_portfwd(self): + res = self.vm.command('human-monitor-command', + command_line='info usernet') + line = res.split('\r\n')[2] + port = re.split(r'.*TCP.HOST_FORWARD.*127\.0\.0\.1 (\d+)\s+10\..*', + line)[1] + self.log.debug("sshd listening on port:" + port) + return port + + def ssh_connect(self, username, password, rsa_hostkey_b64=None): + self.ssh_logger = logging.getLogger('ssh') + self.ssh_username = username + self.ssh_ps1 = '# ' if username is 'root' else '$ ' + self.ssh_client = paramiko.SSHClient() + port = self.get_portfwd() + if rsa_hostkey_b64: + rsa_hostkey_bin = base64.b64decode(rsa_hostkey_b64) + rsa_hostkey = paramiko.RSAKey(data = rsa_hostkey_bin) + ipport = '[%s]:%s' % (self.VM_IP, port) + self.ssh_logger.debug('ipport ' + ipport) + self.ssh_client.get_host_keys().add(ipport, 'ssh-rsa', rsa_hostkey) + for i in range(10): + try: + self.ssh_client.connect(self.VM_IP, int(port), + username, password, banner_timeout=90) + self.ssh_logger.info("Entering interactive session.") + return + except: + time.sleep(4) + pass + self.fail("sshd timeout") + + def ssh_disconnect_vm(self): + self.ssh_client.close() + + def ssh_command(self, command, is_root=True): + self.ssh_logger.info(self.ssh_ps1 + command) + stdin, stdout, stderr = self.ssh_client.exec_command(command) + stdout_lines = [line.strip('\n') for line in stdout] + for line in stdout_lines: + self.ssh_logger.info(line) + stderr_lines = [line.strip('\n') for line in stderr] + for line in stderr_lines: + self.ssh_logger.warning(line) + return stdout_lines, stderr_lines + + def boot_debian_wheezy_image_and_ssh_login(self, endianess, kernel_path): + image_url = self.IMAGE_INFO[endianess]['image_url'] + image_hash = self.IMAGE_INFO[endianess]['image_hash'] + image_path = self.fetch_asset(image_url, asset_hash=image_hash) + rsa_hostkey_b64 = self.IMAGE_INFO[endianess]['rsa_hostkey'] + + self.vm.set_machine('malta') + self.vm.set_console() + kernel_command_line = (self.KERNEL_COMMON_COMMAND_LINE + + 'console=ttyS0 root=/dev/sda1') + self.vm.add_args('-no-reboot', + '-kernel', kernel_path, + '-append', kernel_command_line, + '-hda', image_path, + '-netdev', 'user,id=vnet,hostfwd=:127.0.0.1:0-:22', + '-device', 'pcnet,netdev=vnet') + self.vm.launch() + + self.log.info('VM launched, waiting for sshd') + console_pattern = 'Starting OpenBSD Secure Shell server: sshd' + self.wait_for_console_pattern(console_pattern) + self.log.info('sshd ready') + + self.ssh_connect('root', 'root', rsa_hostkey_b64=rsa_hostkey_b64) + + def shutdown_via_ssh(self): + self.ssh_command('poweroff') + self.ssh_disconnect_vm() + self.wait_for_console_pattern('Power down') + + def run_common_commands(self): + stdout, stderr = self.ssh_command('lspci -d 11ab:4620') + self.assertIn(True, ["GT-64120" in line for line in stdout]) + + stdout, stderr = self.ssh_command('cat /sys/bus/i2c/devices/i2c-0/name') + self.assertIn(True, ["SMBus PIIX4 adapter" in line + for line in stdout]) + + stdout, stderr = self.ssh_command('cat /proc/mtd') + self.assertIn(True, ["YAMON" in line + for line in stdout]) + + # Empty 'Board Config' + stdout, stderr = self.ssh_command('md5sum /dev/mtd2ro') + self.assertIn(True, ["0dfbe8aa4c20b52e1b8bf3cb6cbdf193" in line + for line in stdout]) + + def do_test_mips_malta(self, endianess, kernel_path, uname_m): + self.boot_debian_wheezy_image_and_ssh_login(endianess, kernel_path) + + stdout, stderr = self.ssh_command('uname -a') + self.assertIn(True, [uname_m + " GNU/Linux" in line for line in stdout]) + + self.run_common_commands() + self.shutdown_via_ssh() + + @skipIf(os.getenv('CONTINUOUS_INTEGRATION'), 'Running on Travis-CI') + def test_mips_malta32eb_kernel3_2_0(self): + """ + :avocado: tags=arch:mips + :avocado: tags=machine:malta + :avocado: tags=endian:big + :avocado: tags=device:pcnet32 + """ + kernel_url = ('https://people.debian.org/~aurel32/qemu/mips/' + 'vmlinux-3.2.0-4-4kc-malta') + kernel_hash = '592e384a4edc16dade52a6cd5c785c637bcbc9ad' + kernel_path = self.fetch_asset(kernel_url, asset_hash=kernel_hash) + + self.do_test_mips_malta('be', kernel_path, 'mips') + + @skipIf(os.getenv('CONTINUOUS_INTEGRATION'), 'Running on Travis-CI') + def test_mips_malta32el_kernel3_2_0(self): + """ + :avocado: tags=arch:mipsel + :avocado: tags=machine:malta + :avocado: tags=endian:little + :avocado: tags=device:pcnet32 + """ + kernel_url = ('https://people.debian.org/~aurel32/qemu/mipsel/' + 'vmlinux-3.2.0-4-4kc-malta') + kernel_hash = 'a66bea5a8adaa2cb3d36a1d4e0ccdb01be8f6c2a' + kernel_path = self.fetch_asset(kernel_url, asset_hash=kernel_hash) + + self.do_test_mips_malta('le', kernel_path, 'mips') + + @skipIf(os.getenv('CONTINUOUS_INTEGRATION'), 'Running on Travis-CI') + def test_mips_malta64eb_kernel3_2_0(self): + """ + :avocado: tags=arch:mips64 + :avocado: tags=machine:malta + :avocado: tags=endian:big + :avocado: tags=device:pcnet32 + """ + kernel_url = ('https://people.debian.org/~aurel32/qemu/mips/' + 'vmlinux-3.2.0-4-5kc-malta') + kernel_hash = 'db6eea7de35d36c77d8c165b6bcb222e16eb91db' + kernel_path = self.fetch_asset(kernel_url, asset_hash=kernel_hash) + self.do_test_mips_malta('be', kernel_path, 'mips64') + + @skipIf(os.getenv('CONTINUOUS_INTEGRATION'), 'Running on Travis-CI') + def test_mips_malta64el_kernel3_2_0(self): + """ + :avocado: tags=arch:mips64el + :avocado: tags=machine:malta + :avocado: tags=endian:little + :avocado: tags=device:pcnet32 + """ + kernel_url = ('https://people.debian.org/~aurel32/qemu/mipsel/' + 'vmlinux-3.2.0-4-5kc-malta') + kernel_hash = '6a7f77245acf231415a0e8b725d91ed2f3487794' + kernel_path = self.fetch_asset(kernel_url, asset_hash=kernel_hash) + self.do_test_mips_malta('le', kernel_path, 'mips64') diff --git a/tests/bios-tables-test-allowed-diff.h b/tests/bios-tables-test-allowed-diff.h new file mode 100644 index 0000000000..dfb8523c8b --- /dev/null +++ b/tests/bios-tables-test-allowed-diff.h @@ -0,0 +1 @@ +/* List of comma-separated changed AML files to ignore */ diff --git a/tests/bios-tables-test.c b/tests/bios-tables-test.c index 11e07be093..0ce55182f2 100644 --- a/tests/bios-tables-test.c +++ b/tests/bios-tables-test.c @@ -342,13 +342,29 @@ try_again: return exp_tables; } +static bool test_acpi_find_diff_allowed(AcpiSdtTable *sdt) +{ + const gchar *allowed_diff_file[] = { +#include "bios-tables-test-allowed-diff.h" + NULL + }; + const gchar **f; + + for (f = allowed_diff_file; *f; ++f) { + if (!g_strcmp0(sdt->aml_file, *f)) { + return true; + } + } + return false; +} + /* test the list of tables in @data->tables against reference tables */ static void test_acpi_asl(test_data *data) { int i; AcpiSdtTable *sdt, *exp_sdt; test_data exp_data; - gboolean exp_err, err; + gboolean exp_err, err, all_tables_match = true; memset(&exp_data, 0, sizeof(exp_data)); exp_data.tables = load_expected_aml(data); @@ -359,6 +375,20 @@ static void test_acpi_asl(test_data *data) sdt = &g_array_index(data->tables, AcpiSdtTable, i); exp_sdt = &g_array_index(exp_data.tables, AcpiSdtTable, i); + if (sdt->aml_len == exp_sdt->aml_len && + !memcmp(sdt->aml, exp_sdt->aml, sdt->aml_len)) { + /* Identical table binaries: no need to disassemble. */ + continue; + } + + fprintf(stderr, + "acpi-test: Warning! %.4s binary file mismatch. " + "Actual [aml:%s], Expected [aml:%s].\n", + exp_sdt->aml, sdt->aml_file, exp_sdt->aml_file); + + all_tables_match = all_tables_match && + test_acpi_find_diff_allowed(exp_sdt); + err = load_asl(data->tables, sdt); asl = normalize_asl(sdt->asl); @@ -396,11 +426,12 @@ static void test_acpi_asl(test_data *data) "see ASL difference."); } } - } + } } g_string_free(asl, true); g_string_free(exp_asl, true); } + g_assert(all_tables_match); free_test_data(&exp_data); } @@ -813,6 +844,22 @@ static void test_acpi_piix4_tcg_dimm_pxm(void) test_acpi_tcg_dimm_pxm(MACHINE_PC); } +static void test_acpi_virt_tcg(void) +{ + test_data data = { + .machine = "virt", + .accel = "tcg", + .uefi_fl1 = "pc-bios/edk2-aarch64-code.fd", + .uefi_fl2 = "pc-bios/edk2-arm-vars.fd", + .cd = "tests/data/uefi-boot-images/bios-tables-test.aarch64.iso.qcow2", + .ram_start = 0x40000000ULL, + .scan_len = 128ULL * 1024 * 1024, + }; + + test_acpi_one("-cpu cortex-a57", &data); + free_test_data(&data); +} + int main(int argc, char *argv[]) { const char *arch = qtest_get_arch(); @@ -841,6 +888,8 @@ int main(int argc, char *argv[]) qtest_add_func("acpi/q35/numamem", test_acpi_q35_tcg_numamem); qtest_add_func("acpi/piix4/dimmpxm", test_acpi_piix4_tcg_dimm_pxm); qtest_add_func("acpi/q35/dimmpxm", test_acpi_q35_tcg_dimm_pxm); + } else if (strcmp(arch, "aarch64") == 0) { + qtest_add_func("acpi/virt", test_acpi_virt_tcg); } ret = g_test_run(); boot_sector_cleanup(disk); diff --git a/tests/data/acpi/rebuild-expected-aml.sh b/tests/data/acpi/rebuild-expected-aml.sh index ff7e62249d..d2853218dd 100755 --- a/tests/data/acpi/rebuild-expected-aml.sh +++ b/tests/data/acpi/rebuild-expected-aml.sh @@ -12,7 +12,7 @@ # This work is licensed under the terms of the GNU GPLv2. # See the COPYING.LIB file in the top-level directory. -qemu_bins="x86_64-softmmu/qemu-system-x86_64" +qemu_bins="x86_64-softmmu/qemu-system-x86_64 aarch64-softmmu/qemu-system-aarch64" if [ ! -e "tests/bios-tables-test" ]; then echo "Test: bios-tables-test is required! Run make check before this script." diff --git a/tests/data/acpi/virt/APIC b/tests/data/acpi/virt/APIC Binary files differnew file mode 100644 index 0000000000..797dfde284 --- /dev/null +++ b/tests/data/acpi/virt/APIC diff --git a/tests/data/acpi/virt/DSDT b/tests/data/acpi/virt/DSDT Binary files differnew file mode 100644 index 0000000000..20e85c7f89 --- /dev/null +++ b/tests/data/acpi/virt/DSDT diff --git a/tests/data/acpi/virt/FACP b/tests/data/acpi/virt/FACP Binary files differnew file mode 100644 index 0000000000..27de99f51b --- /dev/null +++ b/tests/data/acpi/virt/FACP diff --git a/tests/data/acpi/virt/GTDT b/tests/data/acpi/virt/GTDT Binary files differnew file mode 100644 index 0000000000..10107a65e9 --- /dev/null +++ b/tests/data/acpi/virt/GTDT diff --git a/tests/data/acpi/virt/MCFG b/tests/data/acpi/virt/MCFG Binary files differnew file mode 100644 index 0000000000..e8987e1af0 --- /dev/null +++ b/tests/data/acpi/virt/MCFG diff --git a/tests/data/acpi/virt/SPCR b/tests/data/acpi/virt/SPCR Binary files differnew file mode 100644 index 0000000000..377271a0e7 --- /dev/null +++ b/tests/data/acpi/virt/SPCR diff --git a/tests/docker/Makefile.include b/tests/docker/Makefile.include index c0e1bf57a3..aaf5396b85 100644 --- a/tests/docker/Makefile.include +++ b/tests/docker/Makefile.include @@ -107,6 +107,7 @@ docker-image-debian-sparc64-cross: docker-image-debian-sid docker-image-debian-mips64-cross: docker-image-debian-sid docker-image-debian-riscv64-cross: docker-image-debian-sid docker-image-debian-powerpc-cross: docker-image-debian-sid +docker-image-debian-ppc64-cross: docker-image-debian-sid docker-image-travis: NOUSER=1 # Specialist build images, sometimes very limited tools diff --git a/tests/docker/dockerfiles/debian-ppc64-cross.docker b/tests/docker/dockerfiles/debian-ppc64-cross.docker new file mode 100644 index 0000000000..7f239c322d --- /dev/null +++ b/tests/docker/dockerfiles/debian-ppc64-cross.docker @@ -0,0 +1,11 @@ +# +# Docker ppc64 cross-compiler target +# +# This docker target builds on the debian sid base image which +# contains cross compilers for Debian "ports" targets. +FROM qemu:debian-sid + +RUN DEBIAN_FRONTEND=noninteractive eatmydata \ + apt-get install -y --no-install-recommends \ + gcc-powerpc64-linux-gnu \ + libc6-dev-ppc64-cross || { echo "Failed to build - see debian-sid.docker notes"; exit 1; } 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/ds1338-test.c b/tests/ds1338-test.c index 742dad9113..f6ade9a050 100644 --- a/tests/ds1338-test.c +++ b/tests/ds1338-test.c @@ -21,31 +21,22 @@ #include "libqtest.h" #include "libqos/i2c.h" -#define IMX25_I2C_0_BASE 0x43F80000 - #define DS1338_ADDR 0x68 -static I2CAdapter *i2c; -static uint8_t addr; - static inline uint8_t bcd2bin(uint8_t x) { return ((x) & 0x0f) + ((x) >> 4) * 10; } -static void send_and_receive(void) +static void send_and_receive(void *obj, void *data, QGuestAllocator *alloc) { - uint8_t cmd[1]; + QI2CDevice *i2cdev = (QI2CDevice *)obj; + uint8_t resp[7]; time_t now = time(NULL); struct tm *tm_ptr = gmtime(&now); - /* reset the index in the RTC memory */ - cmd[0] = 0; - i2c_send(i2c, addr, cmd, 1); - - /* retrieve the date */ - i2c_recv(i2c, addr, resp, 7); + i2c_read_block(i2cdev, 0, resp, sizeof(resp)); /* check retrieved time againt local time */ g_assert_cmpuint(bcd2bin(resp[4]), == , tm_ptr->tm_mday); @@ -53,23 +44,15 @@ static void send_and_receive(void) g_assert_cmpuint(2000 + bcd2bin(resp[6]), == , 1900 + tm_ptr->tm_year); } -int main(int argc, char **argv) +static void ds1338_register_nodes(void) { - QTestState *s = NULL; - int ret; - - g_test_init(&argc, &argv, NULL); - - s = qtest_start("-display none -machine imx25-pdk"); - i2c = imx_i2c_create(s, IMX25_I2C_0_BASE); - addr = DS1338_ADDR; - - qtest_add_func("/ds1338/tx-rx", send_and_receive); - - ret = g_test_run(); - - qtest_quit(s); - g_free(i2c); - - return ret; + QOSGraphEdgeOptions opts = { + .extra_device_opts = "address=0x68" + }; + add_qi2c_address(&opts, &(QI2CAddress) { DS1338_ADDR }); + + qos_node_create_driver("ds1338", i2c_device_create); + qos_node_consumes("ds1338", "i2c-bus", &opts); + qos_add_test("tx-rx", "ds1338", send_and_receive, NULL); } +libqos_init(ds1338_register_nodes); diff --git a/tests/libqos/arm-imx25-pdk-machine.c b/tests/libqos/arm-imx25-pdk-machine.c new file mode 100644 index 0000000000..25066fb8a9 --- /dev/null +++ b/tests/libqos/arm-imx25-pdk-machine.c @@ -0,0 +1,92 @@ +/* + * libqos driver framework + * + * Copyright (c) 2019 Red Hat, Inc. + * + * Author: Paolo Bonzini <pbonzini@redhat.com> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License version 2 as published by the Free Software Foundation. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, see <http://www.gnu.org/licenses/> + */ + +#include "qemu/osdep.h" +#include "libqtest.h" +#include "libqos/malloc.h" +#include "libqos/qgraph.h" +#include "libqos/i2c.h" + +#define ARM_PAGE_SIZE 4096 +#define IMX25_PDK_RAM_START 0x80000000 +#define IMX25_PDK_RAM_END 0x88000000 + +typedef struct QIMX25PDKMachine QIMX25PDKMachine; + +struct QIMX25PDKMachine { + QOSGraphObject obj; + QGuestAllocator alloc; + IMXI2C i2c_1; +}; + +static void *imx25_pdk_get_driver(void *object, const char *interface) +{ + QIMX25PDKMachine *machine = object; + if (!g_strcmp0(interface, "memory")) { + return &machine->alloc; + } + + fprintf(stderr, "%s not present in arm/imx25_pdk\n", interface); + g_assert_not_reached(); +} + +static QOSGraphObject *imx25_pdk_get_device(void *obj, const char *device) +{ + QIMX25PDKMachine *machine = obj; + if (!g_strcmp0(device, "imx.i2c")) { + return &machine->i2c_1.obj; + } + + fprintf(stderr, "%s not present in arm/imx25_pdk\n", device); + g_assert_not_reached(); +} + +static void imx25_pdk_destructor(QOSGraphObject *obj) +{ + QIMX25PDKMachine *machine = (QIMX25PDKMachine *) obj; + alloc_destroy(&machine->alloc); +} + +static void *qos_create_machine_arm_imx25_pdk(QTestState *qts) +{ + QIMX25PDKMachine *machine = g_new0(QIMX25PDKMachine, 1); + + alloc_init(&machine->alloc, 0, + IMX25_PDK_RAM_START, + IMX25_PDK_RAM_END, + ARM_PAGE_SIZE); + machine->obj.get_device = imx25_pdk_get_device; + machine->obj.get_driver = imx25_pdk_get_driver; + machine->obj.destructor = imx25_pdk_destructor; + + imx_i2c_init(&machine->i2c_1, qts, 0x43f80000); + return &machine->obj; +} + +static void imx25_pdk_register_nodes(void) +{ + QOSGraphEdgeOptions edge = { + .extra_device_opts = "bus=i2c-bus.0" + }; + qos_node_create_machine("arm/imx25-pdk", qos_create_machine_arm_imx25_pdk); + qos_node_contains("arm/imx25-pdk", "imx.i2c", &edge, NULL); +} + +libqos_init(imx25_pdk_register_nodes); diff --git a/tests/libqos/arm-n800-machine.c b/tests/libqos/arm-n800-machine.c new file mode 100644 index 0000000000..87279bdb26 --- /dev/null +++ b/tests/libqos/arm-n800-machine.c @@ -0,0 +1,92 @@ +/* + * libqos driver framework + * + * Copyright (c) 2019 Red Hat, Inc. + * + * Author: Paolo Bonzini <pbonzini@redhat.com> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License version 2 as published by the Free Software Foundation. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, see <http://www.gnu.org/licenses/> + */ + +#include "qemu/osdep.h" +#include "libqtest.h" +#include "libqos/malloc.h" +#include "libqos/qgraph.h" +#include "libqos/i2c.h" + +#define ARM_PAGE_SIZE 4096 +#define N800_RAM_START 0x80000000 +#define N800_RAM_END 0x88000000 + +typedef struct QN800Machine QN800Machine; + +struct QN800Machine { + QOSGraphObject obj; + QGuestAllocator alloc; + OMAPI2C i2c_1; +}; + +static void *n800_get_driver(void *object, const char *interface) +{ + QN800Machine *machine = object; + if (!g_strcmp0(interface, "memory")) { + return &machine->alloc; + } + + fprintf(stderr, "%s not present in arm/n800\n", interface); + g_assert_not_reached(); +} + +static QOSGraphObject *n800_get_device(void *obj, const char *device) +{ + QN800Machine *machine = obj; + if (!g_strcmp0(device, "omap_i2c")) { + return &machine->i2c_1.obj; + } + + fprintf(stderr, "%s not present in arm/n800\n", device); + g_assert_not_reached(); +} + +static void n800_destructor(QOSGraphObject *obj) +{ + QN800Machine *machine = (QN800Machine *) obj; + alloc_destroy(&machine->alloc); +} + +static void *qos_create_machine_arm_n800(QTestState *qts) +{ + QN800Machine *machine = g_new0(QN800Machine, 1); + + alloc_init(&machine->alloc, 0, + N800_RAM_START, + N800_RAM_END, + ARM_PAGE_SIZE); + machine->obj.get_device = n800_get_device; + machine->obj.get_driver = n800_get_driver; + machine->obj.destructor = n800_destructor; + + omap_i2c_init(&machine->i2c_1, qts, 0x48070000); + return &machine->obj; +} + +static void n800_register_nodes(void) +{ + QOSGraphEdgeOptions edge = { + .extra_device_opts = "bus=i2c-bus.0" + }; + qos_node_create_machine("arm/n800", qos_create_machine_arm_n800); + qos_node_contains("arm/n800", "omap_i2c", &edge, NULL); +} + +libqos_init(n800_register_nodes); diff --git a/tests/libqos/i2c-imx.c b/tests/libqos/i2c-imx.c index 0945f2ecdc..f33ece55a3 100644 --- a/tests/libqos/i2c-imx.c +++ b/tests/libqos/i2c-imx.c @@ -30,13 +30,6 @@ enum IMXI2CDirection { IMX_I2C_WRITE, }; -typedef struct IMXI2C { - I2CAdapter parent; - - uint64_t addr; -} IMXI2C; - - static void imx_i2c_set_slave_addr(IMXI2C *s, uint8_t addr, enum IMXI2CDirection direction) { @@ -47,7 +40,7 @@ static void imx_i2c_set_slave_addr(IMXI2C *s, uint8_t addr, static void imx_i2c_send(I2CAdapter *i2c, uint8_t addr, const uint8_t *buf, uint16_t len) { - IMXI2C *s = (IMXI2C *)i2c; + IMXI2C *s = container_of(i2c, IMXI2C, parent); uint8_t data; uint8_t status; uint16_t size = 0; @@ -107,7 +100,7 @@ static void imx_i2c_send(I2CAdapter *i2c, uint8_t addr, static void imx_i2c_recv(I2CAdapter *i2c, uint8_t addr, uint8_t *buf, uint16_t len) { - IMXI2C *s = (IMXI2C *)i2c; + IMXI2C *s = container_of(i2c, IMXI2C, parent); uint8_t data; uint8_t status; uint16_t size = 0; @@ -193,16 +186,31 @@ static void imx_i2c_recv(I2CAdapter *i2c, uint8_t addr, g_assert((status & I2SR_IBB) == 0); } -I2CAdapter *imx_i2c_create(QTestState *qts, uint64_t addr) +static void *imx_i2c_get_driver(void *obj, const char *interface) { - IMXI2C *s = g_malloc0(sizeof(*s)); - I2CAdapter *i2c = (I2CAdapter *)s; + IMXI2C *s = obj; + if (!g_strcmp0(interface, "i2c-bus")) { + return &s->parent; + } + fprintf(stderr, "%s not present in imx-i2c\n", interface); + g_assert_not_reached(); +} +void imx_i2c_init(IMXI2C *s, QTestState *qts, uint64_t addr) +{ s->addr = addr; - i2c->send = imx_i2c_send; - i2c->recv = imx_i2c_recv; - i2c->qts = qts; + s->obj.get_driver = imx_i2c_get_driver; - return i2c; + s->parent.send = imx_i2c_send; + s->parent.recv = imx_i2c_recv; + s->parent.qts = qts; } + +static void imx_i2c_register_nodes(void) +{ + qos_node_create_driver("imx.i2c", NULL); + qos_node_produces("imx.i2c", "i2c-bus"); +} + +libqos_init(imx_i2c_register_nodes); diff --git a/tests/libqos/i2c-omap.c b/tests/libqos/i2c-omap.c index 1ef6e7b200..9ae8214fa8 100644 --- a/tests/libqos/i2c-omap.c +++ b/tests/libqos/i2c-omap.c @@ -40,12 +40,6 @@ enum OMAPI2CCONBits { OMAP_I2C_CON_I2C_EN = 1 << 15, }; -typedef struct OMAPI2C { - I2CAdapter parent; - - uint64_t addr; -} OMAPI2C; - static void omap_i2c_set_slave_addr(OMAPI2C *s, uint8_t addr) { @@ -59,7 +53,7 @@ static void omap_i2c_set_slave_addr(OMAPI2C *s, uint8_t addr) static void omap_i2c_send(I2CAdapter *i2c, uint8_t addr, const uint8_t *buf, uint16_t len) { - OMAPI2C *s = (OMAPI2C *)i2c; + OMAPI2C *s = container_of(i2c, OMAPI2C, parent); uint16_t data; omap_i2c_set_slave_addr(s, addr); @@ -103,8 +97,9 @@ static void omap_i2c_send(I2CAdapter *i2c, uint8_t addr, static void omap_i2c_recv(I2CAdapter *i2c, uint8_t addr, uint8_t *buf, uint16_t len) { - OMAPI2C *s = (OMAPI2C *)i2c; + OMAPI2C *s = container_of(i2c, OMAPI2C, parent); uint16_t data, stat; + uint16_t orig_len = len; omap_i2c_set_slave_addr(s, addr); @@ -116,16 +111,24 @@ static void omap_i2c_recv(I2CAdapter *i2c, uint8_t addr, OMAP_I2C_CON_STT | OMAP_I2C_CON_STP; qtest_writew(i2c->qts, s->addr + OMAP_I2C_CON, data); - data = qtest_readw(i2c->qts, s->addr + OMAP_I2C_CON); - g_assert((data & OMAP_I2C_CON_STP) == 0); data = qtest_readw(i2c->qts, s->addr + OMAP_I2C_STAT); g_assert((data & OMAP_I2C_STAT_NACK) == 0); - data = qtest_readw(i2c->qts, s->addr + OMAP_I2C_CNT); - g_assert_cmpuint(data, ==, len); - while (len > 0) { + data = qtest_readw(i2c->qts, s->addr + OMAP_I2C_CON); + if (len <= 4) { + g_assert((data & OMAP_I2C_CON_STP) == 0); + + data = qtest_readw(i2c->qts, s->addr + OMAP_I2C_CNT); + g_assert_cmpuint(data, ==, orig_len); + } else { + g_assert((data & OMAP_I2C_CON_STP) != 0); + + data = qtest_readw(i2c->qts, s->addr + OMAP_I2C_CNT); + g_assert_cmpuint(data, ==, len - 4); + } + data = qtest_readw(i2c->qts, s->addr + OMAP_I2C_STAT); g_assert((data & OMAP_I2C_STAT_RRDY) != 0); g_assert((data & OMAP_I2C_STAT_ROVR) == 0); @@ -152,21 +155,42 @@ static void omap_i2c_recv(I2CAdapter *i2c, uint8_t addr, g_assert((data & OMAP_I2C_CON_STP) == 0); } -I2CAdapter *omap_i2c_create(QTestState *qts, uint64_t addr) +static void *omap_i2c_get_driver(void *obj, const char *interface) +{ + OMAPI2C *s = obj; + if (!g_strcmp0(interface, "i2c-bus")) { + return &s->parent; + } + fprintf(stderr, "%s not present in omap_i2c\n", interface); + g_assert_not_reached(); +} + +static void omap_i2c_start_hw(QOSGraphObject *object) { - OMAPI2C *s = g_malloc0(sizeof(*s)); - I2CAdapter *i2c = (I2CAdapter *)s; + OMAPI2C *s = (OMAPI2C *) object; uint16_t data; + /* verify the mmio address by looking for a known signature */ + data = qtest_readw(s->parent.qts, s->addr + OMAP_I2C_REV); + g_assert_cmphex(data, ==, 0x34); +} + +void omap_i2c_init(OMAPI2C *s, QTestState *qts, uint64_t addr) +{ s->addr = addr; - i2c->send = omap_i2c_send; - i2c->recv = omap_i2c_recv; - i2c->qts = qts; + s->obj.get_driver = omap_i2c_get_driver; + s->obj.start_hw = omap_i2c_start_hw; - /* verify the mmio address by looking for a known signature */ - data = qtest_readw(qts, addr + OMAP_I2C_REV); - g_assert_cmphex(data, ==, 0x34); + s->parent.send = omap_i2c_send; + s->parent.recv = omap_i2c_recv; + s->parent.qts = qts; +} - return i2c; +static void omap_i2c_register_nodes(void) +{ + qos_node_create_driver("omap_i2c", NULL); + qos_node_produces("omap_i2c", "i2c-bus"); } + +libqos_init(omap_i2c_register_nodes); diff --git a/tests/libqos/i2c.c b/tests/libqos/i2c.c index 23bc2a3eb2..156114e745 100644 --- a/tests/libqos/i2c.c +++ b/tests/libqos/i2c.c @@ -10,14 +10,76 @@ #include "libqos/i2c.h" #include "libqtest.h" -void i2c_send(I2CAdapter *i2c, uint8_t addr, - const uint8_t *buf, uint16_t len) +void i2c_send(QI2CDevice *i2cdev, const uint8_t *buf, uint16_t len) { - i2c->send(i2c, addr, buf, len); + i2cdev->bus->send(i2cdev->bus, i2cdev->addr, buf, len); } -void i2c_recv(I2CAdapter *i2c, uint8_t addr, - uint8_t *buf, uint16_t len) +void i2c_recv(QI2CDevice *i2cdev, uint8_t *buf, uint16_t len) { - i2c->recv(i2c, addr, buf, len); + i2cdev->bus->recv(i2cdev->bus, i2cdev->addr, buf, len); +} + +void i2c_read_block(QI2CDevice *i2cdev, uint8_t reg, + uint8_t *buf, uint16_t len) +{ + i2c_send(i2cdev, ®, 1); + i2c_recv(i2cdev, buf, len); +} + +void i2c_write_block(QI2CDevice *i2cdev, uint8_t reg, + const uint8_t *buf, uint16_t len) +{ + uint8_t *cmd = g_malloc(len + 1); + cmd[0] = reg; + memcpy(&cmd[1], buf, len); + i2c_send(i2cdev, cmd, len + 1); + g_free(cmd); +} + +uint8_t i2c_get8(QI2CDevice *i2cdev, uint8_t reg) +{ + uint8_t resp[1]; + i2c_read_block(i2cdev, reg, resp, sizeof(resp)); + return resp[0]; +} + +uint16_t i2c_get16(QI2CDevice *i2cdev, uint8_t reg) +{ + uint8_t resp[2]; + i2c_read_block(i2cdev, reg, resp, sizeof(resp)); + return (resp[0] << 8) | resp[1]; +} + +void i2c_set8(QI2CDevice *i2cdev, uint8_t reg, uint8_t value) +{ + i2c_write_block(i2cdev, reg, &value, 1); +} + +void i2c_set16(QI2CDevice *i2cdev, uint8_t reg, uint16_t value) +{ + uint8_t data[2]; + + data[0] = value >> 8; + data[1] = value & 255; + i2c_write_block(i2cdev, reg, data, sizeof(data)); +} + +void *i2c_device_create(void *i2c_bus, QGuestAllocator *alloc, void *addr) +{ + QI2CDevice *i2cdev = g_new0(QI2CDevice, 1); + + i2cdev->bus = i2c_bus; + if (addr) { + i2cdev->addr = ((QI2CAddress *)addr)->addr; + } + return &i2cdev->obj; +} + +void add_qi2c_address(QOSGraphEdgeOptions *opts, QI2CAddress *addr) +{ + g_assert(addr); + + opts->arg = addr; + opts->size_arg = sizeof(QI2CAddress); } diff --git a/tests/libqos/i2c.h b/tests/libqos/i2c.h index cc01358a9f..945b65b34c 100644 --- a/tests/libqos/i2c.h +++ b/tests/libqos/i2c.h @@ -10,6 +10,7 @@ #define LIBQOS_I2C_H #include "libqtest.h" +#include "libqos/qgraph.h" typedef struct I2CAdapter I2CAdapter; struct I2CAdapter { @@ -21,17 +22,61 @@ struct I2CAdapter { QTestState *qts; }; -#define OMAP2_I2C_1_BASE 0x48070000 +typedef struct QI2CAddress QI2CAddress; +struct QI2CAddress { + uint8_t addr; +}; + +typedef struct QI2CDevice QI2CDevice; +struct QI2CDevice { + /* + * For now, all devices are simple enough that there is no need for + * them to define their own constructor and get_driver functions. + * Therefore, QOSGraphObject is included directly in QI2CDevice; + * the tests expect to get a QI2CDevice rather than doing something + * like obj->get_driver("i2c-device"). + * + * In fact there is no i2c-device interface even, because there are + * no generic I2C tests). + */ + QOSGraphObject obj; + I2CAdapter *bus; + uint8_t addr; +}; + +void *i2c_device_create(void *i2c_bus, QGuestAllocator *alloc, void *addr); +void add_qi2c_address(QOSGraphEdgeOptions *opts, QI2CAddress *addr); + +void i2c_send(QI2CDevice *dev, const uint8_t *buf, uint16_t len); +void i2c_recv(QI2CDevice *dev, uint8_t *buf, uint16_t len); + +void i2c_read_block(QI2CDevice *dev, uint8_t reg, + uint8_t *buf, uint16_t len); +void i2c_write_block(QI2CDevice *dev, uint8_t reg, + const uint8_t *buf, uint16_t len); +uint8_t i2c_get8(QI2CDevice *dev, uint8_t reg); +uint16_t i2c_get16(QI2CDevice *dev, uint8_t reg); +void i2c_set8(QI2CDevice *dev, uint8_t reg, uint8_t value); +void i2c_set16(QI2CDevice *dev, uint8_t reg, uint16_t value); + +/* i2c-omap.c */ +typedef struct OMAPI2C { + QOSGraphObject obj; + I2CAdapter parent; + + uint64_t addr; +} OMAPI2C; + +void omap_i2c_init(OMAPI2C *s, QTestState *qts, uint64_t addr); -void i2c_send(I2CAdapter *i2c, uint8_t addr, - const uint8_t *buf, uint16_t len); -void i2c_recv(I2CAdapter *i2c, uint8_t addr, - uint8_t *buf, uint16_t len); +/* i2c-imx.c */ +typedef struct IMXI2C { + QOSGraphObject obj; + I2CAdapter parent; -/* libi2c-omap.c */ -I2CAdapter *omap_i2c_create(QTestState *qts, uint64_t addr); + uint64_t addr; +} IMXI2C; -/* libi2c-imx.c */ -I2CAdapter *imx_i2c_create(QTestState *qts, uint64_t addr); +void imx_i2c_init(IMXI2C *s, QTestState *qts, uint64_t addr); #endif diff --git a/tests/libqos/qgraph.c b/tests/libqos/qgraph.c index b149caaaa9..7a7ae2a19e 100644 --- a/tests/libqos/qgraph.c +++ b/tests/libqos/qgraph.c @@ -632,15 +632,19 @@ void qos_node_create_driver(const char *name, QOSCreateDriverFunc function) } void qos_node_contains(const char *container, const char *contained, - ...) + QOSGraphEdgeOptions *opts, ...) { va_list va; - va_start(va, contained); - QOSGraphEdgeOptions *opts; + if (opts == NULL) { + add_edge(container, contained, QEDGE_CONTAINS, NULL); + return; + } + + va_start(va, opts); do { - opts = va_arg(va, QOSGraphEdgeOptions *); add_edge(container, contained, QEDGE_CONTAINS, opts); + opts = va_arg(va, QOSGraphEdgeOptions *); } while (opts != NULL); va_end(va); diff --git a/tests/libqos/qgraph.h b/tests/libqos/qgraph.h index e799095b30..3a25dda4b2 100644 --- a/tests/libqos/qgraph.h +++ b/tests/libqos/qgraph.h @@ -453,14 +453,16 @@ void qos_node_create_machine_args(const char *name, void qos_node_create_driver(const char *name, QOSCreateDriverFunc function); /** - * qos_node_contains(): creates an edge of type QEDGE_CONTAINS and - * adds it to the edge list mapped to @container in the + * qos_node_contains(): creates one or more edges of type QEDGE_CONTAINS + * and adds them to the edge list mapped to @container in the * edge hash table. * - * This edge will have @container as source and @contained as destination. + * The edges will have @container as source and @contained as destination. * - * It also has the possibility to add optional NULL-terminated - * @opts parameters (see %QOSGraphEdgeOptions) + * If @opts is NULL, a single edge will be added with no options. + * If @opts is non-NULL, the arguments after @contained represent a + * NULL-terminated list of %QOSGraphEdgeOptions structs, and an + * edge will be added for each of them. * * This function can be useful when there are multiple devices * with the same node name contained in a machine/other node @@ -480,7 +482,8 @@ void qos_node_create_driver(const char *name, QOSCreateDriverFunc function); * For contains, op1.arg and op1.size_arg represent the arg to pass * to @contained constructor to properly initialize it. */ -void qos_node_contains(const char *container, const char *contained, ...); +void qos_node_contains(const char *container, const char *contained, + QOSGraphEdgeOptions *opts, ...); /** * qos_node_produces(): creates an edge of type QEDGE_PRODUCES and diff --git a/tests/libqtest.c b/tests/libqtest.c index 8ac0c02af4..9b9b5f37fc 100644 --- a/tests/libqtest.c +++ b/tests/libqtest.c @@ -32,6 +32,7 @@ #define MAX_IRQ 256 #define SOCKET_TIMEOUT 50 +#define SOCKET_MAX_FDS 16 QTestState *global_qtest; @@ -391,6 +392,40 @@ static void GCC_FMT_ATTR(2, 3) qtest_sendf(QTestState *s, const char *fmt, ...) va_end(ap); } +/* Sends a message and file descriptors to the socket. + * It's needed for qmp-commands like getfd/add-fd */ +static void socket_send_fds(int socket_fd, int *fds, size_t fds_num, + const char *buf, size_t buf_size) +{ + ssize_t ret; + struct msghdr msg = { 0 }; + char control[CMSG_SPACE(sizeof(int) * SOCKET_MAX_FDS)] = { 0 }; + size_t fdsize = sizeof(int) * fds_num; + struct cmsghdr *cmsg; + struct iovec iov = { .iov_base = (char *)buf, .iov_len = buf_size }; + + msg.msg_iov = &iov; + msg.msg_iovlen = 1; + + if (fds && fds_num > 0) { + g_assert_cmpuint(fds_num, <, SOCKET_MAX_FDS); + + msg.msg_control = control; + msg.msg_controllen = CMSG_SPACE(fdsize); + + cmsg = CMSG_FIRSTHDR(&msg); + cmsg->cmsg_len = CMSG_LEN(fdsize); + cmsg->cmsg_level = SOL_SOCKET; + cmsg->cmsg_type = SCM_RIGHTS; + memcpy(CMSG_DATA(cmsg), fds, fdsize); + } + + do { + ret = sendmsg(socket_fd, &msg, 0); + } while (ret < 0 && errno == EINTR); + g_assert_cmpint(ret, >, 0); +} + static GString *qtest_recv_line(QTestState *s) { GString *line; @@ -545,7 +580,8 @@ QDict *qtest_qmp_receive(QTestState *s) * in the case that they choose to discard all replies up until * a particular EVENT is received. */ -void qmp_fd_vsend(int fd, const char *fmt, va_list ap) +void qmp_fd_vsend_fds(int fd, int *fds, size_t fds_num, + const char *fmt, va_list ap) { QObject *qobj; @@ -569,25 +605,49 @@ void qmp_fd_vsend(int fd, const char *fmt, va_list ap) fprintf(stderr, "%s", str); } /* Send QMP request */ - socket_send(fd, str, qstring_get_length(qstr)); + if (fds && fds_num > 0) { + socket_send_fds(fd, fds, fds_num, str, qstring_get_length(qstr)); + } else { + socket_send(fd, str, qstring_get_length(qstr)); + } qobject_unref(qstr); qobject_unref(qobj); } } +void qmp_fd_vsend(int fd, const char *fmt, va_list ap) +{ + qmp_fd_vsend_fds(fd, NULL, 0, fmt, ap); +} + +void qtest_qmp_vsend_fds(QTestState *s, int *fds, size_t fds_num, + const char *fmt, va_list ap) +{ + qmp_fd_vsend_fds(s->qmp_fd, fds, fds_num, fmt, ap); +} + void qtest_qmp_vsend(QTestState *s, const char *fmt, va_list ap) { - qmp_fd_vsend(s->qmp_fd, fmt, ap); + qmp_fd_vsend_fds(s->qmp_fd, NULL, 0, fmt, ap); } QDict *qmp_fdv(int fd, const char *fmt, va_list ap) { - qmp_fd_vsend(fd, fmt, ap); + qmp_fd_vsend_fds(fd, NULL, 0, fmt, ap); return qmp_fd_receive(fd); } +QDict *qtest_vqmp_fds(QTestState *s, int *fds, size_t fds_num, + const char *fmt, va_list ap) +{ + qtest_qmp_vsend_fds(s, fds, fds_num, fmt, ap); + + /* Receive reply */ + return qtest_qmp_receive(s); +} + QDict *qtest_vqmp(QTestState *s, const char *fmt, va_list ap) { qtest_qmp_vsend(s, fmt, ap); @@ -616,6 +676,18 @@ void qmp_fd_send(int fd, const char *fmt, ...) va_end(ap); } +QDict *qtest_qmp_fds(QTestState *s, int *fds, size_t fds_num, + const char *fmt, ...) +{ + va_list ap; + QDict *response; + + va_start(ap, fmt); + response = qtest_vqmp_fds(s, fds, fds_num, fmt, ap); + va_end(ap); + return response; +} + QDict *qtest_qmp(QTestState *s, const char *fmt, ...) { va_list ap; @@ -1038,6 +1110,25 @@ QDict *qmp(const char *fmt, ...) return response; } +void qmp_assert_success(const char *fmt, ...) +{ + va_list ap; + QDict *response; + + va_start(ap, fmt); + response = qtest_vqmp(global_qtest, fmt, ap); + va_end(ap); + + g_assert(response); + if (!qdict_haskey(response, "return")) { + QString *s = qobject_to_json_pretty(QOBJECT(response)); + g_test_message("%s", qstring_get_str(s)); + qobject_unref(s); + } + g_assert(qdict_haskey(response, "return")); + qobject_unref(response); +} + char *hmp(const char *fmt, ...) { va_list ap; diff --git a/tests/libqtest.h b/tests/libqtest.h index a98ea15b7d..cadf1d4a03 100644 --- a/tests/libqtest.h +++ b/tests/libqtest.h @@ -85,6 +85,21 @@ QTestState *qtest_init_with_serial(const char *extra_args, int *sock_fd); void qtest_quit(QTestState *s); /** + * qtest_qmp_fds: + * @s: #QTestState instance to operate on. + * @fds: array of file descriptors + * @fds_num: number of elements in @fds + * @fmt...: QMP message to send to qemu, formatted like + * qobject_from_jsonf_nofail(). See parse_escape() for what's + * supported after '%'. + * + * Sends a QMP message to QEMU with fds and returns the response. + */ +QDict *qtest_qmp_fds(QTestState *s, int *fds, size_t fds_num, + const char *fmt, ...) + GCC_FMT_ATTR(4, 5); + +/** * qtest_qmp: * @s: #QTestState instance to operate on. * @fmt...: QMP message to send to qemu, formatted like @@ -120,7 +135,23 @@ void qtest_qmp_send_raw(QTestState *s, const char *fmt, ...) GCC_FMT_ATTR(2, 3); /** - * qtest_qmpv: + * qtest_vqmp_fds: + * @s: #QTestState instance to operate on. + * @fds: array of file descriptors + * @fds_num: number of elements in @fds + * @fmt: QMP message to send to QEMU, formatted like + * qobject_from_jsonf_nofail(). See parse_escape() for what's + * supported after '%'. + * @ap: QMP message arguments + * + * Sends a QMP message to QEMU with fds and returns the response. + */ +QDict *qtest_vqmp_fds(QTestState *s, int *fds, size_t fds_num, + const char *fmt, va_list ap) + GCC_FMT_ATTR(4, 0); + +/** + * qtest_vqmp: * @s: #QTestState instance to operate on. * @fmt: QMP message to send to QEMU, formatted like * qobject_from_jsonf_nofail(). See parse_escape() for what's @@ -133,6 +164,22 @@ QDict *qtest_vqmp(QTestState *s, const char *fmt, va_list ap) GCC_FMT_ATTR(2, 0); /** + * qtest_qmp_vsend_fds: + * @s: #QTestState instance to operate on. + * @fds: array of file descriptors + * @fds_num: number of elements in @fds + * @fmt: QMP message to send to QEMU, formatted like + * qobject_from_jsonf_nofail(). See parse_escape() for what's + * supported after '%'. + * @ap: QMP message arguments + * + * Sends a QMP message to QEMU and leaves the response in the stream. + */ +void qtest_qmp_vsend_fds(QTestState *s, int *fds, size_t fds_num, + const char *fmt, va_list ap) + GCC_FMT_ATTR(4, 0); + +/** * qtest_qmp_vsend: * @s: #QTestState instance to operate on. * @fmt: QMP message to send to QEMU, formatted like @@ -619,6 +666,17 @@ static inline void qtest_end(void) QDict *qmp(const char *fmt, ...) GCC_FMT_ATTR(1, 2); /** + * qmp_assert_success: + * @fmt...: QMP message to send to qemu, formatted like + * qobject_from_jsonf_nofail(). See parse_escape() for what's + * supported after '%'. + * + * Sends a QMP message to QEMU and asserts that a 'return' key is present in + * the response. + */ +void qmp_assert_success(const char *fmt, ...) GCC_FMT_ATTR(1, 2); + +/* * qmp_eventwait: * @s: #event event to wait for. * @@ -877,6 +935,8 @@ static inline int64_t clock_step(int64_t step) } QDict *qmp_fd_receive(int fd); +void qmp_fd_vsend_fds(int fd, int *fds, size_t fds_num, + const char *fmt, va_list ap) GCC_FMT_ATTR(4, 0); void qmp_fd_vsend(int fd, const char *fmt, va_list ap) GCC_FMT_ATTR(2, 0); void qmp_fd_send(int fd, const char *fmt, ...) GCC_FMT_ATTR(2, 3); void qmp_fd_send_raw(int fd, const char *fmt, ...) GCC_FMT_ATTR(2, 3); diff --git a/tests/migration-test.c b/tests/migration-test.c index bd3f5c3125..e0407576cb 100644 --- a/tests/migration-test.c +++ b/tests/migration-test.c @@ -177,6 +177,21 @@ static void stop_cb(void *opaque, const char *name, QDict *data) /* * Events can get in the way of responses we are actually waiting for. */ +GCC_FMT_ATTR(3, 4) +static QDict *wait_command_fd(QTestState *who, int fd, const char *command, ...) +{ + va_list ap; + + va_start(ap, command); + qtest_qmp_vsend_fds(who, &fd, 1, command, ap); + va_end(ap); + + return qtest_qmp_receive_success(who, stop_cb, NULL); +} + +/* + * Events can get in the way of responses we are actually waiting for. + */ GCC_FMT_ATTR(2, 3) static QDict *wait_command(QTestState *who, const char *command, ...) { @@ -480,6 +495,7 @@ static void migrate(QTestState *who, const char *uri, const char *fmt, ...) qdict_put_str(args, "uri", uri); rsp = qmp("{ 'execute': 'migrate', 'arguments': %p}", args); + g_assert(qdict_haskey(rsp, "return")); qobject_unref(rsp); } @@ -1027,6 +1043,90 @@ static void test_precopy_tcp(void) g_free(uri); } +static void test_migrate_fd_proto(void) +{ + QTestState *from, *to; + int ret; + int pair[2]; + QDict *rsp; + const char *error_desc; + + if (test_migrate_start(&from, &to, "defer", false, false)) { + return; + } + + /* + * We want to pick a speed slow enough that the test completes + * quickly, but that it doesn't complete precopy even on a slow + * machine, so also set the downtime. + */ + /* 1 ms should make it not converge */ + migrate_set_parameter(from, "downtime-limit", 1); + /* 1GB/s */ + migrate_set_parameter(from, "max-bandwidth", 1000000000); + + /* Wait for the first serial output from the source */ + wait_for_serial("src_serial"); + + /* Create two connected sockets for migration */ + ret = socketpair(PF_LOCAL, SOCK_STREAM, 0, pair); + g_assert_cmpint(ret, ==, 0); + + /* Send the 1st socket to the target */ + rsp = wait_command_fd(to, pair[0], + "{ 'execute': 'getfd'," + " 'arguments': { 'fdname': 'fd-mig' }}"); + qobject_unref(rsp); + close(pair[0]); + + /* Start incoming migration from the 1st socket */ + rsp = wait_command(to, "{ 'execute': 'migrate-incoming'," + " 'arguments': { 'uri': 'fd:fd-mig' }}"); + qobject_unref(rsp); + + /* Send the 2nd socket to the target */ + rsp = wait_command_fd(from, pair[1], + "{ 'execute': 'getfd'," + " 'arguments': { 'fdname': 'fd-mig' }}"); + qobject_unref(rsp); + close(pair[1]); + + /* Start migration to the 2nd socket*/ + migrate(from, "fd:fd-mig", "{}"); + + wait_for_migration_pass(from); + + /* 300ms should converge */ + migrate_set_parameter(from, "downtime-limit", 300); + + if (!got_stop) { + qtest_qmp_eventwait(from, "STOP"); + } + qtest_qmp_eventwait(to, "RESUME"); + + /* Test closing fds */ + /* We assume, that QEMU removes named fd from its list, + * so this should fail */ + rsp = qtest_qmp(from, "{ 'execute': 'closefd'," + " 'arguments': { 'fdname': 'fd-mig' }}"); + g_assert_true(qdict_haskey(rsp, "error")); + error_desc = qdict_get_str(qdict_get_qdict(rsp, "error"), "desc"); + g_assert_cmpstr(error_desc, ==, "File descriptor named 'fd-mig' not found"); + qobject_unref(rsp); + + rsp = qtest_qmp(to, "{ 'execute': 'closefd'," + " 'arguments': { 'fdname': 'fd-mig' }}"); + g_assert_true(qdict_haskey(rsp, "error")); + error_desc = qdict_get_str(qdict_get_qdict(rsp, "error"), "desc"); + g_assert_cmpstr(error_desc, ==, "File descriptor named 'fd-mig' not found"); + qobject_unref(rsp); + + /* Complete migration */ + wait_for_serial("dest_serial"); + wait_for_migration_complete(from); + test_migrate_end(from, to, true); +} + int main(int argc, char **argv) { char template[] = "/tmp/migration-test-XXXXXX"; @@ -1081,6 +1181,7 @@ int main(int argc, char **argv) qtest_add_func("/migration/precopy/tcp", test_precopy_tcp); /* qtest_add_func("/migration/ignore_shared", test_ignore_shared); */ qtest_add_func("/migration/xbzrle/unix", test_xbzrle_unix); + qtest_add_func("/migration/fd_proto", test_migrate_fd_proto); ret = g_test_run(); diff --git a/tests/pca9552-test.c b/tests/pca9552-test.c index 5466a67ed7..4b800d3c3e 100644 --- a/tests/pca9552-test.c +++ b/tests/pca9552-test.c @@ -10,107 +10,84 @@ #include "qemu/osdep.h" #include "libqtest.h" +#include "libqos/qgraph.h" #include "libqos/i2c.h" #include "hw/misc/pca9552_regs.h" #define PCA9552_TEST_ID "pca9552-test" #define PCA9552_TEST_ADDR 0x60 -static I2CAdapter *i2c; - -static uint8_t pca9552_get8(I2CAdapter *i2c, uint8_t addr, uint8_t reg) +static void pca9552_init(QI2CDevice *i2cdev) { - uint8_t resp[1]; - i2c_send(i2c, addr, ®, 1); - i2c_recv(i2c, addr, resp, 1); - return resp[0]; + /* Switch on LEDs 0 and 12 */ + i2c_set8(i2cdev, PCA9552_LS0, 0x54); + i2c_set8(i2cdev, PCA9552_LS3, 0x54); } -static void pca9552_set8(I2CAdapter *i2c, uint8_t addr, uint8_t reg, - uint8_t value) -{ - uint8_t cmd[2]; - uint8_t resp[1]; - - cmd[0] = reg; - cmd[1] = value; - i2c_send(i2c, addr, cmd, 2); - i2c_recv(i2c, addr, resp, 1); - g_assert_cmphex(resp[0], ==, cmd[1]); -} - -static void receive_autoinc(void) +static void receive_autoinc(void *obj, void *data, QGuestAllocator *alloc) { + QI2CDevice *i2cdev = (QI2CDevice *)obj; uint8_t resp; uint8_t reg = PCA9552_LS0 | PCA9552_AUTOINC; - i2c_send(i2c, PCA9552_TEST_ADDR, ®, 1); + pca9552_init(i2cdev); + + i2c_send(i2cdev, ®, 1); /* PCA9552_LS0 */ - i2c_recv(i2c, PCA9552_TEST_ADDR, &resp, 1); + i2c_recv(i2cdev, &resp, 1); g_assert_cmphex(resp, ==, 0x54); /* PCA9552_LS1 */ - i2c_recv(i2c, PCA9552_TEST_ADDR, &resp, 1); + i2c_recv(i2cdev, &resp, 1); g_assert_cmphex(resp, ==, 0x55); /* PCA9552_LS2 */ - i2c_recv(i2c, PCA9552_TEST_ADDR, &resp, 1); + i2c_recv(i2cdev, &resp, 1); g_assert_cmphex(resp, ==, 0x55); /* PCA9552_LS3 */ - i2c_recv(i2c, PCA9552_TEST_ADDR, &resp, 1); + i2c_recv(i2cdev, &resp, 1); g_assert_cmphex(resp, ==, 0x54); } -static void send_and_receive(void) +static void send_and_receive(void *obj, void *data, QGuestAllocator *alloc) { + QI2CDevice *i2cdev = (QI2CDevice *)obj; uint8_t value; - value = pca9552_get8(i2c, PCA9552_TEST_ADDR, PCA9552_LS0); + value = i2c_get8(i2cdev, PCA9552_LS0); g_assert_cmphex(value, ==, 0x55); - value = pca9552_get8(i2c, PCA9552_TEST_ADDR, PCA9552_INPUT0); + value = i2c_get8(i2cdev, PCA9552_INPUT0); g_assert_cmphex(value, ==, 0x0); - /* Switch on LED 0 */ - pca9552_set8(i2c, PCA9552_TEST_ADDR, PCA9552_LS0, 0x54); - value = pca9552_get8(i2c, PCA9552_TEST_ADDR, PCA9552_LS0); + pca9552_init(i2cdev); + + value = i2c_get8(i2cdev, PCA9552_LS0); g_assert_cmphex(value, ==, 0x54); - value = pca9552_get8(i2c, PCA9552_TEST_ADDR, PCA9552_INPUT0); + value = i2c_get8(i2cdev, PCA9552_INPUT0); g_assert_cmphex(value, ==, 0x01); - /* Switch on LED 12 */ - pca9552_set8(i2c, PCA9552_TEST_ADDR, PCA9552_LS3, 0x54); - value = pca9552_get8(i2c, PCA9552_TEST_ADDR, PCA9552_LS3); + value = i2c_get8(i2cdev, PCA9552_LS3); g_assert_cmphex(value, ==, 0x54); - value = pca9552_get8(i2c, PCA9552_TEST_ADDR, PCA9552_INPUT1); + value = i2c_get8(i2cdev, PCA9552_INPUT1); g_assert_cmphex(value, ==, 0x10); } -int main(int argc, char **argv) +static void pca9552_register_nodes(void) { - QTestState *s = NULL; - int ret; - - g_test_init(&argc, &argv, NULL); - - s = qtest_start("-machine n800 " - "-device pca9552,bus=i2c-bus.0,id=" PCA9552_TEST_ID - ",address=0x60"); - i2c = omap_i2c_create(s, OMAP2_I2C_1_BASE); - - qtest_add_func("/pca9552/tx-rx", send_and_receive); - qtest_add_func("/pca9552/rx-autoinc", receive_autoinc); - - ret = g_test_run(); + QOSGraphEdgeOptions opts = { + .extra_device_opts = "address=0x60" + }; + add_qi2c_address(&opts, &(QI2CAddress) { 0x60 }); - if (s) { - qtest_quit(s); - } - g_free(i2c); + qos_node_create_driver("pca9552", i2c_device_create); + qos_node_consumes("pca9552", "i2c-bus", &opts); - return ret; + qos_add_test("tx-rx", "pca9552", send_and_receive, NULL); + qos_add_test("rx-autoinc", "pca9552", receive_autoinc, NULL); } +libqos_init(pca9552_register_nodes); diff --git a/tests/perf/block/qcow2/convert-blockstatus b/tests/perf/block/qcow2/convert-blockstatus new file mode 100755 index 0000000000..a1a3c1ef43 --- /dev/null +++ b/tests/perf/block/qcow2/convert-blockstatus @@ -0,0 +1,71 @@ +#!/bin/bash +# +# Test lseek influence on qcow2 block-status +# +# Block layer may recursively check block_status in file child of qcow2, if +# qcow2 driver returned DATA. There are several test cases to check influence +# of lseek on block_status performance. To see real difference run on tmpfs. +# +# Copyright (c) 2019 Virtuozzo International GmbH. All rights reserved. +# +# Tests originally written by Kevin Wolf +# +# This program 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, see <http://www.gnu.org/licenses/>. +# + +if [ "$#" -lt 1 ]; then + echo "Usage: $0 SOURCE_FILE" + exit 1 +fi + +ROOT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )/../../../.." >/dev/null 2>&1 && pwd )" +QEMU_IMG="$ROOT_DIR/qemu-img" +QEMU_IO="$ROOT_DIR/qemu-io" + +size=1G +src="$1" + +# test-case plain + +( +$QEMU_IMG create -f qcow2 "$src" $size +for i in $(seq 16384 -1 0); do + echo "write $((i * 65536)) 64k" +done | $QEMU_IO "$src" +) > /dev/null + +echo -n "plain: " +/usr/bin/time -f %e $QEMU_IMG convert -n "$src" null-co:// + +# test-case forward + +( +$QEMU_IMG create -f qcow2 "$src" $size +for i in $(seq 0 2 16384); do + echo "write $((i * 65536)) 64k" +done | $QEMU_IO "$src" +for i in $(seq 1 2 16384); do + echo "write $((i * 65536)) 64k" +done | $QEMU_IO "$src" +) > /dev/null + +echo -n "forward: " +/usr/bin/time -f %e $QEMU_IMG convert -n "$src" null-co:// + +# test-case prealloc + +$QEMU_IMG create -f qcow2 -o preallocation=metadata "$src" $size > /dev/null + +echo -n "prealloc: " +/usr/bin/time -f %e $QEMU_IMG convert -n "$src" null-co:// diff --git a/tests/qemu-iotests/051 b/tests/qemu-iotests/051 index a3deb1fcad..200660f977 100755 --- a/tests/qemu-iotests/051 +++ b/tests/qemu-iotests/051 @@ -192,6 +192,30 @@ case "$QEMU_DEFAULT_MACHINE" in esac echo +echo === Attach to node in non-default iothread === +echo + +case "$QEMU_DEFAULT_MACHINE" in + pc) + iothread="-drive file=$TEST_IMG,if=none,node-name=disk -object iothread,id=thread0 -device virtio-scsi,iothread=thread0,id=virtio-scsi0 -device scsi-hd,bus=virtio-scsi0.0,drive=disk,share-rw=on" + + # Can't add a device in the main thread while virtio-scsi0 uses the node + run_qemu $iothread -device ide-hd,drive=disk,share-rw=on + run_qemu $iothread -device virtio-blk-pci,drive=disk,share-rw=on + run_qemu $iothread -device lsi53c895a,id=lsi0 -device scsi-hd,bus=lsi0.0,drive=disk,share-rw=on + run_qemu $iothread -device virtio-scsi,id=virtio-scsi1 -device scsi-hd,bus=virtio-scsi1.0,drive=disk,share-rw=on + + # virtio-blk enables the iothread only when the driver initialises the + # device, so a second virtio-blk device can't be added even with the + # same iothread. virtio-scsi allows this. + run_qemu $iothread -device virtio-blk-pci,drive=disk,iohtread=iothread0,share-rw=on + run_qemu $iothread -device virtio-scsi,id=virtio-scsi1,iothread=thread0 -device scsi-hd,bus=virtio-scsi1.0,drive=disk,share-rw=on + ;; + *) + ;; +esac + +echo echo === Read-only === echo diff --git a/tests/qemu-iotests/051.out b/tests/qemu-iotests/051.out index 9f1cf22608..8993835b94 100644 --- a/tests/qemu-iotests/051.out +++ b/tests/qemu-iotests/051.out @@ -137,6 +137,9 @@ QEMU X.Y.Z monitor - type 'help' for more information (qemu) QEMU_PROG: -drive if=virtio: Device needs media, but drive is empty +=== Attach to node in non-default iothread === + + === Read-only === Testing: -drive file=TEST_DIR/t.qcow2,if=virtio,readonly=on diff --git a/tests/qemu-iotests/051.pc.out b/tests/qemu-iotests/051.pc.out index c4743cc31c..2d811c166c 100644 --- a/tests/qemu-iotests/051.pc.out +++ b/tests/qemu-iotests/051.pc.out @@ -173,6 +173,33 @@ QEMU X.Y.Z monitor - type 'help' for more information (qemu) QEMU_PROG: -device scsi-hd,drive=disk: Device needs media, but drive is empty +=== Attach to node in non-default iothread === + +Testing: -drive file=TEST_DIR/t.qcow2,if=none,node-name=disk -object iothread,id=thread0 -device virtio-scsi,iothread=thread0,id=virtio-scsi0 -device scsi-hd,bus=virtio-scsi0.0,drive=disk,share-rw=on -device ide-hd,drive=disk,share-rw=on +QEMU X.Y.Z monitor - type 'help' for more information +(qemu) QEMU_PROG: -device ide-hd,drive=disk,share-rw=on: Cannot change iothread of active block backend + +Testing: -drive file=TEST_DIR/t.qcow2,if=none,node-name=disk -object iothread,id=thread0 -device virtio-scsi,iothread=thread0,id=virtio-scsi0 -device scsi-hd,bus=virtio-scsi0.0,drive=disk,share-rw=on -device virtio-blk-pci,drive=disk,share-rw=on +QEMU X.Y.Z monitor - type 'help' for more information +(qemu) QEMU_PROG: -device virtio-blk-pci,drive=disk,share-rw=on: Cannot change iothread of active block backend + +Testing: -drive file=TEST_DIR/t.qcow2,if=none,node-name=disk -object iothread,id=thread0 -device virtio-scsi,iothread=thread0,id=virtio-scsi0 -device scsi-hd,bus=virtio-scsi0.0,drive=disk,share-rw=on -device lsi53c895a,id=lsi0 -device scsi-hd,bus=lsi0.0,drive=disk,share-rw=on +QEMU X.Y.Z monitor - type 'help' for more information +(qemu) QEMU_PROG: -device scsi-hd,bus=lsi0.0,drive=disk,share-rw=on: HBA does not support iothreads + +Testing: -drive file=TEST_DIR/t.qcow2,if=none,node-name=disk -object iothread,id=thread0 -device virtio-scsi,iothread=thread0,id=virtio-scsi0 -device scsi-hd,bus=virtio-scsi0.0,drive=disk,share-rw=on -device virtio-scsi,id=virtio-scsi1 -device scsi-hd,bus=virtio-scsi1.0,drive=disk,share-rw=on +QEMU X.Y.Z monitor - type 'help' for more information +(qemu) QEMU_PROG: -device scsi-hd,bus=virtio-scsi1.0,drive=disk,share-rw=on: Cannot change iothread of active block backend + +Testing: -drive file=TEST_DIR/t.qcow2,if=none,node-name=disk -object iothread,id=thread0 -device virtio-scsi,iothread=thread0,id=virtio-scsi0 -device scsi-hd,bus=virtio-scsi0.0,drive=disk,share-rw=on -device virtio-blk-pci,drive=disk,iohtread=iothread0,share-rw=on +QEMU X.Y.Z monitor - type 'help' for more information +(qemu) QEMU_PROG: -device virtio-blk-pci,drive=disk,iohtread=iothread0,share-rw=on: Cannot change iothread of active block backend + +Testing: -drive file=TEST_DIR/t.qcow2,if=none,node-name=disk -object iothread,id=thread0 -device virtio-scsi,iothread=thread0,id=virtio-scsi0 -device scsi-hd,bus=virtio-scsi0.0,drive=disk,share-rw=on -device virtio-scsi,id=virtio-scsi1,iothread=thread0 -device scsi-hd,bus=virtio-scsi1.0,drive=disk,share-rw=on +QEMU X.Y.Z monitor - type 'help' for more information +(qemu) quit + + === Read-only === Testing: -drive file=TEST_DIR/t.qcow2,if=floppy,readonly=on diff --git a/tests/qemu-iotests/056 b/tests/qemu-iotests/056 index 3df323984d..f40fc11a09 100755 --- a/tests/qemu-iotests/056 +++ b/tests/qemu-iotests/056 @@ -214,7 +214,7 @@ class BackupTest(iotests.QMPTestCase): res = self.vm.qmp('query-block-jobs') self.assert_qmp(res, 'return[0]/status', 'concluded') # Leave zombie job un-dismissed, observe a failure: - res = self.qmp_backup_and_wait(serror='Need a root block node', + res = self.qmp_backup_and_wait(serror="Node 'drive0' is busy: block device is in use by block job: backup", device='drive0', format=iotests.imgfmt, sync='full', target=self.dest_img, auto_dismiss=False) diff --git a/tests/qemu-iotests/060 b/tests/qemu-iotests/060 index 89e911400c..b91d8321bb 100755 --- a/tests/qemu-iotests/060 +++ b/tests/qemu-iotests/060 @@ -150,10 +150,15 @@ $QEMU_IO -c "$OPEN_RO" -c "read -P 1 0 512" | _filter_qemu_io echo echo "=== Testing overlap while COW is in flight ===" echo +BACKING_IMG=$TEST_IMG.base +TEST_IMG=$BACKING_IMG _make_test_img 1G + +$QEMU_IO -c 'write 0k 64k' "$BACKING_IMG" | _filter_qemu_io + # compat=0.10 is required in order to make the following discard actually # unallocate the sector rather than make it a zero sector - we want COW, after # all. -IMGOPTS='compat=0.10' _make_test_img 1G +IMGOPTS='compat=0.10' _make_test_img -b "$BACKING_IMG" 1G # Write two clusters, the second one enforces creation of an L2 table after # the first data cluster. $QEMU_IO -c 'write 0k 64k' -c 'write 512M 64k' "$TEST_IMG" | _filter_qemu_io diff --git a/tests/qemu-iotests/060.out b/tests/qemu-iotests/060.out index e42bf8c5a9..0f6b0658a1 100644 --- a/tests/qemu-iotests/060.out +++ b/tests/qemu-iotests/060.out @@ -97,7 +97,10 @@ read 512/512 bytes at offset 0 === Testing overlap while COW is in flight === -Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 +Formatting 'TEST_DIR/t.IMGFMT.base', fmt=IMGFMT size=1073741824 +wrote 65536/65536 bytes at offset 0 +64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 backing_file=TEST_DIR/t.IMGFMT.base wrote 65536/65536 bytes at offset 0 64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) wrote 65536/65536 bytes at offset 536870912 diff --git a/tests/qemu-iotests/102 b/tests/qemu-iotests/102 index 749ff66b8a..b898df436f 100755 --- a/tests/qemu-iotests/102 +++ b/tests/qemu-iotests/102 @@ -55,7 +55,7 @@ $QEMU_IO -c 'write 0 64k' "$TEST_IMG" | _filter_qemu_io $QEMU_IMG resize -f raw --shrink "$TEST_IMG" $((5 * 64 * 1024)) $QEMU_IO -c map "$TEST_IMG" -$QEMU_IMG map "$TEST_IMG" +$QEMU_IMG map "$TEST_IMG" | _filter_qemu_img_map echo echo '=== Testing map on an image file truncated outside of qemu ===' diff --git a/tests/qemu-iotests/102.out b/tests/qemu-iotests/102.out index 4401b08fee..cd2fdc7f96 100644 --- a/tests/qemu-iotests/102.out +++ b/tests/qemu-iotests/102.out @@ -7,7 +7,8 @@ wrote 65536/65536 bytes at offset 0 64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) Image resized. 64 KiB (0x10000) bytes allocated at offset 0 bytes (0x0) -Offset Length Mapped to File +Offset Length File +0 0x10000 TEST_DIR/t.IMGFMT === Testing map on an image file truncated outside of qemu === diff --git a/tests/qemu-iotests/141.out b/tests/qemu-iotests/141.out index 41c7291258..4d71d9dcae 100644 --- a/tests/qemu-iotests/141.out +++ b/tests/qemu-iotests/141.out @@ -42,9 +42,9 @@ Formatting 'TEST_DIR/o.IMGFMT', fmt=IMGFMT size=1048576 backing_file=TEST_DIR/t. {"return": {}} {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "created", "id": "job0"}} {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "running", "id": "job0"}} +{"return": {}} {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "ready", "id": "job0"}} {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_JOB_READY", "data": {"device": "job0", "len": 0, "offset": 0, "speed": 0, "type": "commit"}} -{"return": {}} {"error": {"class": "GenericError", "desc": "Node 'drv0' is busy: block device is in use by block job: commit"}} {"return": {}} {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "waiting", "id": "job0"}} diff --git a/tests/qemu-iotests/144.out b/tests/qemu-iotests/144.out index 55299201e4..a9a8216bea 100644 --- a/tests/qemu-iotests/144.out +++ b/tests/qemu-iotests/144.out @@ -14,10 +14,10 @@ Formatting 'TEST_DIR/tmp.qcow2', fmt=qcow2 size=536870912 backing_file=TEST_DIR/ {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "created", "id": "virtio0"}} {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "running", "id": "virtio0"}} +{"return": {}} {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "ready", "id": "virtio0"}} {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_JOB_READY", "data": {"device": "virtio0", "len": 0, "offset": 0, "speed": 0, "type": "commit"}} {"return": {}} -{"return": {}} {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "waiting", "id": "virtio0"}} {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "pending", "id": "virtio0"}} {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_JOB_COMPLETED", "data": {"device": "virtio0", "len": 0, "offset": 0, "speed": 0, "type": "commit"}} diff --git a/tests/qemu-iotests/240 b/tests/qemu-iotests/240 index b4cf95096d..5be6b9c0f7 100755 --- a/tests/qemu-iotests/240 +++ b/tests/qemu-iotests/240 @@ -27,6 +27,12 @@ echo "QA output created by $seq" status=1 # failure is the default! +_cleanup() +{ + rm -f "$TEST_DIR/nbd" +} +trap "_cleanup; exit \$status" 0 1 2 3 15 + # get standard environment, filters and checks . ./common.rc . ./common.filter @@ -122,6 +128,21 @@ run_qemu <<EOF { "execute": "quit"} EOF +echo +echo === Attach a SCSI disks using the same block device as a NBD server === +echo + +run_qemu <<EOF +{ "execute": "qmp_capabilities" } +{ "execute": "blockdev-add", "arguments": {"driver": "null-co", "node-name": "hd0", "read-only": true}} +{ "execute": "nbd-server-start", "arguments": {"addr":{"type":"unix","data":{"path":"$TEST_DIR/nbd"}}}} +{ "execute": "nbd-server-add", "arguments": {"device":"hd0"}} +{ "execute": "object-add", "arguments": {"qom-type": "iothread", "id": "iothread0"}} +{ "execute": "device_add", "arguments": {"id": "scsi0", "driver": "${virtio_scsi}", "iothread": "iothread0"}} +{ "execute": "device_add", "arguments": {"id": "scsi-hd0", "driver": "scsi-hd", "drive": "hd0", "bus": "scsi0.0"}} +{ "execute": "quit"} +EOF + # success, all done echo "*** done" rm -f $seq.full diff --git a/tests/qemu-iotests/240.out b/tests/qemu-iotests/240.out index d76392966c..d00df50297 100644 --- a/tests/qemu-iotests/240.out +++ b/tests/qemu-iotests/240.out @@ -43,7 +43,20 @@ QMP_VERSION {"return": {}} {"return": {}} {"return": {}} -{"error": {"class": "GenericError", "desc": "Cannot attach a blockdev that is using a different iothread"}} +{"error": {"class": "GenericError", "desc": "Cannot change iothread of active block backend"}} +{"return": {}} +{"return": {}} +{"return": {}} +{"return": {}} +{"return": {}} +{"return": {}} +{"return": {}} + +=== Attach a SCSI disks using the same block device as a NBD server === + +Testing: +QMP_VERSION +{"return": {}} {"return": {}} {"return": {}} {"return": {}} diff --git a/tests/qemu-iotests/250 b/tests/qemu-iotests/250 new file mode 100755 index 0000000000..c9c0a84a5a --- /dev/null +++ b/tests/qemu-iotests/250 @@ -0,0 +1,78 @@ +#!/usr/bin/env bash +# +# Test big discard in qcow2 shrink +# +# Copyright (c) 2019 Virtuozzo International GmbH. All rights reserved. +# +# This program 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, see <http://www.gnu.org/licenses/>. +# + +# creator +owner=vsementsov@virtuozzo.com + +seq=`basename $0` +echo "QA output created by $seq" + +status=1 # failure is the default! + +_cleanup() +{ + _cleanup_test_img +} +trap "_cleanup; exit \$status" 0 1 2 3 15 + +# get standard environment, filters and checks +. ./common.rc +. ./common.filter + +_supported_fmt qcow2 +_supported_proto file +_supported_os Linux + +# This test checks that qcow2_process_discards does not truncate a discard +# request > 2G. +# To reproduce bug we need to overflow int by one sequential discard, so we +# need size > 2G, bigger cluster size (as with default 64k we may have maximum +# of 512M sequential data, corresponding to one L1 entry), and we need some +# data of the beginning of the disk mapped to the end of file to prevent +# bdrv_co_truncate(bs->file) call in qcow2_co_truncate(), which might succeed +# anyway. + +disk_usage() +{ + du --block-size=1 $1 | awk '{print $1}' +} + +size=2100M +IMGOPTS="cluster_size=1M,preallocation=metadata" + +_make_test_img $size +$QEMU_IO -c 'discard 0 10M' -c 'discard 2090M 10M' \ + -c 'write 2090M 10M' -c 'write 0 10M' "$TEST_IMG" | _filter_qemu_io + +# Check that our trick with swapping first and last 10M chunks succeeded. +# Otherwise test may pass even if bdrv_pdiscard() fails in +# qcow2_process_discards() +$QEMU_IMG map "$TEST_IMG" | _filter_testdir + +before=$(disk_usage "$TEST_IMG") +$QEMU_IMG resize --shrink "$TEST_IMG" 5M +after=$(disk_usage "$TEST_IMG") + +echo "Disk usage delta: $((before - after))" + +# success, all done +echo "*** done" +rm -f $seq.full +status=0 diff --git a/tests/qemu-iotests/250.out b/tests/qemu-iotests/250.out new file mode 100644 index 0000000000..f480fd273b --- /dev/null +++ b/tests/qemu-iotests/250.out @@ -0,0 +1,16 @@ +QA output created by 250 +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=2202009600 preallocation=metadata +discard 10485760/10485760 bytes at offset 0 +10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +discard 10485760/10485760 bytes at offset 2191523840 +10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +wrote 10485760/10485760 bytes at offset 2191523840 +10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +wrote 10485760/10485760 bytes at offset 0 +10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +Offset Length Mapped to File +0 0xa00000 0x82f00000 TEST_DIR/t.qcow2 +0x82a00000 0xa00000 0x500000 TEST_DIR/t.qcow2 +Image resized. +Disk usage delta: 15728640 +*** done diff --git a/tests/qemu-iotests/254 b/tests/qemu-iotests/254 new file mode 100755 index 0000000000..33cb80a512 --- /dev/null +++ b/tests/qemu-iotests/254 @@ -0,0 +1,52 @@ +#!/usr/bin/env python +# +# Test external snapshot with bitmap copying. +# +# Copyright (c) 2019 Virtuozzo International GmbH. All rights reserved. +# +# This program 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, see <http://www.gnu.org/licenses/>. +# + +import iotests +from iotests import qemu_img_create, file_path, log + +disk, top = file_path('disk', 'top') +size = 1024 * 1024 + +qemu_img_create('-f', iotests.imgfmt, disk, str(size)) + +vm = iotests.VM().add_drive(disk, opts='node-name=base') +vm.launch() + +vm.qmp_log('block-dirty-bitmap-add', node='drive0', name='bitmap0') + +vm.hmp_qemu_io('drive0', 'write 0 512K') + +vm.qmp_log('transaction', indent=2, actions=[ + {'type': 'blockdev-snapshot-sync', + 'data': {'device': 'drive0', 'snapshot-file': top, + 'snapshot-node-name': 'snap'}}, + {'type': 'block-dirty-bitmap-add', + 'data': {'node': 'snap', 'name': 'bitmap0'}}, + {'type': 'block-dirty-bitmap-merge', + 'data': {'node': 'snap', 'target': 'bitmap0', + 'bitmaps': [{'node': 'base', 'name': 'bitmap0'}]}} +], filters=[iotests.filter_qmp_testfiles]) + +result = vm.qmp('query-block')['return'][0] +log("query-block: device = {}, node-name = {}, dirty-bitmaps:".format( + result['device'], result['inserted']['node-name'])) +log(result['dirty-bitmaps'], indent=2) + +vm.shutdown() diff --git a/tests/qemu-iotests/254.out b/tests/qemu-iotests/254.out new file mode 100644 index 0000000000..d7394cf002 --- /dev/null +++ b/tests/qemu-iotests/254.out @@ -0,0 +1,52 @@ +{"execute": "block-dirty-bitmap-add", "arguments": {"name": "bitmap0", "node": "drive0"}} +{"return": {}} +{ + "execute": "transaction", + "arguments": { + "actions": [ + { + "data": { + "device": "drive0", + "snapshot-file": "TEST_DIR/PID-top", + "snapshot-node-name": "snap" + }, + "type": "blockdev-snapshot-sync" + }, + { + "data": { + "name": "bitmap0", + "node": "snap" + }, + "type": "block-dirty-bitmap-add" + }, + { + "data": { + "bitmaps": [ + { + "name": "bitmap0", + "node": "base" + } + ], + "node": "snap", + "target": "bitmap0" + }, + "type": "block-dirty-bitmap-merge" + } + ] + } +} +{ + "return": {} +} +query-block: device = drive0, node-name = snap, dirty-bitmaps: +[ + { + "busy": false, + "count": 524288, + "granularity": 65536, + "name": "bitmap0", + "persistent": false, + "recording": true, + "status": "active" + } +] diff --git a/tests/qemu-iotests/255 b/tests/qemu-iotests/255 new file mode 100755 index 0000000000..49433ec122 --- /dev/null +++ b/tests/qemu-iotests/255 @@ -0,0 +1,135 @@ +#!/usr/bin/env python +# +# Test commit job graph modifications while requests are active +# +# Copyright (C) 2019 Red Hat, Inc. +# +# Creator/Owner: Kevin Wolf <kwolf@redhat.com> +# +# This program 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, see <http://www.gnu.org/licenses/>. +# + +import iotests +from iotests import imgfmt + +iotests.verify_image_format(supported_fmts=['qcow2']) + +def blockdev_create(vm, options): + result = vm.qmp_log('blockdev-create', + filters=[iotests.filter_qmp_testfiles], + job_id='job0', options=options) + + if 'return' in result: + assert result['return'] == {} + vm.run_job('job0') + iotests.log("") + +iotests.log('Finishing a commit job with background reads') +iotests.log('============================================') +iotests.log('') + +with iotests.FilePath('t.qcow2') as disk_path, \ + iotests.FilePath('t.qcow2.mid') as mid_path, \ + iotests.FilePath('t.qcow2.base') as base_path, \ + iotests.VM() as vm: + + iotests.log("=== Create backing chain and start VM ===") + iotests.log("") + + size = 128 * 1024 * 1024 + size_str = str(size) + + iotests.create_image(base_path, size) + iotests.qemu_img_log('create', '-f', iotests.imgfmt, mid_path, size_str) + iotests.qemu_img_log('create', '-f', iotests.imgfmt, disk_path, size_str) + + # Create a backing chain like this: + # base <- [throttled: bps-read=4096] <- mid <- overlay + + vm.add_object('throttle-group,x-bps-read=4096,id=throttle0') + vm.add_blockdev('file,filename=%s,node-name=base' % (base_path)) + vm.add_blockdev('throttle,throttle-group=throttle0,file=base,node-name=throttled') + vm.add_blockdev('file,filename=%s,node-name=mid-file' % (mid_path)) + vm.add_blockdev('qcow2,file=mid-file,node-name=mid,backing=throttled') + vm.add_drive_raw('if=none,id=overlay,driver=qcow2,file=%s,backing=mid' % (disk_path)) + + vm.launch() + + iotests.log("=== Start background read requests ===") + iotests.log("") + + def start_requests(): + vm.hmp_qemu_io('overlay', 'aio_read 0 4k') + vm.hmp_qemu_io('overlay', 'aio_read 0 4k') + + start_requests() + + iotests.log("=== Run a commit job ===") + iotests.log("") + + result = vm.qmp_log('block-commit', job_id='job0', auto_finalize=False, + device='overlay', top_node='mid') + + vm.run_job('job0', auto_finalize=False, pre_finalize=start_requests, + auto_dismiss=True) + + vm.shutdown() + +iotests.log('') +iotests.log('Closing the VM while a job is being cancelled') +iotests.log('=============================================') +iotests.log('') + +with iotests.FilePath('src.qcow2') as src_path, \ + iotests.FilePath('dst.qcow2') as dst_path, \ + iotests.VM() as vm: + + iotests.log('=== Create images and start VM ===') + iotests.log('') + + size = 128 * 1024 * 1024 + size_str = str(size) + + iotests.qemu_img_log('create', '-f', iotests.imgfmt, src_path, size_str) + iotests.qemu_img_log('create', '-f', iotests.imgfmt, dst_path, size_str) + + iotests.log(iotests.qemu_io('-f', iotests.imgfmt, '-c', 'write 0 1M', + src_path), + filters=[iotests.filter_test_dir, iotests.filter_qemu_io]) + + vm.add_object('throttle-group,x-bps-read=4096,id=throttle0') + + vm.add_blockdev('file,node-name=src-file,filename=%s' % (src_path)) + vm.add_blockdev('%s,node-name=src,file=src-file' % (iotests.imgfmt)) + + vm.add_blockdev('file,node-name=dst-file,filename=%s' % (dst_path)) + vm.add_blockdev('%s,node-name=dst,file=dst-file' % (iotests.imgfmt)) + + vm.add_blockdev('throttle,node-name=src-throttled,' + + 'throttle-group=throttle0,file=src') + + vm.add_device('virtio-blk,drive=src-throttled') + + vm.launch() + + iotests.log('=== Start a mirror job ===') + iotests.log('') + + vm.qmp_log('blockdev-mirror', job_id='job0', device='src-throttled', + target='dst', sync='full') + + vm.qmp_log('block-job-cancel', device='job0') + vm.qmp_log('quit') + + vm.shutdown() diff --git a/tests/qemu-iotests/255.out b/tests/qemu-iotests/255.out new file mode 100644 index 0000000000..348909fdef --- /dev/null +++ b/tests/qemu-iotests/255.out @@ -0,0 +1,40 @@ +Finishing a commit job with background reads +============================================ + +=== Create backing chain and start VM === + +Formatting 'TEST_DIR/PID-t.qcow2.mid', fmt=qcow2 size=134217728 cluster_size=65536 lazy_refcounts=off refcount_bits=16 + +Formatting 'TEST_DIR/PID-t.qcow2', fmt=qcow2 size=134217728 cluster_size=65536 lazy_refcounts=off refcount_bits=16 + +=== Start background read requests === + +=== Run a commit job === + +{"execute": "block-commit", "arguments": {"auto-finalize": false, "device": "overlay", "job-id": "job0", "top-node": "mid"}} +{"return": {}} +{"execute": "job-finalize", "arguments": {"id": "job0"}} +{"return": {}} +{"data": {"id": "job0", "type": "commit"}, "event": "BLOCK_JOB_PENDING", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}} +{"data": {"device": "job0", "len": 134217728, "offset": 134217728, "speed": 0, "type": "commit"}, "event": "BLOCK_JOB_COMPLETED", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}} + +Closing the VM while a job is being cancelled +============================================= + +=== Create images and start VM === + +Formatting 'TEST_DIR/PID-src.qcow2', fmt=qcow2 size=134217728 cluster_size=65536 lazy_refcounts=off refcount_bits=16 + +Formatting 'TEST_DIR/PID-dst.qcow2', fmt=qcow2 size=134217728 cluster_size=65536 lazy_refcounts=off refcount_bits=16 + +wrote 1048576/1048576 bytes at offset 0 +1 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) + +=== Start a mirror job === + +{"execute": "blockdev-mirror", "arguments": {"device": "src-throttled", "job-id": "job0", "sync": "full", "target": "dst"}} +{"return": {}} +{"execute": "block-job-cancel", "arguments": {"device": "job0"}} +{"return": {}} +{"execute": "quit", "arguments": {}} +{"return": {}} diff --git a/tests/qemu-iotests/check b/tests/qemu-iotests/check index 922c5d1d3d..44ebf24080 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,22 @@ 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 +892,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..f3b6d601b2 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,77 @@ 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 +250 rw auto quick 252 rw auto backing quick 253 rw auto quick +254 rw auto backing quick +255 rw auto quick diff --git a/tests/qemu-iotests/iotests.py b/tests/qemu-iotests/iotests.py index 7bde380d96..6bcddd8870 100644 --- a/tests/qemu-iotests/iotests.py +++ b/tests/qemu-iotests/iotests.py @@ -126,6 +126,11 @@ def qemu_img_pipe(*args): sys.stderr.write('qemu-img received signal %i: %s\n' % (-exitcode, ' '.join(qemu_img_args + list(args)))) return subp.communicate()[0] +def qemu_img_log(*args): + result = qemu_img_pipe(*args) + log(result, filters=[filter_testfiles]) + return result + def img_info_log(filename, filter_path=None, imgopts=False, extra_args=[]): args = [ 'info' ] if imgopts: @@ -533,7 +538,8 @@ class VM(qtest.QEMUQtestMachine): return result # Returns None on success, and an error string on failure - def run_job(self, job, auto_finalize=True, auto_dismiss=False): + def run_job(self, job, auto_finalize=True, auto_dismiss=False, + pre_finalize=None): error = None while True: for ev in self.get_qmp_events_filtered(wait=True): @@ -546,6 +552,8 @@ class VM(qtest.QEMUQtestMachine): error = j['error'] log('Job failed: %s' % (j['error'])) elif status == 'pending' and not auto_finalize: + if pre_finalize: + pre_finalize() self.qmp_log('job-finalize', id=job) elif status == 'concluded' and not auto_dismiss: self.qmp_log('job-dismiss', id=job) diff --git a/tests/qos-test.c b/tests/qos-test.c index ae2fb5de1c..01b2a22c08 100644 --- a/tests/qos-test.c +++ b/tests/qos-test.c @@ -340,7 +340,8 @@ static void walk_path(QOSGraphNode *orig_path, int len) char **path_vec = g_new0(char *, (QOS_PATH_MAX_ELEMENT_SIZE * 2)); int path_vec_size = 0; - char *after_cmd = NULL, *before_cmd = NULL, *after_device = NULL; + char *after_cmd, *before_cmd, *after_device; + GString *after_device_str = g_string_new(""); char *node_name = orig_path->name, *path_str; GString *cmd_line = g_string_new(""); @@ -363,9 +364,8 @@ static void walk_path(QOSGraphNode *orig_path, int len) /* append node command line + previous edge command line */ if (path->command_line && etype == QEDGE_CONSUMED_BY) { g_string_append(cmd_line, path->command_line); - if (after_device) { - g_string_append(cmd_line, after_device); - } + g_string_append(cmd_line, after_device_str->str); + g_string_truncate(after_device_str, 0); } path_vec[path_vec_size++] = qos_graph_edge_get_name(path->path_edge); @@ -382,12 +382,15 @@ static void walk_path(QOSGraphNode *orig_path, int len) if (after_cmd) { g_string_append(cmd_line2, after_cmd); } + if (after_device) { + g_string_append(after_device_str, after_device); + } } path_vec[path_vec_size++] = NULL; - if (after_device) { - g_string_append(cmd_line, after_device); - } + g_string_append(cmd_line, after_device_str->str); + g_string_free(after_device_str, true); + g_string_append(cmd_line, cmd_line2->str); g_string_free(cmd_line2, true); diff --git a/tests/requirements.txt b/tests/requirements.txt index 002ded6a22..3ae0e29ad7 100644 --- a/tests/requirements.txt +++ b/tests/requirements.txt @@ -2,3 +2,4 @@ # in the tests/venv Python virtual environment. For more info, # refer to: https://pip.pypa.io/en/stable/user_guide/#id1 avocado-framework==68.0 +paramiko 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/mips/include/test_utils_128.h b/tests/tcg/mips/include/test_utils_128.h index cfd7ad3188..a828416d4f 100644 --- a/tests/tcg/mips/include/test_utils_128.h +++ b/tests/tcg/mips/include/test_utils_128.h @@ -66,7 +66,7 @@ static inline int32_t check_results(const char *instruction_name, } } - printf("PASS: %3d FAIL: %3d elapsed time: %5.2f ms\n", + printf("\tPASS: %3d \tFAIL: %3d \telapsed time: %5.2f ms\n", pass_count, fail_count, elapsed_time); if (fail_count > 0) { diff --git a/tests/tcg/mips/include/wrappers_msa.h b/tests/tcg/mips/include/wrappers_msa.h index 254e215b8a..5d28cb531a 100644 --- a/tests/tcg/mips/include/wrappers_msa.h +++ b/tests/tcg/mips/include/wrappers_msa.h @@ -23,8 +23,57 @@ #define WRAPPERS_MSA_H +#define RESET_MSA_REGISTER(wi) \ + __asm__ volatile ( \ + "xor.v $" #wi ", $" #wi ", $" #wi "\n\t" \ + : \ + : \ + : \ + ) + + +static inline void reset_msa_registers() +{ + + RESET_MSA_REGISTER(w0); + RESET_MSA_REGISTER(w1); + RESET_MSA_REGISTER(w2); + RESET_MSA_REGISTER(w3); + RESET_MSA_REGISTER(w4); + RESET_MSA_REGISTER(w5); + RESET_MSA_REGISTER(w6); + RESET_MSA_REGISTER(w7); + RESET_MSA_REGISTER(w8); + RESET_MSA_REGISTER(w9); + RESET_MSA_REGISTER(w10); + RESET_MSA_REGISTER(w11); + RESET_MSA_REGISTER(w12); + RESET_MSA_REGISTER(w13); + RESET_MSA_REGISTER(w14); + RESET_MSA_REGISTER(w15); + RESET_MSA_REGISTER(w16); + RESET_MSA_REGISTER(w17); + RESET_MSA_REGISTER(w18); + RESET_MSA_REGISTER(w19); + RESET_MSA_REGISTER(w20); + RESET_MSA_REGISTER(w21); + RESET_MSA_REGISTER(w22); + RESET_MSA_REGISTER(w23); + RESET_MSA_REGISTER(w24); + RESET_MSA_REGISTER(w25); + RESET_MSA_REGISTER(w26); + RESET_MSA_REGISTER(w27); + RESET_MSA_REGISTER(w28); + RESET_MSA_REGISTER(w29); + RESET_MSA_REGISTER(w30); + RESET_MSA_REGISTER(w31); + +} + + #define DO_MSA__WD__WS(suffix, mnemonic) \ -static inline void do_msa_##suffix(void *input, void *output) \ +static inline void do_msa_##suffix(const void *input, \ + const void *output) \ { \ __asm__ volatile ( \ "move $t0, %0\n\t" \ @@ -39,7 +88,8 @@ static inline void do_msa_##suffix(void *input, void *output) \ } #define DO_MSA__WD__WD(suffix, mnemonic) \ -static inline void do_msa_##suffix(void *input, void *output) \ +static inline void do_msa_##suffix(const void *input, \ + const void *output) \ { \ __asm__ volatile ( \ "move $t0, %0\n\t" \ @@ -53,25 +103,11 @@ static inline void do_msa_##suffix(void *input, void *output) \ ); \ } -DO_MSA__WD__WS(NLOC_B, nloc.b) -DO_MSA__WD__WS(NLOC_H, nloc.h) -DO_MSA__WD__WS(NLOC_W, nloc.w) -DO_MSA__WD__WS(NLOC_D, nloc.d) - -DO_MSA__WD__WS(NLZC_B, nlzc.b) -DO_MSA__WD__WS(NLZC_H, nlzc.h) -DO_MSA__WD__WS(NLZC_W, nlzc.w) -DO_MSA__WD__WS(NLZC_D, nlzc.d) - -DO_MSA__WD__WS(PCNT_B, pcnt.b) -DO_MSA__WD__WS(PCNT_H, pcnt.h) -DO_MSA__WD__WS(PCNT_W, pcnt.w) -DO_MSA__WD__WS(PCNT_D, pcnt.d) - #define DO_MSA__WD__WS_WT(suffix, mnemonic) \ -static inline void do_msa_##suffix(void *input1, void *input2, \ - void *output) \ +static inline void do_msa_##suffix(const void *input1, \ + const void *input2, \ + const void *output) \ { \ __asm__ volatile ( \ "move $t0, %0\n\t" \ @@ -123,30 +159,180 @@ static inline void do_msa_##suffix(void *input1, void *input2, \ ); \ } -DO_MSA__WD__WS_WT(ILVEV_B, ilvev.b) -DO_MSA__WD__WS_WT(ILVEV_H, ilvev.h) -DO_MSA__WD__WS_WT(ILVEV_W, ilvev.w) -DO_MSA__WD__WS_WT(ILVEV_D, ilvev.d) -DO_MSA__WD__WS_WT(ILVOD_B, ilvod.b) -DO_MSA__WD__WS_WT(ILVOD_H, ilvod.h) -DO_MSA__WD__WS_WT(ILVOD_W, ilvod.w) -DO_MSA__WD__WS_WT(ILVOD_D, ilvod.d) +/* + * Bit Count + * --------- + */ -DO_MSA__WD__WS_WT(ILVL_B, ilvl.b) -DO_MSA__WD__WS_WT(ILVL_H, ilvl.h) -DO_MSA__WD__WS_WT(ILVL_W, ilvl.w) -DO_MSA__WD__WS_WT(ILVL_D, ilvl.d) +DO_MSA__WD__WS(NLOC_B, nloc.b) +DO_MSA__WD__WS(NLOC_H, nloc.h) +DO_MSA__WD__WS(NLOC_W, nloc.w) +DO_MSA__WD__WS(NLOC_D, nloc.d) -DO_MSA__WD__WS_WT(ILVR_B, ilvr.b) -DO_MSA__WD__WS_WT(ILVR_H, ilvr.h) -DO_MSA__WD__WS_WT(ILVR_W, ilvr.w) -DO_MSA__WD__WS_WT(ILVR_D, ilvr.d) +DO_MSA__WD__WS(NLZC_B, nlzc.b) +DO_MSA__WD__WS(NLZC_H, nlzc.h) +DO_MSA__WD__WS(NLZC_W, nlzc.w) +DO_MSA__WD__WS(NLZC_D, nlzc.d) -DO_MSA__WD__WS_WT(AND_V, and.v) -DO_MSA__WD__WS_WT(NOR_V, nor.v) -DO_MSA__WD__WS_WT(OR_V, or.v) -DO_MSA__WD__WS_WT(XOR_V, xor.v) +DO_MSA__WD__WS(PCNT_B, pcnt.b) +DO_MSA__WD__WS(PCNT_H, pcnt.h) +DO_MSA__WD__WS(PCNT_W, pcnt.w) +DO_MSA__WD__WS(PCNT_D, pcnt.d) + + +/* + * Bit move + * -------- + */ + +DO_MSA__WD__WS_WT(BINSL_B, binsl.b) +DO_MSA__WD__WS_WT(BINSL_H, binsl.h) +DO_MSA__WD__WS_WT(BINSL_W, binsl.w) +DO_MSA__WD__WS_WT(BINSL_D, binsl.d) + +DO_MSA__WD__WS_WT(BINSR_B, binsr.b) +DO_MSA__WD__WS_WT(BINSR_H, binsr.h) +DO_MSA__WD__WS_WT(BINSR_W, binsr.w) +DO_MSA__WD__WS_WT(BINSR_D, binsr.d) + +DO_MSA__WD__WS_WT(BMNZ_V, bmnz.v) +DO_MSA__WD__WS_WT(BMZ_V, bmz.v) +DO_MSA__WD__WS_WT(BSEL_V, bsel.v) + + +/* + * Bit Set + * ------- + */ + +DO_MSA__WD__WS_WT(BCLR_B, bclr.b) +DO_MSA__WD__WS_WT(BCLR_H, bclr.h) +DO_MSA__WD__WS_WT(BCLR_W, bclr.w) +DO_MSA__WD__WS_WT(BCLR_D, bclr.d) + +DO_MSA__WD__WS_WT(BSET_B, bset.b) +DO_MSA__WD__WS_WT(BSET_H, bset.h) +DO_MSA__WD__WS_WT(BSET_W, bset.w) +DO_MSA__WD__WS_WT(BSET_D, bset.d) + +DO_MSA__WD__WS_WT(BNEG_B, bneg.b) +DO_MSA__WD__WS_WT(BNEG_H, bneg.h) +DO_MSA__WD__WS_WT(BNEG_W, bneg.w) +DO_MSA__WD__WS_WT(BNEG_D, bneg.d) + + +/* + * Fixed Multiply + * -------------- + */ + +DO_MSA__WD__WS_WT(MADD_Q_H, madd_q.h) +DO_MSA__WD__WS_WT(MADD_Q_W, madd_q.w) + +DO_MSA__WD__WS_WT(MADDR_Q_H, maddr_q.h) +DO_MSA__WD__WS_WT(MADDR_Q_W, maddr_q.w) + +DO_MSA__WD__WS_WT(MSUB_Q_H, msub_q.h) +DO_MSA__WD__WS_WT(MSUB_Q_W, msub_q.w) + +DO_MSA__WD__WS_WT(MSUBR_Q_H, msubr_q.h) +DO_MSA__WD__WS_WT(MSUBR_Q_W, msubr_q.w) + +DO_MSA__WD__WS_WT(MUL_Q_H, mul_q.h) +DO_MSA__WD__WS_WT(MUL_Q_W, mul_q.w) + +DO_MSA__WD__WS_WT(MULR_Q_H, mulr_q.h) +DO_MSA__WD__WS_WT(MULR_Q_W, mulr_q.w) + + +/* + * Float Max Min + * ------------- + */ + +DO_MSA__WD__WS_WT(FMAX_W, fmax.w) +DO_MSA__WD__WS_WT(FMAX_D, fmax.d) + +DO_MSA__WD__WS_WT(FMAX_A_W, fmax_a.w) +DO_MSA__WD__WS_WT(FMAX_A_D, fmax_a.d) + +DO_MSA__WD__WS_WT(FMIN_W, fmin.w) +DO_MSA__WD__WS_WT(FMIN_D, fmin.d) + +DO_MSA__WD__WS_WT(FMIN_A_W, fmin_a.w) +DO_MSA__WD__WS_WT(FMIN_A_D, fmin_a.d) + + +/* + * Int Add + * ------- + */ + +DO_MSA__WD__WS_WT(ADD_A_B, add_a.b) +DO_MSA__WD__WS_WT(ADD_A_H, add_a.h) +DO_MSA__WD__WS_WT(ADD_A_W, add_a.w) +DO_MSA__WD__WS_WT(ADD_A_D, add_a.d) + +DO_MSA__WD__WS_WT(ADDS_A_B, adds_a.b) +DO_MSA__WD__WS_WT(ADDS_A_H, adds_a.h) +DO_MSA__WD__WS_WT(ADDS_A_W, adds_a.w) +DO_MSA__WD__WS_WT(ADDS_A_D, adds_a.d) + +DO_MSA__WD__WS_WT(ADDS_S_B, adds_s.b) +DO_MSA__WD__WS_WT(ADDS_S_H, adds_s.h) +DO_MSA__WD__WS_WT(ADDS_S_W, adds_s.w) +DO_MSA__WD__WS_WT(ADDS_S_D, adds_s.d) + +DO_MSA__WD__WS_WT(ADDS_U_B, adds_u.b) +DO_MSA__WD__WS_WT(ADDS_U_H, adds_u.h) +DO_MSA__WD__WS_WT(ADDS_U_W, adds_u.w) +DO_MSA__WD__WS_WT(ADDS_U_D, adds_u.d) + +DO_MSA__WD__WS_WT(ADDV_B, addv.b) +DO_MSA__WD__WS_WT(ADDV_H, addv.h) +DO_MSA__WD__WS_WT(ADDV_W, addv.w) +DO_MSA__WD__WS_WT(ADDV_D, addv.d) + +DO_MSA__WD__WS_WT(HADD_S_H, hadd_s.h) +DO_MSA__WD__WS_WT(HADD_S_W, hadd_s.w) +DO_MSA__WD__WS_WT(HADD_S_D, hadd_s.d) + +DO_MSA__WD__WS_WT(HADD_U_H, hadd_u.h) +DO_MSA__WD__WS_WT(HADD_U_W, hadd_u.w) +DO_MSA__WD__WS_WT(HADD_U_D, hadd_u.d) + + +/* + * Int Average + * ----------- + */ + +DO_MSA__WD__WS_WT(AVE_S_B, ave_s.b) +DO_MSA__WD__WS_WT(AVE_S_H, ave_s.h) +DO_MSA__WD__WS_WT(AVE_S_W, ave_s.w) +DO_MSA__WD__WS_WT(AVE_S_D, ave_s.d) + +DO_MSA__WD__WS_WT(AVE_U_B, ave_u.b) +DO_MSA__WD__WS_WT(AVE_U_H, ave_u.h) +DO_MSA__WD__WS_WT(AVE_U_W, ave_u.w) +DO_MSA__WD__WS_WT(AVE_U_D, ave_u.d) + +DO_MSA__WD__WS_WT(AVER_S_B, aver_s.b) +DO_MSA__WD__WS_WT(AVER_S_H, aver_s.h) +DO_MSA__WD__WS_WT(AVER_S_W, aver_s.w) +DO_MSA__WD__WS_WT(AVER_S_D, aver_s.d) + +DO_MSA__WD__WS_WT(AVER_U_B, aver_u.b) +DO_MSA__WD__WS_WT(AVER_U_H, aver_u.h) +DO_MSA__WD__WS_WT(AVER_U_W, aver_u.w) +DO_MSA__WD__WS_WT(AVER_U_D, aver_u.d) + + +/* + * Int Compare + * ----------- + */ DO_MSA__WD__WS_WT(CEQ_B, ceq.b) DO_MSA__WD__WS_WT(CEQ_H, ceq.h) @@ -173,50 +359,200 @@ DO_MSA__WD__WS_WT(CLT_U_H, clt_u.h) DO_MSA__WD__WS_WT(CLT_U_W, clt_u.w) DO_MSA__WD__WS_WT(CLT_U_D, clt_u.d) + +/* + * Int Divide + * ---------- + */ + +DO_MSA__WD__WS_WT(DIV_S_B, div_s.b) +DO_MSA__WD__WS_WT(DIV_S_H, div_s.h) +DO_MSA__WD__WS_WT(DIV_S_W, div_s.w) +DO_MSA__WD__WS_WT(DIV_S_D, div_s.d) + +DO_MSA__WD__WS_WT(DIV_U_B, div_u.b) +DO_MSA__WD__WS_WT(DIV_U_H, div_u.h) +DO_MSA__WD__WS_WT(DIV_U_W, div_u.w) +DO_MSA__WD__WS_WT(DIV_U_D, div_u.d) + + +/* + * Int Dot Product + * --------------- + */ + +DO_MSA__WD__WS_WT(DOTP_S_H, dotp_s.h) +DO_MSA__WD__WS_WT(DOTP_S_W, dotp_s.w) +DO_MSA__WD__WS_WT(DOTP_S_D, dotp_s.d) + +DO_MSA__WD__WS_WT(DOTP_U_H, dotp_u.h) +DO_MSA__WD__WS_WT(DOTP_U_W, dotp_u.w) +DO_MSA__WD__WS_WT(DOTP_U_D, dotp_u.d) + + +/* + * Int Max Min + * ----------- + */ + DO_MSA__WD__WS_WT(MAX_A_B, max_a.b) DO_MSA__WD__WS_WT(MAX_A_H, max_a.h) DO_MSA__WD__WS_WT(MAX_A_W, max_a.w) DO_MSA__WD__WS_WT(MAX_A_D, max_a.d) -DO_MSA__WD__WS_WT(MIN_A_B, min_a.b) -DO_MSA__WD__WS_WT(MIN_A_H, min_a.h) -DO_MSA__WD__WS_WT(MIN_A_W, min_a.w) -DO_MSA__WD__WS_WT(MIN_A_D, min_a.d) - DO_MSA__WD__WS_WT(MAX_S_B, max_s.b) DO_MSA__WD__WS_WT(MAX_S_H, max_s.h) DO_MSA__WD__WS_WT(MAX_S_W, max_s.w) DO_MSA__WD__WS_WT(MAX_S_D, max_s.d) -DO_MSA__WD__WS_WT(MIN_S_B, min_s.b) -DO_MSA__WD__WS_WT(MIN_S_H, min_s.h) -DO_MSA__WD__WS_WT(MIN_S_W, min_s.w) -DO_MSA__WD__WS_WT(MIN_S_D, min_s.d) - DO_MSA__WD__WS_WT(MAX_U_B, max_u.b) DO_MSA__WD__WS_WT(MAX_U_H, max_u.h) DO_MSA__WD__WS_WT(MAX_U_W, max_u.w) DO_MSA__WD__WS_WT(MAX_U_D, max_u.d) +DO_MSA__WD__WS_WT(MIN_A_B, min_a.b) +DO_MSA__WD__WS_WT(MIN_A_H, min_a.h) +DO_MSA__WD__WS_WT(MIN_A_W, min_a.w) +DO_MSA__WD__WS_WT(MIN_A_D, min_a.d) + +DO_MSA__WD__WS_WT(MIN_S_B, min_s.b) +DO_MSA__WD__WS_WT(MIN_S_H, min_s.h) +DO_MSA__WD__WS_WT(MIN_S_W, min_s.w) +DO_MSA__WD__WS_WT(MIN_S_D, min_s.d) + DO_MSA__WD__WS_WT(MIN_U_B, min_u.b) DO_MSA__WD__WS_WT(MIN_U_H, min_u.h) DO_MSA__WD__WS_WT(MIN_U_W, min_u.w) DO_MSA__WD__WS_WT(MIN_U_D, min_u.d) -DO_MSA__WD__WS_WT(BCLR_B, bclr.b) -DO_MSA__WD__WS_WT(BCLR_H, bclr.h) -DO_MSA__WD__WS_WT(BCLR_W, bclr.w) -DO_MSA__WD__WS_WT(BCLR_D, bclr.d) -DO_MSA__WD__WS_WT(BSET_B, bset.b) -DO_MSA__WD__WS_WT(BSET_H, bset.h) -DO_MSA__WD__WS_WT(BSET_W, bset.w) -DO_MSA__WD__WS_WT(BSET_D, bset.d) +/* + * Int Modulo + * ---------- + */ -DO_MSA__WD__WS_WT(BNEG_B, bneg.b) -DO_MSA__WD__WS_WT(BNEG_H, bneg.h) -DO_MSA__WD__WS_WT(BNEG_W, bneg.w) -DO_MSA__WD__WS_WT(BNEG_D, bneg.d) +DO_MSA__WD__WS_WT(MOD_S_B, mod_s.b) +DO_MSA__WD__WS_WT(MOD_S_H, mod_s.h) +DO_MSA__WD__WS_WT(MOD_S_W, mod_s.w) +DO_MSA__WD__WS_WT(MOD_S_D, mod_s.d) + +DO_MSA__WD__WS_WT(MOD_U_B, mod_u.b) +DO_MSA__WD__WS_WT(MOD_U_H, mod_u.h) +DO_MSA__WD__WS_WT(MOD_U_W, mod_u.w) +DO_MSA__WD__WS_WT(MOD_U_D, mod_u.d) + + +/* + * Int Multiply + * ------------ + */ + +DO_MSA__WD__WS_WT(MADDV_B, maddv.b) +DO_MSA__WD__WS_WT(MADDV_H, maddv.h) +DO_MSA__WD__WS_WT(MADDV_W, maddv.w) +DO_MSA__WD__WS_WT(MADDV_D, maddv.d) + +DO_MSA__WD__WS_WT(MSUBV_B, msubv.b) +DO_MSA__WD__WS_WT(MSUBV_H, msubv.h) +DO_MSA__WD__WS_WT(MSUBV_W, msubv.w) +DO_MSA__WD__WS_WT(MSUBV_D, msubv.d) + +DO_MSA__WD__WS_WT(MULV_B, mulv.b) +DO_MSA__WD__WS_WT(MULV_H, mulv.h) +DO_MSA__WD__WS_WT(MULV_W, mulv.w) +DO_MSA__WD__WS_WT(MULV_D, mulv.d) + + +/* + * Int Subtract + * ------------ + */ + +DO_MSA__WD__WS_WT(ASUB_S_B, asub_s.b) +DO_MSA__WD__WS_WT(ASUB_S_H, asub_s.h) +DO_MSA__WD__WS_WT(ASUB_S_W, asub_s.w) +DO_MSA__WD__WS_WT(ASUB_S_D, asub_s.d) + +DO_MSA__WD__WS_WT(ASUB_U_B, asub_u.b) +DO_MSA__WD__WS_WT(ASUB_U_H, asub_u.h) +DO_MSA__WD__WS_WT(ASUB_U_W, asub_u.w) +DO_MSA__WD__WS_WT(ASUB_U_D, asub_u.d) + +DO_MSA__WD__WS_WT(HSUB_S_H, hsub_s.h) +DO_MSA__WD__WS_WT(HSUB_S_W, hsub_s.w) +DO_MSA__WD__WS_WT(HSUB_S_D, hsub_s.d) + +DO_MSA__WD__WS_WT(HSUB_U_H, hsub_u.h) +DO_MSA__WD__WS_WT(HSUB_U_W, hsub_u.w) +DO_MSA__WD__WS_WT(HSUB_U_D, hsub_u.d) + +DO_MSA__WD__WS_WT(SUBS_S_B, subs_s.b) +DO_MSA__WD__WS_WT(SUBS_S_H, subs_s.h) +DO_MSA__WD__WS_WT(SUBS_S_W, subs_s.w) +DO_MSA__WD__WS_WT(SUBS_S_D, subs_s.d) + +DO_MSA__WD__WS_WT(SUBS_U_B, subs_u.b) +DO_MSA__WD__WS_WT(SUBS_U_H, subs_u.h) +DO_MSA__WD__WS_WT(SUBS_U_W, subs_u.w) +DO_MSA__WD__WS_WT(SUBS_U_D, subs_u.d) + +DO_MSA__WD__WS_WT(SUBSUS_U_B, subsus_u.b) +DO_MSA__WD__WS_WT(SUBSUS_U_H, subsus_u.h) +DO_MSA__WD__WS_WT(SUBSUS_U_W, subsus_u.w) +DO_MSA__WD__WS_WT(SUBSUS_U_D, subsus_u.d) + +DO_MSA__WD__WS_WT(SUBSUU_S_B, subsuu_s.b) +DO_MSA__WD__WS_WT(SUBSUU_S_H, subsuu_s.h) +DO_MSA__WD__WS_WT(SUBSUU_S_W, subsuu_s.w) +DO_MSA__WD__WS_WT(SUBSUU_S_D, subsuu_s.d) + +DO_MSA__WD__WS_WT(SUBV_B, subv.b) +DO_MSA__WD__WS_WT(SUBV_H, subv.h) +DO_MSA__WD__WS_WT(SUBV_W, subv.w) +DO_MSA__WD__WS_WT(SUBV_D, subv.d) + + +/* + * Interleave + * ---------- + */ + +DO_MSA__WD__WS_WT(ILVEV_B, ilvev.b) +DO_MSA__WD__WS_WT(ILVEV_H, ilvev.h) +DO_MSA__WD__WS_WT(ILVEV_W, ilvev.w) +DO_MSA__WD__WS_WT(ILVEV_D, ilvev.d) + +DO_MSA__WD__WS_WT(ILVOD_B, ilvod.b) +DO_MSA__WD__WS_WT(ILVOD_H, ilvod.h) +DO_MSA__WD__WS_WT(ILVOD_W, ilvod.w) +DO_MSA__WD__WS_WT(ILVOD_D, ilvod.d) + +DO_MSA__WD__WS_WT(ILVL_B, ilvl.b) +DO_MSA__WD__WS_WT(ILVL_H, ilvl.h) +DO_MSA__WD__WS_WT(ILVL_W, ilvl.w) +DO_MSA__WD__WS_WT(ILVL_D, ilvl.d) + +DO_MSA__WD__WS_WT(ILVR_B, ilvr.b) +DO_MSA__WD__WS_WT(ILVR_H, ilvr.h) +DO_MSA__WD__WS_WT(ILVR_W, ilvr.w) +DO_MSA__WD__WS_WT(ILVR_D, ilvr.d) + + +/* + * Logic + * ----- + */ + +DO_MSA__WD__WS_WT(AND_V, and.v) +DO_MSA__WD__WS_WT(NOR_V, nor.v) +DO_MSA__WD__WS_WT(OR_V, or.v) +DO_MSA__WD__WS_WT(XOR_V, xor.v) + + +/* + * Pack + * ---- + */ DO_MSA__WD__WS_WT(PCKEV_B, pckev.b) DO_MSA__WD__WS_WT(PCKEV_H, pckev.h) @@ -233,6 +569,12 @@ DO_MSA__WD__WS_WT(VSHF_H, vshf.h) DO_MSA__WD__WS_WT(VSHF_W, vshf.w) DO_MSA__WD__WS_WT(VSHF_D, vshf.d) + +/* + * Shift + * ----- + */ + DO_MSA__WD__WS_WT(SLL_B, sll.b) DO_MSA__WD__WS_WT(SLL_H, sll.h) DO_MSA__WD__WS_WT(SLL_W, sll.w) @@ -258,20 +600,5 @@ DO_MSA__WD__WS_WT(SRLR_H, srlr.h) DO_MSA__WD__WS_WT(SRLR_W, srlr.w) DO_MSA__WD__WS_WT(SRLR_D, srlr.d) -DO_MSA__WD__WS_WT(BMNZ_V, bmnz.v) -DO_MSA__WD__WS_WT(BMZ_V, bmz.v) - -DO_MSA__WD__WS_WT(FMAX_W, fmax.w) -DO_MSA__WD__WS_WT(FMAX_D, fmax.d) - -DO_MSA__WD__WS_WT(FMAX_A_W, fmax_a.w) -DO_MSA__WD__WS_WT(FMAX_A_D, fmax_a.d) - -DO_MSA__WD__WS_WT(FMIN_W, fmin.w) -DO_MSA__WD__WS_WT(FMIN_D, fmin.d) - -DO_MSA__WD__WS_WT(FMIN_A_W, fmin_a.w) -DO_MSA__WD__WS_WT(FMIN_A_D, fmin_a.d) - #endif diff --git a/tests/tcg/mips/user/ase/msa/README b/tests/tcg/mips/user/ase/msa/README new file mode 100644 index 0000000000..ca4f070ec1 --- /dev/null +++ b/tests/tcg/mips/user/ase/msa/README @@ -0,0 +1,20 @@ +The tests in subdirectories of this directory are supposed to be compiled for +mips64el MSA-enabled CPU (I6400, I6500), using an appropriate MIPS toolchain. +For example: + +/opt/img/bin/mips-img-linux-gnu-gcc <source file> \ +-EL -static -mabi=64 -march=mips64r6 -mmsa -o <executable file> + +They are to be executed using QEMU user mode, using command line: + +mips64el-linux-user/qemu-mips64el -cpu I6400 <executable file> + +Helper scripts test_msa_compile.sh and test_msa_run.sh are also +provided. This is an example of compilation and execution of all +MSA tests: + +cd <QEMU root directory> +cd tests/tcg/mips/user/ase/msa + +./test_msa_compile.sh +./test_msa_run.sh diff --git a/tests/tcg/mips/user/ase/msa/bit-count/test_msa_nloc_b.c b/tests/tcg/mips/user/ase/msa/bit-count/test_msa_nloc_b.c index c73ed2464e..287054e716 100644 --- a/tests/tcg/mips/user/ase/msa/bit-count/test_msa_nloc_b.c +++ b/tests/tcg/mips/user/ase/msa/bit-count/test_msa_nloc_b.c @@ -121,6 +121,8 @@ int32_t main(void) { 0x0100010104000201ULL, 0x0200020200000003ULL, }, }; + reset_msa_registers(); + gettimeofday(&start, NULL); for (i = 0; i < TEST_COUNT_TOTAL; i++) { diff --git a/tests/tcg/mips/user/ase/msa/bit-count/test_msa_nloc_d.c b/tests/tcg/mips/user/ase/msa/bit-count/test_msa_nloc_d.c index b10fb23e88..171abdf77c 100644 --- a/tests/tcg/mips/user/ase/msa/bit-count/test_msa_nloc_d.c +++ b/tests/tcg/mips/user/ase/msa/bit-count/test_msa_nloc_d.c @@ -121,6 +121,8 @@ int32_t main(void) { 0x0000000000000001ULL, 0x0000000000000002ULL, }, }; + reset_msa_registers(); + gettimeofday(&start, NULL); for (i = 0; i < TEST_COUNT_TOTAL; i++) { diff --git a/tests/tcg/mips/user/ase/msa/bit-count/test_msa_nloc_h.c b/tests/tcg/mips/user/ase/msa/bit-count/test_msa_nloc_h.c index c1dc0754e6..f260eba7f0 100644 --- a/tests/tcg/mips/user/ase/msa/bit-count/test_msa_nloc_h.c +++ b/tests/tcg/mips/user/ase/msa/bit-count/test_msa_nloc_h.c @@ -121,6 +121,8 @@ int32_t main(void) { 0x0001000100040002ULL, 0x0002000200000000ULL, }, }; + reset_msa_registers(); + gettimeofday(&start, NULL); for (i = 0; i < TEST_COUNT_TOTAL; i++) { diff --git a/tests/tcg/mips/user/ase/msa/bit-count/test_msa_nloc_w.c b/tests/tcg/mips/user/ase/msa/bit-count/test_msa_nloc_w.c index 4f7a556dec..cb1981cafc 100644 --- a/tests/tcg/mips/user/ase/msa/bit-count/test_msa_nloc_w.c +++ b/tests/tcg/mips/user/ase/msa/bit-count/test_msa_nloc_w.c @@ -121,6 +121,8 @@ int32_t main(void) { 0x0000000100000004ULL, 0x0000000200000000ULL, }, }; + reset_msa_registers(); + gettimeofday(&start, NULL); for (i = 0; i < TEST_COUNT_TOTAL; i++) { diff --git a/tests/tcg/mips/user/ase/msa/bit-count/test_msa_nlzc_b.c b/tests/tcg/mips/user/ase/msa/bit-count/test_msa_nlzc_b.c index c202ba4856..96d05d59a1 100644 --- a/tests/tcg/mips/user/ase/msa/bit-count/test_msa_nlzc_b.c +++ b/tests/tcg/mips/user/ase/msa/bit-count/test_msa_nlzc_b.c @@ -121,6 +121,8 @@ int32_t main(void) { 0x0001000000010000ULL, 0x0001000001010300ULL, }, }; + reset_msa_registers(); + gettimeofday(&start, NULL); for (i = 0; i < TEST_COUNT_TOTAL; i++) { diff --git a/tests/tcg/mips/user/ase/msa/bit-count/test_msa_nlzc_d.c b/tests/tcg/mips/user/ase/msa/bit-count/test_msa_nlzc_d.c index 1edead2860..c709d5e852 100644 --- a/tests/tcg/mips/user/ase/msa/bit-count/test_msa_nlzc_d.c +++ b/tests/tcg/mips/user/ase/msa/bit-count/test_msa_nlzc_d.c @@ -121,6 +121,8 @@ int32_t main(void) { 0x0000000000000000ULL, 0x0000000000000000ULL, }, }; + reset_msa_registers(); + gettimeofday(&start, NULL); for (i = 0; i < TEST_COUNT_TOTAL; i++) { diff --git a/tests/tcg/mips/user/ase/msa/bit-count/test_msa_nlzc_h.c b/tests/tcg/mips/user/ase/msa/bit-count/test_msa_nlzc_h.c index b2724c532e..c47e8bfe32 100644 --- a/tests/tcg/mips/user/ase/msa/bit-count/test_msa_nlzc_h.c +++ b/tests/tcg/mips/user/ase/msa/bit-count/test_msa_nlzc_h.c @@ -121,6 +121,8 @@ int32_t main(void) { 0x0000000000000000ULL, 0x0000000000010003ULL, }, }; + reset_msa_registers(); + gettimeofday(&start, NULL); for (i = 0; i < TEST_COUNT_TOTAL; i++) { diff --git a/tests/tcg/mips/user/ase/msa/bit-count/test_msa_nlzc_w.c b/tests/tcg/mips/user/ase/msa/bit-count/test_msa_nlzc_w.c index b547c73621..a8a471ba10 100644 --- a/tests/tcg/mips/user/ase/msa/bit-count/test_msa_nlzc_w.c +++ b/tests/tcg/mips/user/ase/msa/bit-count/test_msa_nlzc_w.c @@ -121,6 +121,8 @@ int32_t main(void) { 0x0000000000000000ULL, 0x0000000000000001ULL, }, }; + reset_msa_registers(); + gettimeofday(&start, NULL); for (i = 0; i < TEST_COUNT_TOTAL; i++) { diff --git a/tests/tcg/mips/user/ase/msa/bit-count/test_msa_pcnt_b.c b/tests/tcg/mips/user/ase/msa/bit-count/test_msa_pcnt_b.c index 5918e7fcf3..067a11b48d 100644 --- a/tests/tcg/mips/user/ase/msa/bit-count/test_msa_pcnt_b.c +++ b/tests/tcg/mips/user/ase/msa/bit-count/test_msa_pcnt_b.c @@ -121,6 +121,8 @@ int32_t main(void) { 0x0404050305040605ULL, 0x0404050504030405ULL, }, }; + reset_msa_registers(); + gettimeofday(&start, NULL); for (i = 0; i < TEST_COUNT_TOTAL; i++) { diff --git a/tests/tcg/mips/user/ase/msa/bit-count/test_msa_pcnt_d.c b/tests/tcg/mips/user/ase/msa/bit-count/test_msa_pcnt_d.c index 667ca3112a..c60635df70 100644 --- a/tests/tcg/mips/user/ase/msa/bit-count/test_msa_pcnt_d.c +++ b/tests/tcg/mips/user/ase/msa/bit-count/test_msa_pcnt_d.c @@ -121,6 +121,8 @@ int32_t main(void) { 0x0000000000000024ULL, 0x0000000000000022ULL, }, }; + reset_msa_registers(); + gettimeofday(&start, NULL); for (i = 0; i < TEST_COUNT_TOTAL; i++) { diff --git a/tests/tcg/mips/user/ase/msa/bit-count/test_msa_pcnt_h.c b/tests/tcg/mips/user/ase/msa/bit-count/test_msa_pcnt_h.c index 2951f86983..8fba20a621 100644 --- a/tests/tcg/mips/user/ase/msa/bit-count/test_msa_pcnt_h.c +++ b/tests/tcg/mips/user/ase/msa/bit-count/test_msa_pcnt_h.c @@ -121,6 +121,8 @@ int32_t main(void) { 0x000800080009000bULL, 0x0008000a00070009ULL, }, }; + reset_msa_registers(); + gettimeofday(&start, NULL); for (i = 0; i < TEST_COUNT_TOTAL; i++) { diff --git a/tests/tcg/mips/user/ase/msa/bit-count/test_msa_pcnt_w.c b/tests/tcg/mips/user/ase/msa/bit-count/test_msa_pcnt_w.c index ab43ea92cd..24c44aefa1 100644 --- a/tests/tcg/mips/user/ase/msa/bit-count/test_msa_pcnt_w.c +++ b/tests/tcg/mips/user/ase/msa/bit-count/test_msa_pcnt_w.c @@ -121,6 +121,8 @@ int32_t main(void) { 0x0000001000000014ULL, 0x0000001200000010ULL, }, }; + reset_msa_registers(); + gettimeofday(&start, NULL); for (i = 0; i < TEST_COUNT_TOTAL; i++) { diff --git a/tests/tcg/mips/user/ase/msa/bit-set/test_msa_bclr_b.c b/tests/tcg/mips/user/ase/msa/bit-set/test_msa_bclr_b.c new file mode 100644 index 0000000000..e27d3b5f13 --- /dev/null +++ b/tests/tcg/mips/user/ase/msa/bit-set/test_msa_bclr_b.c @@ -0,0 +1,155 @@ +/* + * Test program for MSA instruction BCLR.B + * + * Copyright (C) 2019 Wave Computing, Inc. + * Copyright (C) 2019 Aleksandar Markovic <amarkovic@wavecomp.com> + * + * This program 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, see <https://www.gnu.org/licenses/>. + * + */ + +#include <sys/time.h> +#include <stdint.h> + +#include "../../../../include/wrappers_msa.h" +#include "../../../../include/test_inputs_128.h" +#include "../../../../include/test_utils_128.h" + +#define TEST_COUNT_TOTAL ( \ + (PATTERN_INPUTS_SHORT_COUNT) * (PATTERN_INPUTS_SHORT_COUNT) + \ + (RANDOM_INPUTS_SHORT_COUNT) * (RANDOM_INPUTS_SHORT_COUNT)) + + +int32_t main(void) +{ + char *instruction_name = "BCLR.B"; + int32_t ret; + uint32_t i, j; + struct timeval start, end; + double elapsed_time; + + uint64_t b128_result[TEST_COUNT_TOTAL][2]; + uint64_t b128_expect[TEST_COUNT_TOTAL][2] = { + { 0x7f7f7f7f7f7f7f7fULL, 0x7f7f7f7f7f7f7f7fULL, }, /* 0 */ + { 0xfefefefefefefefeULL, 0xfefefefefefefefeULL, }, + { 0xfbfbfbfbfbfbfbfbULL, 0xfbfbfbfbfbfbfbfbULL, }, + { 0xdfdfdfdfdfdfdfdfULL, 0xdfdfdfdfdfdfdfdfULL, }, + { 0xefefefefefefefefULL, 0xefefefefefefefefULL, }, + { 0xf7f7f7f7f7f7f7f7ULL, 0xf7f7f7f7f7f7f7f7ULL, }, + { 0xf7bffef7bffef7bfULL, 0xfef7bffef7bffef7ULL, }, + { 0xeffd7feffd7feffdULL, 0x7feffd7feffd7fefULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, /* 8 */ + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x2a2a2a2a2a2a2a2aULL, 0x2a2a2a2a2a2a2a2aULL, }, /* 16 */ + { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, }, + { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, }, + { 0x8a8a8a8a8a8a8a8aULL, 0x8a8a8a8a8a8a8a8aULL, }, + { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, }, + { 0xa2a2a2a2a2a2a2a2ULL, 0xa2a2a2a2a2a2a2a2ULL, }, + { 0xa2aaaaa2aaaaa2aaULL, 0xaaa2aaaaa2aaaaa2ULL, }, + { 0xaaa82aaaa82aaaa8ULL, 0x2aaaa82aaaa82aaaULL, }, + { 0x5555555555555555ULL, 0x5555555555555555ULL, }, /* 24 */ + { 0x5454545454545454ULL, 0x5454545454545454ULL, }, + { 0x5151515151515151ULL, 0x5151515151515151ULL, }, + { 0x5555555555555555ULL, 0x5555555555555555ULL, }, + { 0x4545454545454545ULL, 0x4545454545454545ULL, }, + { 0x5555555555555555ULL, 0x5555555555555555ULL, }, + { 0x5515545515545515ULL, 0x5455155455155455ULL, }, + { 0x4555554555554555ULL, 0x5545555545555545ULL, }, + { 0x4c4c4c4c4c4c4c4cULL, 0x4c4c4c4c4c4c4c4cULL, }, /* 32 */ + { 0xccccccccccccccccULL, 0xccccccccccccccccULL, }, + { 0xc8c8c8c8c8c8c8c8ULL, 0xc8c8c8c8c8c8c8c8ULL, }, + { 0xccccccccccccccccULL, 0xccccccccccccccccULL, }, + { 0xccccccccccccccccULL, 0xccccccccccccccccULL, }, + { 0xc4c4c4c4c4c4c4c4ULL, 0xc4c4c4c4c4c4c4c4ULL, }, + { 0xc48cccc48cccc48cULL, 0xccc48cccc48cccc4ULL, }, + { 0xcccc4ccccc4cccccULL, 0x4ccccc4ccccc4cccULL, }, + { 0x3333333333333333ULL, 0x3333333333333333ULL, }, /* 40 */ + { 0x3232323232323232ULL, 0x3232323232323232ULL, }, + { 0x3333333333333333ULL, 0x3333333333333333ULL, }, + { 0x1313131313131313ULL, 0x1313131313131313ULL, }, + { 0x2323232323232323ULL, 0x2323232323232323ULL, }, + { 0x3333333333333333ULL, 0x3333333333333333ULL, }, + { 0x3333323333323333ULL, 0x3233333233333233ULL, }, + { 0x2331332331332331ULL, 0x3323313323313323ULL, }, + { 0x630e38630e38630eULL, 0x38630e38630e3863ULL, }, /* 48 */ + { 0xe28e38e28e38e28eULL, 0x38e28e38e28e38e2ULL, }, + { 0xe38a38e38a38e38aULL, 0x38e38a38e38a38e3ULL, }, + { 0xc38e18c38e18c38eULL, 0x18c38e18c38e18c3ULL, }, + { 0xe38e28e38e28e38eULL, 0x28e38e28e38e28e3ULL, }, + { 0xe38630e38630e386ULL, 0x30e38630e38630e3ULL, }, + { 0xe38e38e38e38e38eULL, 0x38e38e38e38e38e3ULL, }, + { 0xe38c38e38c38e38cULL, 0x38e38c38e38c38e3ULL, }, + { 0x1c71471c71471c71ULL, 0x471c71471c71471cULL, }, /* 56 */ + { 0x1c70c61c70c61c70ULL, 0xc61c70c61c70c61cULL, }, + { 0x1871c31871c31871ULL, 0xc31871c31871c318ULL, }, + { 0x1c51c71c51c71c51ULL, 0xc71c51c71c51c71cULL, }, + { 0x0c61c70c61c70c61ULL, 0xc70c61c70c61c70cULL, }, + { 0x1471c71471c71471ULL, 0xc71471c71471c714ULL, }, + { 0x1431c61431c61431ULL, 0xc61431c61431c614ULL, }, + { 0x0c71470c71470c71ULL, 0x470c71470c71470cULL, }, + { 0x886aa6cc28625540ULL, 0x4367031ebe73b00cULL, }, /* 64 */ + { 0x802ae6c408625540ULL, 0x4b67035ade7bb00cULL, }, + { 0x886aa6c828625540ULL, 0x4b660b5ef673900cULL, }, + { 0x886aa6cc28605100ULL, 0x4b650a5efc7bb00cULL, }, + { 0xfaba00634c93c708ULL, 0x1277b31a153752ecULL, }, + { 0xf3be00634d934708ULL, 0x1277b31a153f52ecULL, }, + { 0xebba00634d13c708ULL, 0x12f6bb1a153752ecULL, }, + { 0xfa3e00430d91c308ULL, 0x12f5ba1a153b52fcULL, }, + { 0xac5aaeaab8cb8b80ULL, 0x2758c6bfab232404ULL, }, /* 72 */ + { 0xa41aaea299c70b80ULL, 0x2358c6fb8b2b2104ULL, }, + { 0xac5aaeaab94f8380ULL, 0x27d8867fa3230504ULL, }, + { 0xac5aae8ab9cd8b80ULL, 0x07d8c6fea92b2114ULL, }, + { 0x704b164d5e31c24eULL, 0x85718098a942e2a0ULL, }, + { 0x700f16455e31624eULL, 0x897180d88942e2a0ULL, }, + { 0x604b16495c31e24eULL, 0x0df08858a142c2a0ULL, }, + { 0x704f164d1e31e20eULL, 0x8df188d8a942e2a0ULL, }, + }; + + reset_msa_registers(); + + gettimeofday(&start, NULL); + + for (i = 0; i < PATTERN_INPUTS_SHORT_COUNT; i++) { + for (j = 0; j < PATTERN_INPUTS_SHORT_COUNT; j++) { + do_msa_BCLR_B(b128_pattern[i], b128_pattern[j], + b128_result[PATTERN_INPUTS_SHORT_COUNT * i + j]); + } + } + + for (i = 0; i < RANDOM_INPUTS_SHORT_COUNT; i++) { + for (j = 0; j < RANDOM_INPUTS_SHORT_COUNT; j++) { + do_msa_BCLR_B(b128_random[i], b128_random[j], + b128_result[((PATTERN_INPUTS_SHORT_COUNT) * + (PATTERN_INPUTS_SHORT_COUNT)) + + RANDOM_INPUTS_SHORT_COUNT * i + j]); + } + } + + gettimeofday(&end, NULL); + + elapsed_time = (end.tv_sec - start.tv_sec) * 1000.0; + elapsed_time += (end.tv_usec - start.tv_usec) / 1000.0; + + ret = check_results(instruction_name, TEST_COUNT_TOTAL, elapsed_time, + &b128_result[0][0], &b128_expect[0][0]); + + return ret; +} diff --git a/tests/tcg/mips/user/ase/msa/bit-set/test_msa_bclr_d.c b/tests/tcg/mips/user/ase/msa/bit-set/test_msa_bclr_d.c new file mode 100644 index 0000000000..3b8c38494b --- /dev/null +++ b/tests/tcg/mips/user/ase/msa/bit-set/test_msa_bclr_d.c @@ -0,0 +1,155 @@ +/* + * Test program for MSA instruction BCLR.D + * + * Copyright (C) 2019 Wave Computing, Inc. + * Copyright (C) 2019 Aleksandar Markovic <amarkovic@wavecomp.com> + * + * This program 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, see <https://www.gnu.org/licenses/>. + * + */ + +#include <sys/time.h> +#include <stdint.h> + +#include "../../../../include/wrappers_msa.h" +#include "../../../../include/test_inputs_128.h" +#include "../../../../include/test_utils_128.h" + +#define TEST_COUNT_TOTAL ( \ + (PATTERN_INPUTS_SHORT_COUNT) * (PATTERN_INPUTS_SHORT_COUNT) + \ + (RANDOM_INPUTS_SHORT_COUNT) * (RANDOM_INPUTS_SHORT_COUNT)) + + +int32_t main(void) +{ + char *instruction_name = "BCLR.D"; + int32_t ret; + uint32_t i, j; + struct timeval start, end; + double elapsed_time; + + uint64_t b128_result[TEST_COUNT_TOTAL][2]; + uint64_t b128_expect[TEST_COUNT_TOTAL][2] = { + { 0x7fffffffffffffffULL, 0x7fffffffffffffffULL, }, /* 0 */ + { 0xfffffffffffffffeULL, 0xfffffffffffffffeULL, }, + { 0xfffffbffffffffffULL, 0xfffffbffffffffffULL, }, + { 0xffffffffffdfffffULL, 0xffffffffffdfffffULL, }, + { 0xffffffffffffefffULL, 0xffffffffffffefffULL, }, + { 0xfff7ffffffffffffULL, 0xfff7ffffffffffffULL, }, + { 0xffffffffffffbfffULL, 0xfffffff7ffffffffULL, }, + { 0xfffdffffffffffffULL, 0xffffffffefffffffULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, /* 8 */ + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x2aaaaaaaaaaaaaaaULL, 0x2aaaaaaaaaaaaaaaULL, }, /* 16 */ + { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, }, + { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, }, + { 0xaaaaaaaaaa8aaaaaULL, 0xaaaaaaaaaa8aaaaaULL, }, + { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, }, + { 0xaaa2aaaaaaaaaaaaULL, 0xaaa2aaaaaaaaaaaaULL, }, + { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaa2aaaaaaaaULL, }, + { 0xaaa8aaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, }, + { 0x5555555555555555ULL, 0x5555555555555555ULL, }, /* 24 */ + { 0x5555555555555554ULL, 0x5555555555555554ULL, }, + { 0x5555515555555555ULL, 0x5555515555555555ULL, }, + { 0x5555555555555555ULL, 0x5555555555555555ULL, }, + { 0x5555555555554555ULL, 0x5555555555554555ULL, }, + { 0x5555555555555555ULL, 0x5555555555555555ULL, }, + { 0x5555555555551555ULL, 0x5555555555555555ULL, }, + { 0x5555555555555555ULL, 0x5555555545555555ULL, }, + { 0x4cccccccccccccccULL, 0x4cccccccccccccccULL, }, /* 32 */ + { 0xccccccccccccccccULL, 0xccccccccccccccccULL, }, + { 0xccccc8ccccccccccULL, 0xccccc8ccccccccccULL, }, + { 0xccccccccccccccccULL, 0xccccccccccccccccULL, }, + { 0xccccccccccccccccULL, 0xccccccccccccccccULL, }, + { 0xccc4ccccccccccccULL, 0xccc4ccccccccccccULL, }, + { 0xcccccccccccc8cccULL, 0xccccccc4ccccccccULL, }, + { 0xccccccccccccccccULL, 0xccccccccccccccccULL, }, + { 0x3333333333333333ULL, 0x3333333333333333ULL, }, /* 40 */ + { 0x3333333333333332ULL, 0x3333333333333332ULL, }, + { 0x3333333333333333ULL, 0x3333333333333333ULL, }, + { 0x3333333333133333ULL, 0x3333333333133333ULL, }, + { 0x3333333333332333ULL, 0x3333333333332333ULL, }, + { 0x3333333333333333ULL, 0x3333333333333333ULL, }, + { 0x3333333333333333ULL, 0x3333333333333333ULL, }, + { 0x3331333333333333ULL, 0x3333333323333333ULL, }, + { 0x638e38e38e38e38eULL, 0x38e38e38e38e38e3ULL, }, /* 48 */ + { 0xe38e38e38e38e38eULL, 0x38e38e38e38e38e2ULL, }, + { 0xe38e38e38e38e38eULL, 0x38e38a38e38e38e3ULL, }, + { 0xe38e38e38e18e38eULL, 0x38e38e38e38e38e3ULL, }, + { 0xe38e38e38e38e38eULL, 0x38e38e38e38e28e3ULL, }, + { 0xe38638e38e38e38eULL, 0x38e38e38e38e38e3ULL, }, + { 0xe38e38e38e38a38eULL, 0x38e38e30e38e38e3ULL, }, + { 0xe38c38e38e38e38eULL, 0x38e38e38e38e38e3ULL, }, + { 0x1c71c71c71c71c71ULL, 0x471c71c71c71c71cULL, }, /* 56 */ + { 0x1c71c71c71c71c70ULL, 0xc71c71c71c71c71cULL, }, + { 0x1c71c31c71c71c71ULL, 0xc71c71c71c71c71cULL, }, + { 0x1c71c71c71c71c71ULL, 0xc71c71c71c51c71cULL, }, + { 0x1c71c71c71c70c71ULL, 0xc71c71c71c71c71cULL, }, + { 0x1c71c71c71c71c71ULL, 0xc71471c71c71c71cULL, }, + { 0x1c71c71c71c71c71ULL, 0xc71c71c71c71c71cULL, }, + { 0x1c71c71c71c71c71ULL, 0xc71c71c70c71c71cULL, }, + { 0x886ae6cc28625540ULL, 0x4b670b5efe7ba00cULL, }, /* 64 */ + { 0x886ae6cc28625440ULL, 0x4b670b5efe7bb00cULL, }, + { 0x886ae6cc28625540ULL, 0x4b670b5efe6bb00cULL, }, + { 0x886ae6cc28621540ULL, 0x4b670b5efe7bb00cULL, }, + { 0xfbbe00634d93c708ULL, 0x12f7bb1a153f42fcULL, }, + { 0xfbbe00634d93c608ULL, 0x02f7bb1a153f52fcULL, }, + { 0xfbbe00634d93c708ULL, 0x12f7bb1a152f52fcULL, }, + { 0xfbbe00634d938708ULL, 0x12f7bb1a153f52fcULL, }, + { 0xac5aaeaab9cf8b80ULL, 0x27d8c6ffab2b2514ULL, }, /* 72 */ + { 0xac5aaeaab9cf8a80ULL, 0x27d8c6ffab2b2514ULL, }, + { 0xac5aaeaab9cf8b80ULL, 0x27d8c6ffab2b2514ULL, }, + { 0xac5aaeaab9cf8b80ULL, 0x27d8c6feab2b2514ULL, }, + { 0x704f164d5e31e24eULL, 0x8df188d8a942e2a0ULL, }, + { 0x704f164d5e31e24eULL, 0x8df188d8a942e2a0ULL, }, + { 0x704f164d5e31e24eULL, 0x8df188d8a942e2a0ULL, }, + { 0x704f164d5e31a24eULL, 0x8df188d8a942e2a0ULL, }, + }; + + reset_msa_registers(); + + gettimeofday(&start, NULL); + + for (i = 0; i < PATTERN_INPUTS_SHORT_COUNT; i++) { + for (j = 0; j < PATTERN_INPUTS_SHORT_COUNT; j++) { + do_msa_BCLR_D(b128_pattern[i], b128_pattern[j], + b128_result[PATTERN_INPUTS_SHORT_COUNT * i + j]); + } + } + + for (i = 0; i < RANDOM_INPUTS_SHORT_COUNT; i++) { + for (j = 0; j < RANDOM_INPUTS_SHORT_COUNT; j++) { + do_msa_BCLR_D(b128_random[i], b128_random[j], + b128_result[((PATTERN_INPUTS_SHORT_COUNT) * + (PATTERN_INPUTS_SHORT_COUNT)) + + RANDOM_INPUTS_SHORT_COUNT * i + j]); + } + } + + gettimeofday(&end, NULL); + + elapsed_time = (end.tv_sec - start.tv_sec) * 1000.0; + elapsed_time += (end.tv_usec - start.tv_usec) / 1000.0; + + ret = check_results(instruction_name, TEST_COUNT_TOTAL, elapsed_time, + &b128_result[0][0], &b128_expect[0][0]); + + return ret; +} diff --git a/tests/tcg/mips/user/ase/msa/bit-set/test_msa_bclr_h.c b/tests/tcg/mips/user/ase/msa/bit-set/test_msa_bclr_h.c new file mode 100644 index 0000000000..d1db60fb02 --- /dev/null +++ b/tests/tcg/mips/user/ase/msa/bit-set/test_msa_bclr_h.c @@ -0,0 +1,155 @@ +/* + * Test program for MSA instruction BCLR.H + * + * Copyright (C) 2019 Wave Computing, Inc. + * Copyright (C) 2019 Aleksandar Markovic <amarkovic@wavecomp.com> + * + * This program 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, see <https://www.gnu.org/licenses/>. + * + */ + +#include <sys/time.h> +#include <stdint.h> + +#include "../../../../include/wrappers_msa.h" +#include "../../../../include/test_inputs_128.h" +#include "../../../../include/test_utils_128.h" + +#define TEST_COUNT_TOTAL ( \ + (PATTERN_INPUTS_SHORT_COUNT) * (PATTERN_INPUTS_SHORT_COUNT) + \ + (RANDOM_INPUTS_SHORT_COUNT) * (RANDOM_INPUTS_SHORT_COUNT)) + + +int32_t main(void) +{ + char *instruction_name = "BCLR.H"; + int32_t ret; + uint32_t i, j; + struct timeval start, end; + double elapsed_time; + + uint64_t b128_result[TEST_COUNT_TOTAL][2]; + uint64_t b128_expect[TEST_COUNT_TOTAL][2] = { + { 0x7fff7fff7fff7fffULL, 0x7fff7fff7fff7fffULL, }, /* 0 */ + { 0xfffefffefffefffeULL, 0xfffefffefffefffeULL, }, + { 0xfbfffbfffbfffbffULL, 0xfbfffbfffbfffbffULL, }, + { 0xffdfffdfffdfffdfULL, 0xffdfffdfffdfffdfULL, }, + { 0xefffefffefffefffULL, 0xefffefffefffefffULL, }, + { 0xfff7fff7fff7fff7ULL, 0xfff7fff7fff7fff7ULL, }, + { 0xbffffff7feffbfffULL, 0xfff7feffbffffff7ULL, }, + { 0xfffdefffff7ffffdULL, 0xefffff7ffffdefffULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, /* 8 */ + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x2aaa2aaa2aaa2aaaULL, 0x2aaa2aaa2aaa2aaaULL, }, /* 16 */ + { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, }, + { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, }, + { 0xaa8aaa8aaa8aaa8aULL, 0xaa8aaa8aaa8aaa8aULL, }, + { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, }, + { 0xaaa2aaa2aaa2aaa2ULL, 0xaaa2aaa2aaa2aaa2ULL, }, + { 0xaaaaaaa2aaaaaaaaULL, 0xaaa2aaaaaaaaaaa2ULL, }, + { 0xaaa8aaaaaa2aaaa8ULL, 0xaaaaaa2aaaa8aaaaULL, }, + { 0x5555555555555555ULL, 0x5555555555555555ULL, }, /* 24 */ + { 0x5554555455545554ULL, 0x5554555455545554ULL, }, + { 0x5155515551555155ULL, 0x5155515551555155ULL, }, + { 0x5555555555555555ULL, 0x5555555555555555ULL, }, + { 0x4555455545554555ULL, 0x4555455545554555ULL, }, + { 0x5555555555555555ULL, 0x5555555555555555ULL, }, + { 0x1555555554551555ULL, 0x5555545515555555ULL, }, + { 0x5555455555555555ULL, 0x4555555555554555ULL, }, + { 0x4ccc4ccc4ccc4cccULL, 0x4ccc4ccc4ccc4cccULL, }, /* 32 */ + { 0xccccccccccccccccULL, 0xccccccccccccccccULL, }, + { 0xc8ccc8ccc8ccc8ccULL, 0xc8ccc8ccc8ccc8ccULL, }, + { 0xccccccccccccccccULL, 0xccccccccccccccccULL, }, + { 0xccccccccccccccccULL, 0xccccccccccccccccULL, }, + { 0xccc4ccc4ccc4ccc4ULL, 0xccc4ccc4ccc4ccc4ULL, }, + { 0x8cccccc4cccc8cccULL, 0xccc4cccc8cccccc4ULL, }, + { 0xcccccccccc4cccccULL, 0xcccccc4cccccccccULL, }, + { 0x3333333333333333ULL, 0x3333333333333333ULL, }, /* 40 */ + { 0x3332333233323332ULL, 0x3332333233323332ULL, }, + { 0x3333333333333333ULL, 0x3333333333333333ULL, }, + { 0x3313331333133313ULL, 0x3313331333133313ULL, }, + { 0x2333233323332333ULL, 0x2333233323332333ULL, }, + { 0x3333333333333333ULL, 0x3333333333333333ULL, }, + { 0x3333333332333333ULL, 0x3333323333333333ULL, }, + { 0x3331233333333331ULL, 0x2333333333312333ULL, }, + { 0x638e38e30e38638eULL, 0x38e30e38638e38e3ULL, }, /* 48 */ + { 0xe38e38e28e38e38eULL, 0x38e28e38e38e38e2ULL, }, + { 0xe38e38e38a38e38eULL, 0x38e38a38e38e38e3ULL, }, + { 0xe38e38c38e18e38eULL, 0x38c38e18e38e38c3ULL, }, + { 0xe38e28e38e38e38eULL, 0x28e38e38e38e28e3ULL, }, + { 0xe38638e38e30e386ULL, 0x38e38e30e38638e3ULL, }, + { 0xa38e38e38e38a38eULL, 0x38e38e38a38e38e3ULL, }, + { 0xe38c28e38e38e38cULL, 0x28e38e38e38c28e3ULL, }, + { 0x1c71471c71c71c71ULL, 0x471c71c71c71471cULL, }, /* 56 */ + { 0x1c70c71c71c61c70ULL, 0xc71c71c61c70c71cULL, }, + { 0x1871c31c71c71871ULL, 0xc31c71c71871c31cULL, }, + { 0x1c51c71c71c71c51ULL, 0xc71c71c71c51c71cULL, }, + { 0x0c71c71c61c70c71ULL, 0xc71c61c70c71c71cULL, }, + { 0x1c71c71471c71c71ULL, 0xc71471c71c71c714ULL, }, + { 0x1c71c71470c71c71ULL, 0xc71470c71c71c714ULL, }, + { 0x1c71c71c71471c71ULL, 0xc71c71471c71c71cULL, }, + { 0x886ae6cc28625540ULL, 0x4b670b5ef67ba00cULL, }, /* 64 */ + { 0x886ae6c428625440ULL, 0x4b670b5e7e7ba00cULL, }, + { 0x886ae2cc28625540ULL, 0x4a670b5ef67bb00cULL, }, + { 0x086ac6cc28601540ULL, 0x4b650a5efe7bb00cULL, }, + { 0xfbbe00634d93c708ULL, 0x1277bb1a153f42fcULL, }, + { 0xbbbe00634d93c608ULL, 0x1277bb1a153f42fcULL, }, + { 0xfbbe00634d93c708ULL, 0x12f73b1a153f52ecULL, }, + { 0x7bbe00634d918708ULL, 0x12f5ba1a153b52fcULL, }, + { 0xa85aaeaab9cb8b80ULL, 0x275886ffa32b2514ULL, }, /* 72 */ + { 0xac5aaea2b9c78a80ULL, 0x2758c2ff2b2b2514ULL, }, + { 0xa85aaaaa39cf8b80ULL, 0x26d846ffa32b2504ULL, }, + { 0x2c5a8eaab9cd8b80ULL, 0x27d8c6ffab2b2514ULL, }, + { 0x704f064d5e31e24eULL, 0x8d7188d8a142e2a0ULL, }, + { 0x304f16455e31e24eULL, 0x8d7188d82942e2a0ULL, }, + { 0x704f124d5e31e24eULL, 0x8cf108d8a142e2a0ULL, }, + { 0x704f164d5e31a24eULL, 0x8df188d8a942e2a0ULL, }, + }; + + reset_msa_registers(); + + gettimeofday(&start, NULL); + + for (i = 0; i < PATTERN_INPUTS_SHORT_COUNT; i++) { + for (j = 0; j < PATTERN_INPUTS_SHORT_COUNT; j++) { + do_msa_BCLR_H(b128_pattern[i], b128_pattern[j], + b128_result[PATTERN_INPUTS_SHORT_COUNT * i + j]); + } + } + + for (i = 0; i < RANDOM_INPUTS_SHORT_COUNT; i++) { + for (j = 0; j < RANDOM_INPUTS_SHORT_COUNT; j++) { + do_msa_BCLR_H(b128_random[i], b128_random[j], + b128_result[((PATTERN_INPUTS_SHORT_COUNT) * + (PATTERN_INPUTS_SHORT_COUNT)) + + RANDOM_INPUTS_SHORT_COUNT * i + j]); + } + } + + gettimeofday(&end, NULL); + + elapsed_time = (end.tv_sec - start.tv_sec) * 1000.0; + elapsed_time += (end.tv_usec - start.tv_usec) / 1000.0; + + ret = check_results(instruction_name, TEST_COUNT_TOTAL, elapsed_time, + &b128_result[0][0], &b128_expect[0][0]); + + return ret; +} diff --git a/tests/tcg/mips/user/ase/msa/bit-set/test_msa_bclr_w.c b/tests/tcg/mips/user/ase/msa/bit-set/test_msa_bclr_w.c new file mode 100644 index 0000000000..54087b7c6e --- /dev/null +++ b/tests/tcg/mips/user/ase/msa/bit-set/test_msa_bclr_w.c @@ -0,0 +1,155 @@ +/* + * Test program for MSA instruction BCLR.W + * + * Copyright (C) 2019 Wave Computing, Inc. + * Copyright (C) 2019 Aleksandar Markovic <amarkovic@wavecomp.com> + * + * This program 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, see <https://www.gnu.org/licenses/>. + * + */ + +#include <sys/time.h> +#include <stdint.h> + +#include "../../../../include/wrappers_msa.h" +#include "../../../../include/test_inputs_128.h" +#include "../../../../include/test_utils_128.h" + +#define TEST_COUNT_TOTAL ( \ + (PATTERN_INPUTS_SHORT_COUNT) * (PATTERN_INPUTS_SHORT_COUNT) + \ + (RANDOM_INPUTS_SHORT_COUNT) * (RANDOM_INPUTS_SHORT_COUNT)) + + +int32_t main(void) +{ + char *instruction_name = "BCLR.W"; + int32_t ret; + uint32_t i, j; + struct timeval start, end; + double elapsed_time; + + uint64_t b128_result[TEST_COUNT_TOTAL][2]; + uint64_t b128_expect[TEST_COUNT_TOTAL][2] = { + { 0x7fffffff7fffffffULL, 0x7fffffff7fffffffULL, }, /* 0 */ + { 0xfffffffefffffffeULL, 0xfffffffefffffffeULL, }, + { 0xfffffbfffffffbffULL, 0xfffffbfffffffbffULL, }, + { 0xffdfffffffdfffffULL, 0xffdfffffffdfffffULL, }, + { 0xffffefffffffefffULL, 0xffffefffffffefffULL, }, + { 0xfff7fffffff7ffffULL, 0xfff7fffffff7ffffULL, }, + { 0xfffffff7ffffbfffULL, 0xfefffffffffffff7ULL, }, + { 0xeffffffffffdffffULL, 0xffffff7fefffffffULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, /* 8 */ + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x2aaaaaaa2aaaaaaaULL, 0x2aaaaaaa2aaaaaaaULL, }, /* 16 */ + { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, }, + { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, }, + { 0xaa8aaaaaaa8aaaaaULL, 0xaa8aaaaaaa8aaaaaULL, }, + { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, }, + { 0xaaa2aaaaaaa2aaaaULL, 0xaaa2aaaaaaa2aaaaULL, }, + { 0xaaaaaaa2aaaaaaaaULL, 0xaaaaaaaaaaaaaaa2ULL, }, + { 0xaaaaaaaaaaa8aaaaULL, 0xaaaaaa2aaaaaaaaaULL, }, + { 0x5555555555555555ULL, 0x5555555555555555ULL, }, /* 24 */ + { 0x5555555455555554ULL, 0x5555555455555554ULL, }, + { 0x5555515555555155ULL, 0x5555515555555155ULL, }, + { 0x5555555555555555ULL, 0x5555555555555555ULL, }, + { 0x5555455555554555ULL, 0x5555455555554555ULL, }, + { 0x5555555555555555ULL, 0x5555555555555555ULL, }, + { 0x5555555555551555ULL, 0x5455555555555555ULL, }, + { 0x4555555555555555ULL, 0x5555555545555555ULL, }, + { 0x4ccccccc4cccccccULL, 0x4ccccccc4cccccccULL, }, /* 32 */ + { 0xccccccccccccccccULL, 0xccccccccccccccccULL, }, + { 0xccccc8ccccccc8ccULL, 0xccccc8ccccccc8ccULL, }, + { 0xccccccccccccccccULL, 0xccccccccccccccccULL, }, + { 0xccccccccccccccccULL, 0xccccccccccccccccULL, }, + { 0xccc4ccccccc4ccccULL, 0xccc4ccccccc4ccccULL, }, + { 0xccccccc4cccc8cccULL, 0xccccccccccccccc4ULL, }, + { 0xccccccccccccccccULL, 0xcccccc4cccccccccULL, }, + { 0x3333333333333333ULL, 0x3333333333333333ULL, }, /* 40 */ + { 0x3333333233333332ULL, 0x3333333233333332ULL, }, + { 0x3333333333333333ULL, 0x3333333333333333ULL, }, + { 0x3313333333133333ULL, 0x3313333333133333ULL, }, + { 0x3333233333332333ULL, 0x3333233333332333ULL, }, + { 0x3333333333333333ULL, 0x3333333333333333ULL, }, + { 0x3333333333333333ULL, 0x3233333333333333ULL, }, + { 0x2333333333313333ULL, 0x3333333323333333ULL, }, + { 0x638e38e30e38e38eULL, 0x38e38e38638e38e3ULL, }, /* 48 */ + { 0xe38e38e28e38e38eULL, 0x38e38e38e38e38e2ULL, }, + { 0xe38e38e38e38e38eULL, 0x38e38a38e38e38e3ULL, }, + { 0xe38e38e38e18e38eULL, 0x38c38e38e38e38e3ULL, }, + { 0xe38e28e38e38e38eULL, 0x38e38e38e38e28e3ULL, }, + { 0xe38638e38e30e38eULL, 0x38e38e38e38638e3ULL, }, + { 0xe38e38e38e38a38eULL, 0x38e38e38e38e38e3ULL, }, + { 0xe38e38e38e38e38eULL, 0x38e38e38e38e38e3ULL, }, + { 0x1c71c71c71c71c71ULL, 0x471c71c71c71c71cULL, }, /* 56 */ + { 0x1c71c71c71c71c70ULL, 0xc71c71c61c71c71cULL, }, + { 0x1c71c31c71c71871ULL, 0xc71c71c71c71c31cULL, }, + { 0x1c51c71c71c71c71ULL, 0xc71c71c71c51c71cULL, }, + { 0x1c71c71c71c70c71ULL, 0xc71c61c71c71c71cULL, }, + { 0x1c71c71c71c71c71ULL, 0xc71471c71c71c71cULL, }, + { 0x1c71c71471c71c71ULL, 0xc61c71c71c71c714ULL, }, + { 0x0c71c71c71c51c71ULL, 0xc71c71470c71c71cULL, }, + { 0x886ae6cc28625540ULL, 0x0b670b5efe7ba00cULL, }, /* 64 */ + { 0x886ae6c428625440ULL, 0x4b670b5eee7bb00cULL, }, + { 0x886ae2cc28625540ULL, 0x4b670b5efe6bb00cULL, }, + { 0x886ac6cc28621540ULL, 0x4a670b5efe7bb00cULL, }, + { 0xfbbe00634d93c708ULL, 0x12f7bb1a153f42fcULL, }, + { 0xfbbe00634d93c608ULL, 0x12f7bb1a053f52fcULL, }, + { 0xfbbe00634d93c708ULL, 0x12f7bb1a152f52fcULL, }, + { 0xfbbe00634d938708ULL, 0x12f7bb1a153f52fcULL, }, + { 0xac5aaeaab9cf8b80ULL, 0x27d8c6ffab2b2514ULL, }, /* 72 */ + { 0xac5aaea2b9cf8a80ULL, 0x23d8c6ffab2b2514ULL, }, + { 0xac5aaaaab9cf8b80ULL, 0x27d8c6ffab2b2514ULL, }, + { 0xac5a8eaab9cf8b80ULL, 0x26d8c6ffab2b2514ULL, }, + { 0x704f064d5e31e24eULL, 0x8df188d8a942e2a0ULL, }, + { 0x704f16455e31e24eULL, 0x89f188d8a942e2a0ULL, }, + { 0x704f124d5e31e24eULL, 0x0df188d8a942e2a0ULL, }, + { 0x704f164d5e31a24eULL, 0x8cf188d8a942e2a0ULL, }, + }; + + reset_msa_registers(); + + gettimeofday(&start, NULL); + + for (i = 0; i < PATTERN_INPUTS_SHORT_COUNT; i++) { + for (j = 0; j < PATTERN_INPUTS_SHORT_COUNT; j++) { + do_msa_BCLR_W(b128_pattern[i], b128_pattern[j], + b128_result[PATTERN_INPUTS_SHORT_COUNT * i + j]); + } + } + + for (i = 0; i < RANDOM_INPUTS_SHORT_COUNT; i++) { + for (j = 0; j < RANDOM_INPUTS_SHORT_COUNT; j++) { + do_msa_BCLR_W(b128_random[i], b128_random[j], + b128_result[((PATTERN_INPUTS_SHORT_COUNT) * + (PATTERN_INPUTS_SHORT_COUNT)) + + RANDOM_INPUTS_SHORT_COUNT * i + j]); + } + } + + gettimeofday(&end, NULL); + + elapsed_time = (end.tv_sec - start.tv_sec) * 1000.0; + elapsed_time += (end.tv_usec - start.tv_usec) / 1000.0; + + ret = check_results(instruction_name, TEST_COUNT_TOTAL, elapsed_time, + &b128_result[0][0], &b128_expect[0][0]); + + return ret; +} diff --git a/tests/tcg/mips/user/ase/msa/bit-set/test_msa_bneg_b.c b/tests/tcg/mips/user/ase/msa/bit-set/test_msa_bneg_b.c new file mode 100644 index 0000000000..733bc24867 --- /dev/null +++ b/tests/tcg/mips/user/ase/msa/bit-set/test_msa_bneg_b.c @@ -0,0 +1,155 @@ +/* + * Test program for MSA instruction BNEG.B + * + * Copyright (C) 2019 Wave Computing, Inc. + * Copyright (C) 2019 Aleksandar Markovic <amarkovic@wavecomp.com> + * + * This program 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, see <https://www.gnu.org/licenses/>. + * + */ + +#include <sys/time.h> +#include <stdint.h> + +#include "../../../../include/wrappers_msa.h" +#include "../../../../include/test_inputs_128.h" +#include "../../../../include/test_utils_128.h" + +#define TEST_COUNT_TOTAL ( \ + (PATTERN_INPUTS_SHORT_COUNT) * (PATTERN_INPUTS_SHORT_COUNT) + \ + (RANDOM_INPUTS_SHORT_COUNT) * (RANDOM_INPUTS_SHORT_COUNT)) + + +int32_t main(void) +{ + char *instruction_name = "BNEG.B"; + int32_t ret; + uint32_t i, j; + struct timeval start, end; + double elapsed_time; + + uint64_t b128_result[TEST_COUNT_TOTAL][2]; + uint64_t b128_expect[TEST_COUNT_TOTAL][2] = { + { 0x7f7f7f7f7f7f7f7fULL, 0x7f7f7f7f7f7f7f7fULL, }, /* 0 */ + { 0xfefefefefefefefeULL, 0xfefefefefefefefeULL, }, + { 0xfbfbfbfbfbfbfbfbULL, 0xfbfbfbfbfbfbfbfbULL, }, + { 0xdfdfdfdfdfdfdfdfULL, 0xdfdfdfdfdfdfdfdfULL, }, + { 0xefefefefefefefefULL, 0xefefefefefefefefULL, }, + { 0xf7f7f7f7f7f7f7f7ULL, 0xf7f7f7f7f7f7f7f7ULL, }, + { 0xf7bffef7bffef7bfULL, 0xfef7bffef7bffef7ULL, }, + { 0xeffd7feffd7feffdULL, 0x7feffd7feffd7fefULL, }, + { 0x8080808080808080ULL, 0x8080808080808080ULL, }, /* 8 */ + { 0x0101010101010101ULL, 0x0101010101010101ULL, }, + { 0x0404040404040404ULL, 0x0404040404040404ULL, }, + { 0x2020202020202020ULL, 0x2020202020202020ULL, }, + { 0x1010101010101010ULL, 0x1010101010101010ULL, }, + { 0x0808080808080808ULL, 0x0808080808080808ULL, }, + { 0x0840010840010840ULL, 0x0108400108400108ULL, }, + { 0x1002801002801002ULL, 0x8010028010028010ULL, }, + { 0x2a2a2a2a2a2a2a2aULL, 0x2a2a2a2a2a2a2a2aULL, }, /* 16 */ + { 0xababababababababULL, 0xababababababababULL, }, + { 0xaeaeaeaeaeaeaeaeULL, 0xaeaeaeaeaeaeaeaeULL, }, + { 0x8a8a8a8a8a8a8a8aULL, 0x8a8a8a8a8a8a8a8aULL, }, + { 0xbabababababababaULL, 0xbabababababababaULL, }, + { 0xa2a2a2a2a2a2a2a2ULL, 0xa2a2a2a2a2a2a2a2ULL, }, + { 0xa2eaaba2eaaba2eaULL, 0xaba2eaaba2eaaba2ULL, }, + { 0xbaa82abaa82abaa8ULL, 0x2abaa82abaa82abaULL, }, + { 0xd5d5d5d5d5d5d5d5ULL, 0xd5d5d5d5d5d5d5d5ULL, }, /* 24 */ + { 0x5454545454545454ULL, 0x5454545454545454ULL, }, + { 0x5151515151515151ULL, 0x5151515151515151ULL, }, + { 0x7575757575757575ULL, 0x7575757575757575ULL, }, + { 0x4545454545454545ULL, 0x4545454545454545ULL, }, + { 0x5d5d5d5d5d5d5d5dULL, 0x5d5d5d5d5d5d5d5dULL, }, + { 0x5d15545d15545d15ULL, 0x545d15545d15545dULL, }, + { 0x4557d54557d54557ULL, 0xd54557d54557d545ULL, }, + { 0x4c4c4c4c4c4c4c4cULL, 0x4c4c4c4c4c4c4c4cULL, }, /* 32 */ + { 0xcdcdcdcdcdcdcdcdULL, 0xcdcdcdcdcdcdcdcdULL, }, + { 0xc8c8c8c8c8c8c8c8ULL, 0xc8c8c8c8c8c8c8c8ULL, }, + { 0xececececececececULL, 0xececececececececULL, }, + { 0xdcdcdcdcdcdcdcdcULL, 0xdcdcdcdcdcdcdcdcULL, }, + { 0xc4c4c4c4c4c4c4c4ULL, 0xc4c4c4c4c4c4c4c4ULL, }, + { 0xc48ccdc48ccdc48cULL, 0xcdc48ccdc48ccdc4ULL, }, + { 0xdcce4cdcce4cdcceULL, 0x4cdcce4cdcce4cdcULL, }, + { 0xb3b3b3b3b3b3b3b3ULL, 0xb3b3b3b3b3b3b3b3ULL, }, /* 40 */ + { 0x3232323232323232ULL, 0x3232323232323232ULL, }, + { 0x3737373737373737ULL, 0x3737373737373737ULL, }, + { 0x1313131313131313ULL, 0x1313131313131313ULL, }, + { 0x2323232323232323ULL, 0x2323232323232323ULL, }, + { 0x3b3b3b3b3b3b3b3bULL, 0x3b3b3b3b3b3b3b3bULL, }, + { 0x3b73323b73323b73ULL, 0x323b73323b73323bULL, }, + { 0x2331b32331b32331ULL, 0xb32331b32331b323ULL, }, + { 0x630eb8630eb8630eULL, 0xb8630eb8630eb863ULL, }, /* 48 */ + { 0xe28f39e28f39e28fULL, 0x39e28f39e28f39e2ULL, }, + { 0xe78a3ce78a3ce78aULL, 0x3ce78a3ce78a3ce7ULL, }, + { 0xc3ae18c3ae18c3aeULL, 0x18c3ae18c3ae18c3ULL, }, + { 0xf39e28f39e28f39eULL, 0x28f39e28f39e28f3ULL, }, + { 0xeb8630eb8630eb86ULL, 0x30eb8630eb8630ebULL, }, + { 0xebce39ebce39ebceULL, 0x39ebce39ebce39ebULL, }, + { 0xf38cb8f38cb8f38cULL, 0xb8f38cb8f38cb8f3ULL, }, + { 0x9cf1479cf1479cf1ULL, 0x479cf1479cf1479cULL, }, /* 56 */ + { 0x1d70c61d70c61d70ULL, 0xc61d70c61d70c61dULL, }, + { 0x1875c31875c31875ULL, 0xc31875c31875c318ULL, }, + { 0x3c51e73c51e73c51ULL, 0xe73c51e73c51e73cULL, }, + { 0x0c61d70c61d70c61ULL, 0xd70c61d70c61d70cULL, }, + { 0x1479cf1479cf1479ULL, 0xcf1479cf1479cf14ULL, }, + { 0x1431c61431c61431ULL, 0xc61431c61431c614ULL, }, + { 0x0c73470c73470c73ULL, 0x470c73470c73470cULL, }, + { 0x896ea6dc29667541ULL, 0x43e7031ebe73b11cULL, }, /* 64 */ + { 0x802ae7c4086ad541ULL, 0x4fe7035adefbb41cULL, }, + { 0x986ea6c82ae25d41ULL, 0xcb664bdef673901cULL, }, + { 0x89eaa6ec68605100ULL, 0x6b650a5ffc7fb40dULL, }, + { 0xfaba40734c97e709ULL, 0x1a77b35a553753ecULL, }, + { 0xf3fe016b6d9b4709ULL, 0x1677b31e35bf56ecULL, }, + { 0xebba40674f13cf09ULL, 0x92f6fb9a1d3772ecULL, }, + { 0xfa3e40430d91c348ULL, 0x32f5ba1b173b56fdULL, }, + { 0xad5eeebab8cbab81ULL, 0x2f58cebfeb232404ULL, }, /* 72 */ + { 0xa41aafa299c70b81ULL, 0x2358cefb8bab2104ULL, }, + { 0xbc5eeeaebb4f8381ULL, 0xa7d9867fa3230504ULL, }, + { 0xaddaee8af9cd8fc0ULL, 0x07dac7fea92f2115ULL, }, + { 0x714b565d5f35c24fULL, 0x85718098e94ae3b0ULL, }, + { 0x780f17457e39624fULL, 0x897180dc89c2e6b0ULL, }, + { 0x604b56495cb1ea4fULL, 0x0df0c858a14ac2b0ULL, }, + { 0x71cf566d1e33e60eULL, 0xadf389d9ab46e6a1ULL, }, + }; + + reset_msa_registers(); + + gettimeofday(&start, NULL); + + for (i = 0; i < PATTERN_INPUTS_SHORT_COUNT; i++) { + for (j = 0; j < PATTERN_INPUTS_SHORT_COUNT; j++) { + do_msa_BNEG_B(b128_pattern[i], b128_pattern[j], + b128_result[PATTERN_INPUTS_SHORT_COUNT * i + j]); + } + } + + for (i = 0; i < RANDOM_INPUTS_SHORT_COUNT; i++) { + for (j = 0; j < RANDOM_INPUTS_SHORT_COUNT; j++) { + do_msa_BNEG_B(b128_random[i], b128_random[j], + b128_result[((PATTERN_INPUTS_SHORT_COUNT) * + (PATTERN_INPUTS_SHORT_COUNT)) + + RANDOM_INPUTS_SHORT_COUNT * i + j]); + } + } + + gettimeofday(&end, NULL); + + elapsed_time = (end.tv_sec - start.tv_sec) * 1000.0; + elapsed_time += (end.tv_usec - start.tv_usec) / 1000.0; + + ret = check_results(instruction_name, TEST_COUNT_TOTAL, elapsed_time, + &b128_result[0][0], &b128_expect[0][0]); + + return ret; +} diff --git a/tests/tcg/mips/user/ase/msa/bit-set/test_msa_bneg_d.c b/tests/tcg/mips/user/ase/msa/bit-set/test_msa_bneg_d.c new file mode 100644 index 0000000000..fc092215d5 --- /dev/null +++ b/tests/tcg/mips/user/ase/msa/bit-set/test_msa_bneg_d.c @@ -0,0 +1,155 @@ +/* + * Test program for MSA instruction BNEG.D + * + * Copyright (C) 2019 Wave Computing, Inc. + * Copyright (C) 2019 Aleksandar Markovic <amarkovic@wavecomp.com> + * + * This program 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, see <https://www.gnu.org/licenses/>. + * + */ + +#include <sys/time.h> +#include <stdint.h> + +#include "../../../../include/wrappers_msa.h" +#include "../../../../include/test_inputs_128.h" +#include "../../../../include/test_utils_128.h" + +#define TEST_COUNT_TOTAL ( \ + (PATTERN_INPUTS_SHORT_COUNT) * (PATTERN_INPUTS_SHORT_COUNT) + \ + (RANDOM_INPUTS_SHORT_COUNT) * (RANDOM_INPUTS_SHORT_COUNT)) + + +int32_t main(void) +{ + char *instruction_name = "BNEG.D"; + int32_t ret; + uint32_t i, j; + struct timeval start, end; + double elapsed_time; + + uint64_t b128_result[TEST_COUNT_TOTAL][2]; + uint64_t b128_expect[TEST_COUNT_TOTAL][2] = { + { 0x7fffffffffffffffULL, 0x7fffffffffffffffULL, }, /* 0 */ + { 0xfffffffffffffffeULL, 0xfffffffffffffffeULL, }, + { 0xfffffbffffffffffULL, 0xfffffbffffffffffULL, }, + { 0xffffffffffdfffffULL, 0xffffffffffdfffffULL, }, + { 0xffffffffffffefffULL, 0xffffffffffffefffULL, }, + { 0xfff7ffffffffffffULL, 0xfff7ffffffffffffULL, }, + { 0xffffffffffffbfffULL, 0xfffffff7ffffffffULL, }, + { 0xfffdffffffffffffULL, 0xffffffffefffffffULL, }, + { 0x8000000000000000ULL, 0x8000000000000000ULL, }, /* 8 */ + { 0x0000000000000001ULL, 0x0000000000000001ULL, }, + { 0x0000040000000000ULL, 0x0000040000000000ULL, }, + { 0x0000000000200000ULL, 0x0000000000200000ULL, }, + { 0x0000000000001000ULL, 0x0000000000001000ULL, }, + { 0x0008000000000000ULL, 0x0008000000000000ULL, }, + { 0x0000000000004000ULL, 0x0000000800000000ULL, }, + { 0x0002000000000000ULL, 0x0000000010000000ULL, }, + { 0x2aaaaaaaaaaaaaaaULL, 0x2aaaaaaaaaaaaaaaULL, }, /* 16 */ + { 0xaaaaaaaaaaaaaaabULL, 0xaaaaaaaaaaaaaaabULL, }, + { 0xaaaaaeaaaaaaaaaaULL, 0xaaaaaeaaaaaaaaaaULL, }, + { 0xaaaaaaaaaa8aaaaaULL, 0xaaaaaaaaaa8aaaaaULL, }, + { 0xaaaaaaaaaaaabaaaULL, 0xaaaaaaaaaaaabaaaULL, }, + { 0xaaa2aaaaaaaaaaaaULL, 0xaaa2aaaaaaaaaaaaULL, }, + { 0xaaaaaaaaaaaaeaaaULL, 0xaaaaaaa2aaaaaaaaULL, }, + { 0xaaa8aaaaaaaaaaaaULL, 0xaaaaaaaabaaaaaaaULL, }, + { 0xd555555555555555ULL, 0xd555555555555555ULL, }, /* 24 */ + { 0x5555555555555554ULL, 0x5555555555555554ULL, }, + { 0x5555515555555555ULL, 0x5555515555555555ULL, }, + { 0x5555555555755555ULL, 0x5555555555755555ULL, }, + { 0x5555555555554555ULL, 0x5555555555554555ULL, }, + { 0x555d555555555555ULL, 0x555d555555555555ULL, }, + { 0x5555555555551555ULL, 0x5555555d55555555ULL, }, + { 0x5557555555555555ULL, 0x5555555545555555ULL, }, + { 0x4cccccccccccccccULL, 0x4cccccccccccccccULL, }, /* 32 */ + { 0xcccccccccccccccdULL, 0xcccccccccccccccdULL, }, + { 0xccccc8ccccccccccULL, 0xccccc8ccccccccccULL, }, + { 0xccccccccccecccccULL, 0xccccccccccecccccULL, }, + { 0xccccccccccccdcccULL, 0xccccccccccccdcccULL, }, + { 0xccc4ccccccccccccULL, 0xccc4ccccccccccccULL, }, + { 0xcccccccccccc8cccULL, 0xccccccc4ccccccccULL, }, + { 0xccceccccccccccccULL, 0xccccccccdcccccccULL, }, + { 0xb333333333333333ULL, 0xb333333333333333ULL, }, /* 40 */ + { 0x3333333333333332ULL, 0x3333333333333332ULL, }, + { 0x3333373333333333ULL, 0x3333373333333333ULL, }, + { 0x3333333333133333ULL, 0x3333333333133333ULL, }, + { 0x3333333333332333ULL, 0x3333333333332333ULL, }, + { 0x333b333333333333ULL, 0x333b333333333333ULL, }, + { 0x3333333333337333ULL, 0x3333333b33333333ULL, }, + { 0x3331333333333333ULL, 0x3333333323333333ULL, }, + { 0x638e38e38e38e38eULL, 0xb8e38e38e38e38e3ULL, }, /* 48 */ + { 0xe38e38e38e38e38fULL, 0x38e38e38e38e38e2ULL, }, + { 0xe38e3ce38e38e38eULL, 0x38e38a38e38e38e3ULL, }, + { 0xe38e38e38e18e38eULL, 0x38e38e38e3ae38e3ULL, }, + { 0xe38e38e38e38f38eULL, 0x38e38e38e38e28e3ULL, }, + { 0xe38638e38e38e38eULL, 0x38eb8e38e38e38e3ULL, }, + { 0xe38e38e38e38a38eULL, 0x38e38e30e38e38e3ULL, }, + { 0xe38c38e38e38e38eULL, 0x38e38e38f38e38e3ULL, }, + { 0x9c71c71c71c71c71ULL, 0x471c71c71c71c71cULL, }, /* 56 */ + { 0x1c71c71c71c71c70ULL, 0xc71c71c71c71c71dULL, }, + { 0x1c71c31c71c71c71ULL, 0xc71c75c71c71c71cULL, }, + { 0x1c71c71c71e71c71ULL, 0xc71c71c71c51c71cULL, }, + { 0x1c71c71c71c70c71ULL, 0xc71c71c71c71d71cULL, }, + { 0x1c79c71c71c71c71ULL, 0xc71471c71c71c71cULL, }, + { 0x1c71c71c71c75c71ULL, 0xc71c71cf1c71c71cULL, }, + { 0x1c73c71c71c71c71ULL, 0xc71c71c70c71c71cULL, }, + { 0x886ae6cc28625541ULL, 0x4b670b5efe7ba00cULL, }, /* 64 */ + { 0x886ae6cc28625440ULL, 0x5b670b5efe7bb00cULL, }, + { 0x886ae6cc28625541ULL, 0x4b670b5efe6bb00cULL, }, + { 0x886ae6cc28621540ULL, 0x4b670b5ffe7bb00cULL, }, + { 0xfbbe00634d93c709ULL, 0x12f7bb1a153f42fcULL, }, + { 0xfbbe00634d93c608ULL, 0x02f7bb1a153f52fcULL, }, + { 0xfbbe00634d93c709ULL, 0x12f7bb1a152f52fcULL, }, + { 0xfbbe00634d938708ULL, 0x12f7bb1b153f52fcULL, }, + { 0xac5aaeaab9cf8b81ULL, 0x27d8c6ffab2b3514ULL, }, /* 72 */ + { 0xac5aaeaab9cf8a80ULL, 0x37d8c6ffab2b2514ULL, }, + { 0xac5aaeaab9cf8b81ULL, 0x27d8c6ffab3b2514ULL, }, + { 0xac5aaeaab9cfcb80ULL, 0x27d8c6feab2b2514ULL, }, + { 0x704f164d5e31e24fULL, 0x8df188d8a942f2a0ULL, }, + { 0x704f164d5e31e34eULL, 0x9df188d8a942e2a0ULL, }, + { 0x704f164d5e31e24fULL, 0x8df188d8a952e2a0ULL, }, + { 0x704f164d5e31a24eULL, 0x8df188d9a942e2a0ULL, }, + }; + + reset_msa_registers(); + + gettimeofday(&start, NULL); + + for (i = 0; i < PATTERN_INPUTS_SHORT_COUNT; i++) { + for (j = 0; j < PATTERN_INPUTS_SHORT_COUNT; j++) { + do_msa_BNEG_D(b128_pattern[i], b128_pattern[j], + b128_result[PATTERN_INPUTS_SHORT_COUNT * i + j]); + } + } + + for (i = 0; i < RANDOM_INPUTS_SHORT_COUNT; i++) { + for (j = 0; j < RANDOM_INPUTS_SHORT_COUNT; j++) { + do_msa_BNEG_D(b128_random[i], b128_random[j], + b128_result[((PATTERN_INPUTS_SHORT_COUNT) * + (PATTERN_INPUTS_SHORT_COUNT)) + + RANDOM_INPUTS_SHORT_COUNT * i + j]); + } + } + + gettimeofday(&end, NULL); + + elapsed_time = (end.tv_sec - start.tv_sec) * 1000.0; + elapsed_time += (end.tv_usec - start.tv_usec) / 1000.0; + + ret = check_results(instruction_name, TEST_COUNT_TOTAL, elapsed_time, + &b128_result[0][0], &b128_expect[0][0]); + + return ret; +} diff --git a/tests/tcg/mips/user/ase/msa/bit-set/test_msa_bneg_h.c b/tests/tcg/mips/user/ase/msa/bit-set/test_msa_bneg_h.c new file mode 100644 index 0000000000..d8347a1884 --- /dev/null +++ b/tests/tcg/mips/user/ase/msa/bit-set/test_msa_bneg_h.c @@ -0,0 +1,155 @@ +/* + * Test program for MSA instruction BNEG.H + * + * Copyright (C) 2019 Wave Computing, Inc. + * Copyright (C) 2019 Aleksandar Markovic <amarkovic@wavecomp.com> + * + * This program 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, see <https://www.gnu.org/licenses/>. + * + */ + +#include <sys/time.h> +#include <stdint.h> + +#include "../../../../include/wrappers_msa.h" +#include "../../../../include/test_inputs_128.h" +#include "../../../../include/test_utils_128.h" + +#define TEST_COUNT_TOTAL ( \ + (PATTERN_INPUTS_SHORT_COUNT) * (PATTERN_INPUTS_SHORT_COUNT) + \ + (RANDOM_INPUTS_SHORT_COUNT) * (RANDOM_INPUTS_SHORT_COUNT)) + + +int32_t main(void) +{ + char *instruction_name = "BNEG.H"; + int32_t ret; + uint32_t i, j; + struct timeval start, end; + double elapsed_time; + + uint64_t b128_result[TEST_COUNT_TOTAL][2]; + uint64_t b128_expect[TEST_COUNT_TOTAL][2] = { + { 0x7fff7fff7fff7fffULL, 0x7fff7fff7fff7fffULL, }, /* 0 */ + { 0xfffefffefffefffeULL, 0xfffefffefffefffeULL, }, + { 0xfbfffbfffbfffbffULL, 0xfbfffbfffbfffbffULL, }, + { 0xffdfffdfffdfffdfULL, 0xffdfffdfffdfffdfULL, }, + { 0xefffefffefffefffULL, 0xefffefffefffefffULL, }, + { 0xfff7fff7fff7fff7ULL, 0xfff7fff7fff7fff7ULL, }, + { 0xbffffff7feffbfffULL, 0xfff7feffbffffff7ULL, }, + { 0xfffdefffff7ffffdULL, 0xefffff7ffffdefffULL, }, + { 0x8000800080008000ULL, 0x8000800080008000ULL, }, /* 8 */ + { 0x0001000100010001ULL, 0x0001000100010001ULL, }, + { 0x0400040004000400ULL, 0x0400040004000400ULL, }, + { 0x0020002000200020ULL, 0x0020002000200020ULL, }, + { 0x1000100010001000ULL, 0x1000100010001000ULL, }, + { 0x0008000800080008ULL, 0x0008000800080008ULL, }, + { 0x4000000801004000ULL, 0x0008010040000008ULL, }, + { 0x0002100000800002ULL, 0x1000008000021000ULL, }, + { 0x2aaa2aaa2aaa2aaaULL, 0x2aaa2aaa2aaa2aaaULL, }, /* 16 */ + { 0xaaabaaabaaabaaabULL, 0xaaabaaabaaabaaabULL, }, + { 0xaeaaaeaaaeaaaeaaULL, 0xaeaaaeaaaeaaaeaaULL, }, + { 0xaa8aaa8aaa8aaa8aULL, 0xaa8aaa8aaa8aaa8aULL, }, + { 0xbaaabaaabaaabaaaULL, 0xbaaabaaabaaabaaaULL, }, + { 0xaaa2aaa2aaa2aaa2ULL, 0xaaa2aaa2aaa2aaa2ULL, }, + { 0xeaaaaaa2abaaeaaaULL, 0xaaa2abaaeaaaaaa2ULL, }, + { 0xaaa8baaaaa2aaaa8ULL, 0xbaaaaa2aaaa8baaaULL, }, + { 0xd555d555d555d555ULL, 0xd555d555d555d555ULL, }, /* 24 */ + { 0x5554555455545554ULL, 0x5554555455545554ULL, }, + { 0x5155515551555155ULL, 0x5155515551555155ULL, }, + { 0x5575557555755575ULL, 0x5575557555755575ULL, }, + { 0x4555455545554555ULL, 0x4555455545554555ULL, }, + { 0x555d555d555d555dULL, 0x555d555d555d555dULL, }, + { 0x1555555d54551555ULL, 0x555d54551555555dULL, }, + { 0x5557455555d55557ULL, 0x455555d555574555ULL, }, + { 0x4ccc4ccc4ccc4cccULL, 0x4ccc4ccc4ccc4cccULL, }, /* 32 */ + { 0xcccdcccdcccdcccdULL, 0xcccdcccdcccdcccdULL, }, + { 0xc8ccc8ccc8ccc8ccULL, 0xc8ccc8ccc8ccc8ccULL, }, + { 0xccecccecccecccecULL, 0xccecccecccecccecULL, }, + { 0xdcccdcccdcccdcccULL, 0xdcccdcccdcccdcccULL, }, + { 0xccc4ccc4ccc4ccc4ULL, 0xccc4ccc4ccc4ccc4ULL, }, + { 0x8cccccc4cdcc8cccULL, 0xccc4cdcc8cccccc4ULL, }, + { 0xcccedccccc4cccceULL, 0xdccccc4ccccedcccULL, }, + { 0xb333b333b333b333ULL, 0xb333b333b333b333ULL, }, /* 40 */ + { 0x3332333233323332ULL, 0x3332333233323332ULL, }, + { 0x3733373337333733ULL, 0x3733373337333733ULL, }, + { 0x3313331333133313ULL, 0x3313331333133313ULL, }, + { 0x2333233323332333ULL, 0x2333233323332333ULL, }, + { 0x333b333b333b333bULL, 0x333b333b333b333bULL, }, + { 0x7333333b32337333ULL, 0x333b32337333333bULL, }, + { 0x3331233333b33331ULL, 0x233333b333312333ULL, }, + { 0x638eb8e30e38638eULL, 0xb8e30e38638eb8e3ULL, }, /* 48 */ + { 0xe38f38e28e39e38fULL, 0x38e28e39e38f38e2ULL, }, + { 0xe78e3ce38a38e78eULL, 0x3ce38a38e78e3ce3ULL, }, + { 0xe3ae38c38e18e3aeULL, 0x38c38e18e3ae38c3ULL, }, + { 0xf38e28e39e38f38eULL, 0x28e39e38f38e28e3ULL, }, + { 0xe38638eb8e30e386ULL, 0x38eb8e30e38638ebULL, }, + { 0xa38e38eb8f38a38eULL, 0x38eb8f38a38e38ebULL, }, + { 0xe38c28e38eb8e38cULL, 0x28e38eb8e38c28e3ULL, }, + { 0x9c71471cf1c79c71ULL, 0x471cf1c79c71471cULL, }, /* 56 */ + { 0x1c70c71d71c61c70ULL, 0xc71d71c61c70c71dULL, }, + { 0x1871c31c75c71871ULL, 0xc31c75c71871c31cULL, }, + { 0x1c51c73c71e71c51ULL, 0xc73c71e71c51c73cULL, }, + { 0x0c71d71c61c70c71ULL, 0xd71c61c70c71d71cULL, }, + { 0x1c79c71471cf1c79ULL, 0xc71471cf1c79c714ULL, }, + { 0x5c71c71470c75c71ULL, 0xc71470c75c71c714ULL, }, + { 0x1c73d71c71471c73ULL, 0xd71c71471c73d71cULL, }, + { 0x8c6af6cc28665541ULL, 0x4be74b5ef67ba00cULL, }, /* 64 */ + { 0xc86ae6c4286a5440ULL, 0x4be70f5e7e7ba00cULL, }, + { 0x8c6ae2cca8625541ULL, 0x4a678b5ef67bb01cULL, }, + { 0x086ac6cc28601540ULL, 0x4b650a5efe7fb00dULL, }, + { 0xffbe10634d97c709ULL, 0x1277fb1a1d3f42fcULL, }, + { 0xbbbe006b4d9bc608ULL, 0x1277bf1a953f42fcULL, }, + { 0xffbe0463cd93c709ULL, 0x13f73b1a1d3f52ecULL, }, + { 0x7bbe20634d918708ULL, 0x12f5ba1a153b52fdULL, }, + { 0xa85abeaab9cb8b81ULL, 0x275886ffa32b3514ULL, }, /* 72 */ + { 0xec5aaea2b9c78a80ULL, 0x2758c2ff2b2b3514ULL, }, + { 0xa85aaaaa39cf8b81ULL, 0x26d846ffa32b2504ULL, }, + { 0x2c5a8eaab9cdcb80ULL, 0x27dac7ffab2f2515ULL, }, + { 0x744f064d5e35e24fULL, 0x8d71c8d8a142f2a0ULL, }, + { 0x304f16455e39e34eULL, 0x8d718cd82942f2a0ULL, }, + { 0x744f124dde31e24fULL, 0x8cf108d8a142e2b0ULL, }, + { 0xf04f364d5e33a24eULL, 0x8df389d8a946e2a1ULL, }, + }; + + reset_msa_registers(); + + gettimeofday(&start, NULL); + + for (i = 0; i < PATTERN_INPUTS_SHORT_COUNT; i++) { + for (j = 0; j < PATTERN_INPUTS_SHORT_COUNT; j++) { + do_msa_BNEG_H(b128_pattern[i], b128_pattern[j], + b128_result[PATTERN_INPUTS_SHORT_COUNT * i + j]); + } + } + + for (i = 0; i < RANDOM_INPUTS_SHORT_COUNT; i++) { + for (j = 0; j < RANDOM_INPUTS_SHORT_COUNT; j++) { + do_msa_BNEG_H(b128_random[i], b128_random[j], + b128_result[((PATTERN_INPUTS_SHORT_COUNT) * + (PATTERN_INPUTS_SHORT_COUNT)) + + RANDOM_INPUTS_SHORT_COUNT * i + j]); + } + } + + gettimeofday(&end, NULL); + + elapsed_time = (end.tv_sec - start.tv_sec) * 1000.0; + elapsed_time += (end.tv_usec - start.tv_usec) / 1000.0; + + ret = check_results(instruction_name, TEST_COUNT_TOTAL, elapsed_time, + &b128_result[0][0], &b128_expect[0][0]); + + return ret; +} diff --git a/tests/tcg/mips/user/ase/msa/bit-set/test_msa_bneg_w.c b/tests/tcg/mips/user/ase/msa/bit-set/test_msa_bneg_w.c new file mode 100644 index 0000000000..36ef43672f --- /dev/null +++ b/tests/tcg/mips/user/ase/msa/bit-set/test_msa_bneg_w.c @@ -0,0 +1,155 @@ +/* + * Test program for MSA instruction BNEG.W + * + * Copyright (C) 2019 Wave Computing, Inc. + * Copyright (C) 2019 Aleksandar Markovic <amarkovic@wavecomp.com> + * + * This program 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, see <https://www.gnu.org/licenses/>. + * + */ + +#include <sys/time.h> +#include <stdint.h> + +#include "../../../../include/wrappers_msa.h" +#include "../../../../include/test_inputs_128.h" +#include "../../../../include/test_utils_128.h" + +#define TEST_COUNT_TOTAL ( \ + (PATTERN_INPUTS_SHORT_COUNT) * (PATTERN_INPUTS_SHORT_COUNT) + \ + (RANDOM_INPUTS_SHORT_COUNT) * (RANDOM_INPUTS_SHORT_COUNT)) + + +int32_t main(void) +{ + char *instruction_name = "BNEG.W"; + int32_t ret; + uint32_t i, j; + struct timeval start, end; + double elapsed_time; + + uint64_t b128_result[TEST_COUNT_TOTAL][2]; + uint64_t b128_expect[TEST_COUNT_TOTAL][2] = { + { 0x7fffffff7fffffffULL, 0x7fffffff7fffffffULL, }, /* 0 */ + { 0xfffffffefffffffeULL, 0xfffffffefffffffeULL, }, + { 0xfffffbfffffffbffULL, 0xfffffbfffffffbffULL, }, + { 0xffdfffffffdfffffULL, 0xffdfffffffdfffffULL, }, + { 0xffffefffffffefffULL, 0xffffefffffffefffULL, }, + { 0xfff7fffffff7ffffULL, 0xfff7fffffff7ffffULL, }, + { 0xfffffff7ffffbfffULL, 0xfefffffffffffff7ULL, }, + { 0xeffffffffffdffffULL, 0xffffff7fefffffffULL, }, + { 0x8000000080000000ULL, 0x8000000080000000ULL, }, /* 8 */ + { 0x0000000100000001ULL, 0x0000000100000001ULL, }, + { 0x0000040000000400ULL, 0x0000040000000400ULL, }, + { 0x0020000000200000ULL, 0x0020000000200000ULL, }, + { 0x0000100000001000ULL, 0x0000100000001000ULL, }, + { 0x0008000000080000ULL, 0x0008000000080000ULL, }, + { 0x0000000800004000ULL, 0x0100000000000008ULL, }, + { 0x1000000000020000ULL, 0x0000008010000000ULL, }, + { 0x2aaaaaaa2aaaaaaaULL, 0x2aaaaaaa2aaaaaaaULL, }, /* 16 */ + { 0xaaaaaaabaaaaaaabULL, 0xaaaaaaabaaaaaaabULL, }, + { 0xaaaaaeaaaaaaaeaaULL, 0xaaaaaeaaaaaaaeaaULL, }, + { 0xaa8aaaaaaa8aaaaaULL, 0xaa8aaaaaaa8aaaaaULL, }, + { 0xaaaabaaaaaaabaaaULL, 0xaaaabaaaaaaabaaaULL, }, + { 0xaaa2aaaaaaa2aaaaULL, 0xaaa2aaaaaaa2aaaaULL, }, + { 0xaaaaaaa2aaaaeaaaULL, 0xabaaaaaaaaaaaaa2ULL, }, + { 0xbaaaaaaaaaa8aaaaULL, 0xaaaaaa2abaaaaaaaULL, }, + { 0xd5555555d5555555ULL, 0xd5555555d5555555ULL, }, /* 24 */ + { 0x5555555455555554ULL, 0x5555555455555554ULL, }, + { 0x5555515555555155ULL, 0x5555515555555155ULL, }, + { 0x5575555555755555ULL, 0x5575555555755555ULL, }, + { 0x5555455555554555ULL, 0x5555455555554555ULL, }, + { 0x555d5555555d5555ULL, 0x555d5555555d5555ULL, }, + { 0x5555555d55551555ULL, 0x545555555555555dULL, }, + { 0x4555555555575555ULL, 0x555555d545555555ULL, }, + { 0x4ccccccc4cccccccULL, 0x4ccccccc4cccccccULL, }, /* 32 */ + { 0xcccccccdcccccccdULL, 0xcccccccdcccccccdULL, }, + { 0xccccc8ccccccc8ccULL, 0xccccc8ccccccc8ccULL, }, + { 0xccecccccccecccccULL, 0xccecccccccecccccULL, }, + { 0xccccdcccccccdcccULL, 0xccccdcccccccdcccULL, }, + { 0xccc4ccccccc4ccccULL, 0xccc4ccccccc4ccccULL, }, + { 0xccccccc4cccc8cccULL, 0xcdccccccccccccc4ULL, }, + { 0xdcccccccccceccccULL, 0xcccccc4cdcccccccULL, }, + { 0xb3333333b3333333ULL, 0xb3333333b3333333ULL, }, /* 40 */ + { 0x3333333233333332ULL, 0x3333333233333332ULL, }, + { 0x3333373333333733ULL, 0x3333373333333733ULL, }, + { 0x3313333333133333ULL, 0x3313333333133333ULL, }, + { 0x3333233333332333ULL, 0x3333233333332333ULL, }, + { 0x333b3333333b3333ULL, 0x333b3333333b3333ULL, }, + { 0x3333333b33337333ULL, 0x323333333333333bULL, }, + { 0x2333333333313333ULL, 0x333333b323333333ULL, }, + { 0x638e38e30e38e38eULL, 0xb8e38e38638e38e3ULL, }, /* 48 */ + { 0xe38e38e28e38e38fULL, 0x38e38e39e38e38e2ULL, }, + { 0xe38e3ce38e38e78eULL, 0x38e38a38e38e3ce3ULL, }, + { 0xe3ae38e38e18e38eULL, 0x38c38e38e3ae38e3ULL, }, + { 0xe38e28e38e38f38eULL, 0x38e39e38e38e28e3ULL, }, + { 0xe38638e38e30e38eULL, 0x38eb8e38e38638e3ULL, }, + { 0xe38e38eb8e38a38eULL, 0x39e38e38e38e38ebULL, }, + { 0xf38e38e38e3ae38eULL, 0x38e38eb8f38e38e3ULL, }, + { 0x9c71c71cf1c71c71ULL, 0x471c71c79c71c71cULL, }, /* 56 */ + { 0x1c71c71d71c71c70ULL, 0xc71c71c61c71c71dULL, }, + { 0x1c71c31c71c71871ULL, 0xc71c75c71c71c31cULL, }, + { 0x1c51c71c71e71c71ULL, 0xc73c71c71c51c71cULL, }, + { 0x1c71d71c71c70c71ULL, 0xc71c61c71c71d71cULL, }, + { 0x1c79c71c71cf1c71ULL, 0xc71471c71c79c71cULL, }, + { 0x1c71c71471c75c71ULL, 0xc61c71c71c71c714ULL, }, + { 0x0c71c71c71c51c71ULL, 0xc71c71470c71c71cULL, }, + { 0x886af6cc28625541ULL, 0x0b670b5efe7ba00cULL, }, /* 64 */ + { 0x886ae6c428625440ULL, 0x4f670b5eee7bb00cULL, }, + { 0x886ae2cc28625541ULL, 0xcb670b5efe6bb00cULL, }, + { 0x886ac6cc28621540ULL, 0x4a670b5efe7bb00dULL, }, + { 0xfbbe10634d93c709ULL, 0x52f7bb1a153f42fcULL, }, + { 0xfbbe006b4d93c608ULL, 0x16f7bb1a053f52fcULL, }, + { 0xfbbe04634d93c709ULL, 0x92f7bb1a152f52fcULL, }, + { 0xfbbe20634d938708ULL, 0x13f7bb1a153f52fdULL, }, + { 0xac5abeaab9cf8b81ULL, 0x67d8c6ffab2b3514ULL, }, /* 72 */ + { 0xac5aaea2b9cf8a80ULL, 0x23d8c6ffbb2b2514ULL, }, + { 0xac5aaaaab9cf8b81ULL, 0xa7d8c6ffab3b2514ULL, }, + { 0xac5a8eaab9cfcb80ULL, 0x26d8c6ffab2b2515ULL, }, + { 0x704f064d5e31e24fULL, 0xcdf188d8a942f2a0ULL, }, + { 0x704f16455e31e34eULL, 0x89f188d8b942e2a0ULL, }, + { 0x704f124d5e31e24fULL, 0x0df188d8a952e2a0ULL, }, + { 0x704f364d5e31a24eULL, 0x8cf188d8a942e2a1ULL, }, + }; + + reset_msa_registers(); + + gettimeofday(&start, NULL); + + for (i = 0; i < PATTERN_INPUTS_SHORT_COUNT; i++) { + for (j = 0; j < PATTERN_INPUTS_SHORT_COUNT; j++) { + do_msa_BNEG_W(b128_pattern[i], b128_pattern[j], + b128_result[PATTERN_INPUTS_SHORT_COUNT * i + j]); + } + } + + for (i = 0; i < RANDOM_INPUTS_SHORT_COUNT; i++) { + for (j = 0; j < RANDOM_INPUTS_SHORT_COUNT; j++) { + do_msa_BNEG_W(b128_random[i], b128_random[j], + b128_result[((PATTERN_INPUTS_SHORT_COUNT) * + (PATTERN_INPUTS_SHORT_COUNT)) + + RANDOM_INPUTS_SHORT_COUNT * i + j]); + } + } + + gettimeofday(&end, NULL); + + elapsed_time = (end.tv_sec - start.tv_sec) * 1000.0; + elapsed_time += (end.tv_usec - start.tv_usec) / 1000.0; + + ret = check_results(instruction_name, TEST_COUNT_TOTAL, elapsed_time, + &b128_result[0][0], &b128_expect[0][0]); + + return ret; +} diff --git a/tests/tcg/mips/user/ase/msa/bit-set/test_msa_bset_b.c b/tests/tcg/mips/user/ase/msa/bit-set/test_msa_bset_b.c new file mode 100644 index 0000000000..f6907cb3d3 --- /dev/null +++ b/tests/tcg/mips/user/ase/msa/bit-set/test_msa_bset_b.c @@ -0,0 +1,155 @@ +/* + * Test program for MSA instruction BSET.B + * + * Copyright (C) 2019 Wave Computing, Inc. + * Copyright (C) 2019 Aleksandar Markovic <amarkovic@wavecomp.com> + * + * This program 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, see <https://www.gnu.org/licenses/>. + * + */ + +#include <sys/time.h> +#include <stdint.h> + +#include "../../../../include/wrappers_msa.h" +#include "../../../../include/test_inputs_128.h" +#include "../../../../include/test_utils_128.h" + +#define TEST_COUNT_TOTAL ( \ + (PATTERN_INPUTS_SHORT_COUNT) * (PATTERN_INPUTS_SHORT_COUNT) + \ + (RANDOM_INPUTS_SHORT_COUNT) * (RANDOM_INPUTS_SHORT_COUNT)) + + +int32_t main(void) +{ + char *instruction_name = "BSET.B"; + int32_t ret; + uint32_t i, j; + struct timeval start, end; + double elapsed_time; + + uint64_t b128_result[TEST_COUNT_TOTAL][2]; + uint64_t b128_expect[TEST_COUNT_TOTAL][2] = { + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 0 */ + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, + { 0x8080808080808080ULL, 0x8080808080808080ULL, }, /* 8 */ + { 0x0101010101010101ULL, 0x0101010101010101ULL, }, + { 0x0404040404040404ULL, 0x0404040404040404ULL, }, + { 0x2020202020202020ULL, 0x2020202020202020ULL, }, + { 0x1010101010101010ULL, 0x1010101010101010ULL, }, + { 0x0808080808080808ULL, 0x0808080808080808ULL, }, + { 0x0840010840010840ULL, 0x0108400108400108ULL, }, + { 0x1002801002801002ULL, 0x8010028010028010ULL, }, + { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, }, /* 16 */ + { 0xababababababababULL, 0xababababababababULL, }, + { 0xaeaeaeaeaeaeaeaeULL, 0xaeaeaeaeaeaeaeaeULL, }, + { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, }, + { 0xbabababababababaULL, 0xbabababababababaULL, }, + { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, }, + { 0xaaeaabaaeaabaaeaULL, 0xabaaeaabaaeaabaaULL, }, + { 0xbaaaaabaaaaabaaaULL, 0xaabaaaaabaaaaabaULL, }, + { 0xd5d5d5d5d5d5d5d5ULL, 0xd5d5d5d5d5d5d5d5ULL, }, /* 24 */ + { 0x5555555555555555ULL, 0x5555555555555555ULL, }, + { 0x5555555555555555ULL, 0x5555555555555555ULL, }, + { 0x7575757575757575ULL, 0x7575757575757575ULL, }, + { 0x5555555555555555ULL, 0x5555555555555555ULL, }, + { 0x5d5d5d5d5d5d5d5dULL, 0x5d5d5d5d5d5d5d5dULL, }, + { 0x5d55555d55555d55ULL, 0x555d55555d55555dULL, }, + { 0x5557d55557d55557ULL, 0xd55557d55557d555ULL, }, + { 0xccccccccccccccccULL, 0xccccccccccccccccULL, }, /* 32 */ + { 0xcdcdcdcdcdcdcdcdULL, 0xcdcdcdcdcdcdcdcdULL, }, + { 0xccccccccccccccccULL, 0xccccccccccccccccULL, }, + { 0xececececececececULL, 0xececececececececULL, }, + { 0xdcdcdcdcdcdcdcdcULL, 0xdcdcdcdcdcdcdcdcULL, }, + { 0xccccccccccccccccULL, 0xccccccccccccccccULL, }, + { 0xcccccdcccccdccccULL, 0xcdcccccdcccccdccULL, }, + { 0xdcceccdcceccdcceULL, 0xccdcceccdcceccdcULL, }, + { 0xb3b3b3b3b3b3b3b3ULL, 0xb3b3b3b3b3b3b3b3ULL, }, /* 40 */ + { 0x3333333333333333ULL, 0x3333333333333333ULL, }, + { 0x3737373737373737ULL, 0x3737373737373737ULL, }, + { 0x3333333333333333ULL, 0x3333333333333333ULL, }, + { 0x3333333333333333ULL, 0x3333333333333333ULL, }, + { 0x3b3b3b3b3b3b3b3bULL, 0x3b3b3b3b3b3b3b3bULL, }, + { 0x3b73333b73333b73ULL, 0x333b73333b73333bULL, }, + { 0x3333b33333b33333ULL, 0xb33333b33333b333ULL, }, + { 0xe38eb8e38eb8e38eULL, 0xb8e38eb8e38eb8e3ULL, }, /* 48 */ + { 0xe38f39e38f39e38fULL, 0x39e38f39e38f39e3ULL, }, + { 0xe78e3ce78e3ce78eULL, 0x3ce78e3ce78e3ce7ULL, }, + { 0xe3ae38e3ae38e3aeULL, 0x38e3ae38e3ae38e3ULL, }, + { 0xf39e38f39e38f39eULL, 0x38f39e38f39e38f3ULL, }, + { 0xeb8e38eb8e38eb8eULL, 0x38eb8e38eb8e38ebULL, }, + { 0xebce39ebce39ebceULL, 0x39ebce39ebce39ebULL, }, + { 0xf38eb8f38eb8f38eULL, 0xb8f38eb8f38eb8f3ULL, }, + { 0x9cf1c79cf1c79cf1ULL, 0xc79cf1c79cf1c79cULL, }, /* 56 */ + { 0x1d71c71d71c71d71ULL, 0xc71d71c71d71c71dULL, }, + { 0x1c75c71c75c71c75ULL, 0xc71c75c71c75c71cULL, }, + { 0x3c71e73c71e73c71ULL, 0xe73c71e73c71e73cULL, }, + { 0x1c71d71c71d71c71ULL, 0xd71c71d71c71d71cULL, }, + { 0x1c79cf1c79cf1c79ULL, 0xcf1c79cf1c79cf1cULL, }, + { 0x1c71c71c71c71c71ULL, 0xc71c71c71c71c71cULL, }, + { 0x1c73c71c73c71c73ULL, 0xc71c73c71c73c71cULL, }, + { 0x896ee6dc29667541ULL, 0x4be70b5efe7bb11cULL, }, /* 64 */ + { 0x886ae7cc286ad541ULL, 0x4fe70b5efefbb41cULL, }, + { 0x986ee6cc2ae25d41ULL, 0xcb674bdefe7bb01cULL, }, + { 0x89eae6ec68625540ULL, 0x6b670b5ffe7fb40dULL, }, + { 0xfbbe40734d97e709ULL, 0x1af7bb5a553f53fcULL, }, + { 0xfbfe016b6d9bc709ULL, 0x16f7bb1e35bf56fcULL, }, + { 0xfbbe40674f93cf09ULL, 0x92f7fb9a1d3f72fcULL, }, + { 0xfbbe40634d93c748ULL, 0x32f7bb1b173f56fdULL, }, + { 0xad5eeebab9cfab81ULL, 0x2fd8ceffeb2b2514ULL, }, /* 72 */ + { 0xac5aafaab9cf8b81ULL, 0x27d8ceffabab2514ULL, }, + { 0xbc5eeeaebbcf8b81ULL, 0xa7d9c6ffab2b2514ULL, }, + { 0xaddaeeaaf9cf8fc0ULL, 0x27dac7ffab2f2515ULL, }, + { 0x714f565d5f35e24fULL, 0x8df188d8e94ae3b0ULL, }, + { 0x784f174d7e39e24fULL, 0x8df188dca9c2e6b0ULL, }, + { 0x704f564d5eb1ea4fULL, 0x8df1c8d8a94ae2b0ULL, }, + { 0x71cf566d5e33e64eULL, 0xadf389d9ab46e6a1ULL, }, + }; + + reset_msa_registers(); + + gettimeofday(&start, NULL); + + for (i = 0; i < PATTERN_INPUTS_SHORT_COUNT; i++) { + for (j = 0; j < PATTERN_INPUTS_SHORT_COUNT; j++) { + do_msa_BSET_B(b128_pattern[i], b128_pattern[j], + b128_result[PATTERN_INPUTS_SHORT_COUNT * i + j]); + } + } + + for (i = 0; i < RANDOM_INPUTS_SHORT_COUNT; i++) { + for (j = 0; j < RANDOM_INPUTS_SHORT_COUNT; j++) { + do_msa_BSET_B(b128_random[i], b128_random[j], + b128_result[((PATTERN_INPUTS_SHORT_COUNT) * + (PATTERN_INPUTS_SHORT_COUNT)) + + RANDOM_INPUTS_SHORT_COUNT * i + j]); + } + } + + gettimeofday(&end, NULL); + + elapsed_time = (end.tv_sec - start.tv_sec) * 1000.0; + elapsed_time += (end.tv_usec - start.tv_usec) / 1000.0; + + ret = check_results(instruction_name, TEST_COUNT_TOTAL, elapsed_time, + &b128_result[0][0], &b128_expect[0][0]); + + return ret; +} diff --git a/tests/tcg/mips/user/ase/msa/bit-set/test_msa_bset_d.c b/tests/tcg/mips/user/ase/msa/bit-set/test_msa_bset_d.c new file mode 100644 index 0000000000..ecd833bee0 --- /dev/null +++ b/tests/tcg/mips/user/ase/msa/bit-set/test_msa_bset_d.c @@ -0,0 +1,155 @@ +/* + * Test program for MSA instruction BSET.D + * + * Copyright (C) 2019 Wave Computing, Inc. + * Copyright (C) 2019 Aleksandar Markovic <amarkovic@wavecomp.com> + * + * This program 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, see <https://www.gnu.org/licenses/>. + * + */ + +#include <sys/time.h> +#include <stdint.h> + +#include "../../../../include/wrappers_msa.h" +#include "../../../../include/test_inputs_128.h" +#include "../../../../include/test_utils_128.h" + +#define TEST_COUNT_TOTAL ( \ + (PATTERN_INPUTS_SHORT_COUNT) * (PATTERN_INPUTS_SHORT_COUNT) + \ + (RANDOM_INPUTS_SHORT_COUNT) * (RANDOM_INPUTS_SHORT_COUNT)) + + +int32_t main(void) +{ + char *instruction_name = "BSET.D"; + int32_t ret; + uint32_t i, j; + struct timeval start, end; + double elapsed_time; + + uint64_t b128_result[TEST_COUNT_TOTAL][2]; + uint64_t b128_expect[TEST_COUNT_TOTAL][2] = { + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 0 */ + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, + { 0x8000000000000000ULL, 0x8000000000000000ULL, }, /* 8 */ + { 0x0000000000000001ULL, 0x0000000000000001ULL, }, + { 0x0000040000000000ULL, 0x0000040000000000ULL, }, + { 0x0000000000200000ULL, 0x0000000000200000ULL, }, + { 0x0000000000001000ULL, 0x0000000000001000ULL, }, + { 0x0008000000000000ULL, 0x0008000000000000ULL, }, + { 0x0000000000004000ULL, 0x0000000800000000ULL, }, + { 0x0002000000000000ULL, 0x0000000010000000ULL, }, + { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, }, /* 16 */ + { 0xaaaaaaaaaaaaaaabULL, 0xaaaaaaaaaaaaaaabULL, }, + { 0xaaaaaeaaaaaaaaaaULL, 0xaaaaaeaaaaaaaaaaULL, }, + { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, }, + { 0xaaaaaaaaaaaabaaaULL, 0xaaaaaaaaaaaabaaaULL, }, + { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, }, + { 0xaaaaaaaaaaaaeaaaULL, 0xaaaaaaaaaaaaaaaaULL, }, + { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaabaaaaaaaULL, }, + { 0xd555555555555555ULL, 0xd555555555555555ULL, }, /* 24 */ + { 0x5555555555555555ULL, 0x5555555555555555ULL, }, + { 0x5555555555555555ULL, 0x5555555555555555ULL, }, + { 0x5555555555755555ULL, 0x5555555555755555ULL, }, + { 0x5555555555555555ULL, 0x5555555555555555ULL, }, + { 0x555d555555555555ULL, 0x555d555555555555ULL, }, + { 0x5555555555555555ULL, 0x5555555d55555555ULL, }, + { 0x5557555555555555ULL, 0x5555555555555555ULL, }, + { 0xccccccccccccccccULL, 0xccccccccccccccccULL, }, /* 32 */ + { 0xcccccccccccccccdULL, 0xcccccccccccccccdULL, }, + { 0xccccccccccccccccULL, 0xccccccccccccccccULL, }, + { 0xccccccccccecccccULL, 0xccccccccccecccccULL, }, + { 0xccccccccccccdcccULL, 0xccccccccccccdcccULL, }, + { 0xccccccccccccccccULL, 0xccccccccccccccccULL, }, + { 0xccccccccccccccccULL, 0xccccccccccccccccULL, }, + { 0xccceccccccccccccULL, 0xccccccccdcccccccULL, }, + { 0xb333333333333333ULL, 0xb333333333333333ULL, }, /* 40 */ + { 0x3333333333333333ULL, 0x3333333333333333ULL, }, + { 0x3333373333333333ULL, 0x3333373333333333ULL, }, + { 0x3333333333333333ULL, 0x3333333333333333ULL, }, + { 0x3333333333333333ULL, 0x3333333333333333ULL, }, + { 0x333b333333333333ULL, 0x333b333333333333ULL, }, + { 0x3333333333337333ULL, 0x3333333b33333333ULL, }, + { 0x3333333333333333ULL, 0x3333333333333333ULL, }, + { 0xe38e38e38e38e38eULL, 0xb8e38e38e38e38e3ULL, }, /* 48 */ + { 0xe38e38e38e38e38fULL, 0x38e38e38e38e38e3ULL, }, + { 0xe38e3ce38e38e38eULL, 0x38e38e38e38e38e3ULL, }, + { 0xe38e38e38e38e38eULL, 0x38e38e38e3ae38e3ULL, }, + { 0xe38e38e38e38f38eULL, 0x38e38e38e38e38e3ULL, }, + { 0xe38e38e38e38e38eULL, 0x38eb8e38e38e38e3ULL, }, + { 0xe38e38e38e38e38eULL, 0x38e38e38e38e38e3ULL, }, + { 0xe38e38e38e38e38eULL, 0x38e38e38f38e38e3ULL, }, + { 0x9c71c71c71c71c71ULL, 0xc71c71c71c71c71cULL, }, /* 56 */ + { 0x1c71c71c71c71c71ULL, 0xc71c71c71c71c71dULL, }, + { 0x1c71c71c71c71c71ULL, 0xc71c75c71c71c71cULL, }, + { 0x1c71c71c71e71c71ULL, 0xc71c71c71c71c71cULL, }, + { 0x1c71c71c71c71c71ULL, 0xc71c71c71c71d71cULL, }, + { 0x1c79c71c71c71c71ULL, 0xc71c71c71c71c71cULL, }, + { 0x1c71c71c71c75c71ULL, 0xc71c71cf1c71c71cULL, }, + { 0x1c73c71c71c71c71ULL, 0xc71c71c71c71c71cULL, }, + { 0x886ae6cc28625541ULL, 0x4b670b5efe7bb00cULL, }, /* 64 */ + { 0x886ae6cc28625540ULL, 0x5b670b5efe7bb00cULL, }, + { 0x886ae6cc28625541ULL, 0x4b670b5efe7bb00cULL, }, + { 0x886ae6cc28625540ULL, 0x4b670b5ffe7bb00cULL, }, + { 0xfbbe00634d93c709ULL, 0x12f7bb1a153f52fcULL, }, + { 0xfbbe00634d93c708ULL, 0x12f7bb1a153f52fcULL, }, + { 0xfbbe00634d93c709ULL, 0x12f7bb1a153f52fcULL, }, + { 0xfbbe00634d93c708ULL, 0x12f7bb1b153f52fcULL, }, + { 0xac5aaeaab9cf8b81ULL, 0x27d8c6ffab2b3514ULL, }, /* 72 */ + { 0xac5aaeaab9cf8b80ULL, 0x37d8c6ffab2b2514ULL, }, + { 0xac5aaeaab9cf8b81ULL, 0x27d8c6ffab3b2514ULL, }, + { 0xac5aaeaab9cfcb80ULL, 0x27d8c6ffab2b2514ULL, }, + { 0x704f164d5e31e24fULL, 0x8df188d8a942f2a0ULL, }, + { 0x704f164d5e31e34eULL, 0x9df188d8a942e2a0ULL, }, + { 0x704f164d5e31e24fULL, 0x8df188d8a952e2a0ULL, }, + { 0x704f164d5e31e24eULL, 0x8df188d9a942e2a0ULL, }, + }; + + reset_msa_registers(); + + gettimeofday(&start, NULL); + + for (i = 0; i < PATTERN_INPUTS_SHORT_COUNT; i++) { + for (j = 0; j < PATTERN_INPUTS_SHORT_COUNT; j++) { + do_msa_BSET_D(b128_pattern[i], b128_pattern[j], + b128_result[PATTERN_INPUTS_SHORT_COUNT * i + j]); + } + } + + for (i = 0; i < RANDOM_INPUTS_SHORT_COUNT; i++) { + for (j = 0; j < RANDOM_INPUTS_SHORT_COUNT; j++) { + do_msa_BSET_D(b128_random[i], b128_random[j], + b128_result[((PATTERN_INPUTS_SHORT_COUNT) * + (PATTERN_INPUTS_SHORT_COUNT)) + + RANDOM_INPUTS_SHORT_COUNT * i + j]); + } + } + + gettimeofday(&end, NULL); + + elapsed_time = (end.tv_sec - start.tv_sec) * 1000.0; + elapsed_time += (end.tv_usec - start.tv_usec) / 1000.0; + + ret = check_results(instruction_name, TEST_COUNT_TOTAL, elapsed_time, + &b128_result[0][0], &b128_expect[0][0]); + + return ret; +} diff --git a/tests/tcg/mips/user/ase/msa/bit-set/test_msa_bset_h.c b/tests/tcg/mips/user/ase/msa/bit-set/test_msa_bset_h.c new file mode 100644 index 0000000000..de63f26881 --- /dev/null +++ b/tests/tcg/mips/user/ase/msa/bit-set/test_msa_bset_h.c @@ -0,0 +1,155 @@ +/* + * Test program for MSA instruction BSET.H + * + * Copyright (C) 2019 Wave Computing, Inc. + * Copyright (C) 2019 Aleksandar Markovic <amarkovic@wavecomp.com> + * + * This program 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, see <https://www.gnu.org/licenses/>. + * + */ + +#include <sys/time.h> +#include <stdint.h> + +#include "../../../../include/wrappers_msa.h" +#include "../../../../include/test_inputs_128.h" +#include "../../../../include/test_utils_128.h" + +#define TEST_COUNT_TOTAL ( \ + (PATTERN_INPUTS_SHORT_COUNT) * (PATTERN_INPUTS_SHORT_COUNT) + \ + (RANDOM_INPUTS_SHORT_COUNT) * (RANDOM_INPUTS_SHORT_COUNT)) + + +int32_t main(void) +{ + char *instruction_name = "BSET.H"; + int32_t ret; + uint32_t i, j; + struct timeval start, end; + double elapsed_time; + + uint64_t b128_result[TEST_COUNT_TOTAL][2]; + uint64_t b128_expect[TEST_COUNT_TOTAL][2] = { + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 0 */ + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, + { 0x8000800080008000ULL, 0x8000800080008000ULL, }, /* 8 */ + { 0x0001000100010001ULL, 0x0001000100010001ULL, }, + { 0x0400040004000400ULL, 0x0400040004000400ULL, }, + { 0x0020002000200020ULL, 0x0020002000200020ULL, }, + { 0x1000100010001000ULL, 0x1000100010001000ULL, }, + { 0x0008000800080008ULL, 0x0008000800080008ULL, }, + { 0x4000000801004000ULL, 0x0008010040000008ULL, }, + { 0x0002100000800002ULL, 0x1000008000021000ULL, }, + { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, }, /* 16 */ + { 0xaaabaaabaaabaaabULL, 0xaaabaaabaaabaaabULL, }, + { 0xaeaaaeaaaeaaaeaaULL, 0xaeaaaeaaaeaaaeaaULL, }, + { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, }, + { 0xbaaabaaabaaabaaaULL, 0xbaaabaaabaaabaaaULL, }, + { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, }, + { 0xeaaaaaaaabaaeaaaULL, 0xaaaaabaaeaaaaaaaULL, }, + { 0xaaaabaaaaaaaaaaaULL, 0xbaaaaaaaaaaabaaaULL, }, + { 0xd555d555d555d555ULL, 0xd555d555d555d555ULL, }, /* 24 */ + { 0x5555555555555555ULL, 0x5555555555555555ULL, }, + { 0x5555555555555555ULL, 0x5555555555555555ULL, }, + { 0x5575557555755575ULL, 0x5575557555755575ULL, }, + { 0x5555555555555555ULL, 0x5555555555555555ULL, }, + { 0x555d555d555d555dULL, 0x555d555d555d555dULL, }, + { 0x5555555d55555555ULL, 0x555d55555555555dULL, }, + { 0x5557555555d55557ULL, 0x555555d555575555ULL, }, + { 0xccccccccccccccccULL, 0xccccccccccccccccULL, }, /* 32 */ + { 0xcccdcccdcccdcccdULL, 0xcccdcccdcccdcccdULL, }, + { 0xccccccccccccccccULL, 0xccccccccccccccccULL, }, + { 0xccecccecccecccecULL, 0xccecccecccecccecULL, }, + { 0xdcccdcccdcccdcccULL, 0xdcccdcccdcccdcccULL, }, + { 0xccccccccccccccccULL, 0xccccccccccccccccULL, }, + { 0xcccccccccdccccccULL, 0xcccccdccccccccccULL, }, + { 0xcccedcccccccccceULL, 0xdccccccccccedcccULL, }, + { 0xb333b333b333b333ULL, 0xb333b333b333b333ULL, }, /* 40 */ + { 0x3333333333333333ULL, 0x3333333333333333ULL, }, + { 0x3733373337333733ULL, 0x3733373337333733ULL, }, + { 0x3333333333333333ULL, 0x3333333333333333ULL, }, + { 0x3333333333333333ULL, 0x3333333333333333ULL, }, + { 0x333b333b333b333bULL, 0x333b333b333b333bULL, }, + { 0x7333333b33337333ULL, 0x333b33337333333bULL, }, + { 0x3333333333b33333ULL, 0x333333b333333333ULL, }, + { 0xe38eb8e38e38e38eULL, 0xb8e38e38e38eb8e3ULL, }, /* 48 */ + { 0xe38f38e38e39e38fULL, 0x38e38e39e38f38e3ULL, }, + { 0xe78e3ce38e38e78eULL, 0x3ce38e38e78e3ce3ULL, }, + { 0xe3ae38e38e38e3aeULL, 0x38e38e38e3ae38e3ULL, }, + { 0xf38e38e39e38f38eULL, 0x38e39e38f38e38e3ULL, }, + { 0xe38e38eb8e38e38eULL, 0x38eb8e38e38e38ebULL, }, + { 0xe38e38eb8f38e38eULL, 0x38eb8f38e38e38ebULL, }, + { 0xe38e38e38eb8e38eULL, 0x38e38eb8e38e38e3ULL, }, + { 0x9c71c71cf1c79c71ULL, 0xc71cf1c79c71c71cULL, }, /* 56 */ + { 0x1c71c71d71c71c71ULL, 0xc71d71c71c71c71dULL, }, + { 0x1c71c71c75c71c71ULL, 0xc71c75c71c71c71cULL, }, + { 0x1c71c73c71e71c71ULL, 0xc73c71e71c71c73cULL, }, + { 0x1c71d71c71c71c71ULL, 0xd71c71c71c71d71cULL, }, + { 0x1c79c71c71cf1c79ULL, 0xc71c71cf1c79c71cULL, }, + { 0x5c71c71c71c75c71ULL, 0xc71c71c75c71c71cULL, }, + { 0x1c73d71c71c71c73ULL, 0xd71c71c71c73d71cULL, }, + { 0x8c6af6cc28665541ULL, 0x4be74b5efe7bb00cULL, }, /* 64 */ + { 0xc86ae6cc286a5540ULL, 0x4be70f5efe7bb00cULL, }, + { 0x8c6ae6cca8625541ULL, 0x4b678b5efe7bb01cULL, }, + { 0x886ae6cc28625540ULL, 0x4b670b5efe7fb00dULL, }, + { 0xffbe10634d97c709ULL, 0x12f7fb1a1d3f52fcULL, }, + { 0xfbbe006b4d9bc708ULL, 0x12f7bf1a953f52fcULL, }, + { 0xffbe0463cd93c709ULL, 0x13f7bb1a1d3f52fcULL, }, + { 0xfbbe20634d93c708ULL, 0x12f7bb1a153f52fdULL, }, + { 0xac5abeaab9cf8b81ULL, 0x27d8c6ffab2b3514ULL, }, /* 72 */ + { 0xec5aaeaab9cf8b80ULL, 0x27d8c6ffab2b3514ULL, }, + { 0xac5aaeaab9cf8b81ULL, 0x27d8c6ffab2b2514ULL, }, + { 0xac5aaeaab9cfcb80ULL, 0x27dac7ffab2f2515ULL, }, + { 0x744f164d5e35e24fULL, 0x8df1c8d8a942f2a0ULL, }, + { 0x704f164d5e39e34eULL, 0x8df18cd8a942f2a0ULL, }, + { 0x744f164dde31e24fULL, 0x8df188d8a942e2b0ULL, }, + { 0xf04f364d5e33e24eULL, 0x8df389d8a946e2a1ULL, }, + }; + + reset_msa_registers(); + + gettimeofday(&start, NULL); + + for (i = 0; i < PATTERN_INPUTS_SHORT_COUNT; i++) { + for (j = 0; j < PATTERN_INPUTS_SHORT_COUNT; j++) { + do_msa_BSET_H(b128_pattern[i], b128_pattern[j], + b128_result[PATTERN_INPUTS_SHORT_COUNT * i + j]); + } + } + + for (i = 0; i < RANDOM_INPUTS_SHORT_COUNT; i++) { + for (j = 0; j < RANDOM_INPUTS_SHORT_COUNT; j++) { + do_msa_BSET_H(b128_random[i], b128_random[j], + b128_result[((PATTERN_INPUTS_SHORT_COUNT) * + (PATTERN_INPUTS_SHORT_COUNT)) + + RANDOM_INPUTS_SHORT_COUNT * i + j]); + } + } + + gettimeofday(&end, NULL); + + elapsed_time = (end.tv_sec - start.tv_sec) * 1000.0; + elapsed_time += (end.tv_usec - start.tv_usec) / 1000.0; + + ret = check_results(instruction_name, TEST_COUNT_TOTAL, elapsed_time, + &b128_result[0][0], &b128_expect[0][0]); + + return ret; +} diff --git a/tests/tcg/mips/user/ase/msa/bit-set/test_msa_bset_w.c b/tests/tcg/mips/user/ase/msa/bit-set/test_msa_bset_w.c new file mode 100644 index 0000000000..b973e67065 --- /dev/null +++ b/tests/tcg/mips/user/ase/msa/bit-set/test_msa_bset_w.c @@ -0,0 +1,155 @@ +/* + * Test program for MSA instruction BSET.W + * + * Copyright (C) 2019 Wave Computing, Inc. + * Copyright (C) 2019 Aleksandar Markovic <amarkovic@wavecomp.com> + * + * This program 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, see <https://www.gnu.org/licenses/>. + * + */ + +#include <sys/time.h> +#include <stdint.h> + +#include "../../../../include/wrappers_msa.h" +#include "../../../../include/test_inputs_128.h" +#include "../../../../include/test_utils_128.h" + +#define TEST_COUNT_TOTAL ( \ + (PATTERN_INPUTS_SHORT_COUNT) * (PATTERN_INPUTS_SHORT_COUNT) + \ + (RANDOM_INPUTS_SHORT_COUNT) * (RANDOM_INPUTS_SHORT_COUNT)) + + +int32_t main(void) +{ + char *instruction_name = "BSET.W"; + int32_t ret; + uint32_t i, j; + struct timeval start, end; + double elapsed_time; + + uint64_t b128_result[TEST_COUNT_TOTAL][2]; + uint64_t b128_expect[TEST_COUNT_TOTAL][2] = { + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 0 */ + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, + { 0x8000000080000000ULL, 0x8000000080000000ULL, }, /* 8 */ + { 0x0000000100000001ULL, 0x0000000100000001ULL, }, + { 0x0000040000000400ULL, 0x0000040000000400ULL, }, + { 0x0020000000200000ULL, 0x0020000000200000ULL, }, + { 0x0000100000001000ULL, 0x0000100000001000ULL, }, + { 0x0008000000080000ULL, 0x0008000000080000ULL, }, + { 0x0000000800004000ULL, 0x0100000000000008ULL, }, + { 0x1000000000020000ULL, 0x0000008010000000ULL, }, + { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, }, /* 16 */ + { 0xaaaaaaabaaaaaaabULL, 0xaaaaaaabaaaaaaabULL, }, + { 0xaaaaaeaaaaaaaeaaULL, 0xaaaaaeaaaaaaaeaaULL, }, + { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, }, + { 0xaaaabaaaaaaabaaaULL, 0xaaaabaaaaaaabaaaULL, }, + { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, }, + { 0xaaaaaaaaaaaaeaaaULL, 0xabaaaaaaaaaaaaaaULL, }, + { 0xbaaaaaaaaaaaaaaaULL, 0xaaaaaaaabaaaaaaaULL, }, + { 0xd5555555d5555555ULL, 0xd5555555d5555555ULL, }, /* 24 */ + { 0x5555555555555555ULL, 0x5555555555555555ULL, }, + { 0x5555555555555555ULL, 0x5555555555555555ULL, }, + { 0x5575555555755555ULL, 0x5575555555755555ULL, }, + { 0x5555555555555555ULL, 0x5555555555555555ULL, }, + { 0x555d5555555d5555ULL, 0x555d5555555d5555ULL, }, + { 0x5555555d55555555ULL, 0x555555555555555dULL, }, + { 0x5555555555575555ULL, 0x555555d555555555ULL, }, + { 0xccccccccccccccccULL, 0xccccccccccccccccULL, }, /* 32 */ + { 0xcccccccdcccccccdULL, 0xcccccccdcccccccdULL, }, + { 0xccccccccccccccccULL, 0xccccccccccccccccULL, }, + { 0xccecccccccecccccULL, 0xccecccccccecccccULL, }, + { 0xccccdcccccccdcccULL, 0xccccdcccccccdcccULL, }, + { 0xccccccccccccccccULL, 0xccccccccccccccccULL, }, + { 0xccccccccccccccccULL, 0xcdccccccccccccccULL, }, + { 0xdcccccccccceccccULL, 0xccccccccdcccccccULL, }, + { 0xb3333333b3333333ULL, 0xb3333333b3333333ULL, }, /* 40 */ + { 0x3333333333333333ULL, 0x3333333333333333ULL, }, + { 0x3333373333333733ULL, 0x3333373333333733ULL, }, + { 0x3333333333333333ULL, 0x3333333333333333ULL, }, + { 0x3333333333333333ULL, 0x3333333333333333ULL, }, + { 0x333b3333333b3333ULL, 0x333b3333333b3333ULL, }, + { 0x3333333b33337333ULL, 0x333333333333333bULL, }, + { 0x3333333333333333ULL, 0x333333b333333333ULL, }, + { 0xe38e38e38e38e38eULL, 0xb8e38e38e38e38e3ULL, }, /* 48 */ + { 0xe38e38e38e38e38fULL, 0x38e38e39e38e38e3ULL, }, + { 0xe38e3ce38e38e78eULL, 0x38e38e38e38e3ce3ULL, }, + { 0xe3ae38e38e38e38eULL, 0x38e38e38e3ae38e3ULL, }, + { 0xe38e38e38e38f38eULL, 0x38e39e38e38e38e3ULL, }, + { 0xe38e38e38e38e38eULL, 0x38eb8e38e38e38e3ULL, }, + { 0xe38e38eb8e38e38eULL, 0x39e38e38e38e38ebULL, }, + { 0xf38e38e38e3ae38eULL, 0x38e38eb8f38e38e3ULL, }, + { 0x9c71c71cf1c71c71ULL, 0xc71c71c79c71c71cULL, }, /* 56 */ + { 0x1c71c71d71c71c71ULL, 0xc71c71c71c71c71dULL, }, + { 0x1c71c71c71c71c71ULL, 0xc71c75c71c71c71cULL, }, + { 0x1c71c71c71e71c71ULL, 0xc73c71c71c71c71cULL, }, + { 0x1c71d71c71c71c71ULL, 0xc71c71c71c71d71cULL, }, + { 0x1c79c71c71cf1c71ULL, 0xc71c71c71c79c71cULL, }, + { 0x1c71c71c71c75c71ULL, 0xc71c71c71c71c71cULL, }, + { 0x1c71c71c71c71c71ULL, 0xc71c71c71c71c71cULL, }, + { 0x886af6cc28625541ULL, 0x4b670b5efe7bb00cULL, }, /* 64 */ + { 0x886ae6cc28625540ULL, 0x4f670b5efe7bb00cULL, }, + { 0x886ae6cc28625541ULL, 0xcb670b5efe7bb00cULL, }, + { 0x886ae6cc28625540ULL, 0x4b670b5efe7bb00dULL, }, + { 0xfbbe10634d93c709ULL, 0x52f7bb1a153f52fcULL, }, + { 0xfbbe006b4d93c708ULL, 0x16f7bb1a153f52fcULL, }, + { 0xfbbe04634d93c709ULL, 0x92f7bb1a153f52fcULL, }, + { 0xfbbe20634d93c708ULL, 0x13f7bb1a153f52fdULL, }, + { 0xac5abeaab9cf8b81ULL, 0x67d8c6ffab2b3514ULL, }, /* 72 */ + { 0xac5aaeaab9cf8b80ULL, 0x27d8c6ffbb2b2514ULL, }, + { 0xac5aaeaab9cf8b81ULL, 0xa7d8c6ffab3b2514ULL, }, + { 0xac5aaeaab9cfcb80ULL, 0x27d8c6ffab2b2515ULL, }, + { 0x704f164d5e31e24fULL, 0xcdf188d8a942f2a0ULL, }, + { 0x704f164d5e31e34eULL, 0x8df188d8b942e2a0ULL, }, + { 0x704f164d5e31e24fULL, 0x8df188d8a952e2a0ULL, }, + { 0x704f364d5e31e24eULL, 0x8df188d8a942e2a1ULL, }, + }; + + reset_msa_registers(); + + gettimeofday(&start, NULL); + + for (i = 0; i < PATTERN_INPUTS_SHORT_COUNT; i++) { + for (j = 0; j < PATTERN_INPUTS_SHORT_COUNT; j++) { + do_msa_BSET_W(b128_pattern[i], b128_pattern[j], + b128_result[PATTERN_INPUTS_SHORT_COUNT * i + j]); + } + } + + for (i = 0; i < RANDOM_INPUTS_SHORT_COUNT; i++) { + for (j = 0; j < RANDOM_INPUTS_SHORT_COUNT; j++) { + do_msa_BSET_W(b128_random[i], b128_random[j], + b128_result[((PATTERN_INPUTS_SHORT_COUNT) * + (PATTERN_INPUTS_SHORT_COUNT)) + + RANDOM_INPUTS_SHORT_COUNT * i + j]); + } + } + + gettimeofday(&end, NULL); + + elapsed_time = (end.tv_sec - start.tv_sec) * 1000.0; + elapsed_time += (end.tv_usec - start.tv_usec) / 1000.0; + + ret = check_results(instruction_name, TEST_COUNT_TOTAL, elapsed_time, + &b128_result[0][0], &b128_expect[0][0]); + + return ret; +} diff --git a/tests/tcg/mips/user/ase/msa/int-multiply/test_msa_mul_q_h.c b/tests/tcg/mips/user/ase/msa/fixed-multiply/test_msa_mul_q_h.c index f1526087fa..39a89ac099 100644 --- a/tests/tcg/mips/user/ase/msa/int-multiply/test_msa_mul_q_h.c +++ b/tests/tcg/mips/user/ase/msa/fixed-multiply/test_msa_mul_q_h.c @@ -1,8 +1,10 @@ /* * Test program for MSA instruction MUL_Q.H * - * Copyright (C) 2018 Wave Computing, Inc. - * Copyright (C) 2018 Mateja Marjanovic <mateja.marjanovic@rt-rk.com> + * Copyright (C) 2019 Wave Computing, Inc. + * Copyright (C) 2019 Aleksandar Markovic <amarkovic@wavecomp.com> + * Copyright (C) 2019 RT-RK Computer Based Systems LLC + * Copyright (C) 2019 Mateja Marjanovic <mateja.marjanovic@rt-rk.com> * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -23,8 +25,8 @@ #include <stdint.h> #include "../../../../include/wrappers_msa.h" -#include "../../../../include/test_inputs.h" -#include "../../../../include/test_utils.h" +#include "../../../../include/test_inputs_128.h" +#include "../../../../include/test_utils_128.h" #define TEST_COUNT_TOTAL ( \ (PATTERN_INPUTS_SHORT_COUNT) * (PATTERN_INPUTS_SHORT_COUNT) + \ @@ -119,8 +121,12 @@ int32_t main(void) { 0xb69bf1d4cc591b07ULL, 0xdc7e3510397df77dULL, }, { 0x9712fb9b1db7ec38ULL, 0xbccff56b01071259ULL, }, { 0xfc43001139150d37ULL, 0xef194023f19aecf4ULL, }, + { 0xb69bf1d4cc591b07ULL, 0xdc7e3510397df77dULL, }, + { 0x628a03e2455006e3ULL, 0x65a26eec3ac806bdULL, }, }; + reset_msa_registers(); + gettimeofday(&start, NULL); for (i = 0; i < PATTERN_INPUTS_SHORT_COUNT; i++) { diff --git a/tests/tcg/mips/user/ase/msa/int-multiply/test_msa_mul_q_w.c b/tests/tcg/mips/user/ase/msa/fixed-multiply/test_msa_mul_q_w.c index df815ee9da..07f2daecac 100644 --- a/tests/tcg/mips/user/ase/msa/int-multiply/test_msa_mul_q_w.c +++ b/tests/tcg/mips/user/ase/msa/fixed-multiply/test_msa_mul_q_w.c @@ -1,8 +1,10 @@ /* * Test program for MSA instruction MUL_Q.W * - * Copyright (C) 2018 Wave Computing, Inc. - * Copyright (C) 2018 Mateja Marjanovic <mateja.marjanovic@rt-rk.com> + * Copyright (C) 2019 Wave Computing, Inc. + * Copyright (C) 2019 Aleksandar Markovic <amarkovic@wavecomp.com> + * Copyright (C) 2019 RT-RK Computer Based Systems LLC + * Copyright (C) 2019 Mateja Marjanovic <mateja.marjanovic@rt-rk.com> * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -23,8 +25,8 @@ #include <stdint.h> #include "../../../../include/wrappers_msa.h" -#include "../../../../include/test_inputs.h" -#include "../../../../include/test_utils.h" +#include "../../../../include/test_inputs_128.h" +#include "../../../../include/test_utils_128.h" #define TEST_COUNT_TOTAL ( \ (PATTERN_INPUTS_SHORT_COUNT) * (PATTERN_INPUTS_SHORT_COUNT) + \ @@ -119,8 +121,12 @@ int32_t main(void) { 0xb69baa39cc590fcdULL, 0xdc7e6df7397c58d9ULL, }, { 0x9713a7171db7f3a5ULL, 0xbccfb4690107236fULL, }, { 0xfc439edc3916c1e4ULL, 0xef19389cf19a0fddULL, }, + { 0xb69baa39cc590fcdULL, 0xdc7e6df7397c58d9ULL, }, + { 0x628a97e4455157d3ULL, 0x65a1c5e13ac736e1ULL, }, }; + reset_msa_registers(); + gettimeofday(&start, NULL); for (i = 0; i < PATTERN_INPUTS_SHORT_COUNT; i++) { diff --git a/tests/tcg/mips/user/ase/msa/int-multiply/test_msa_mulr_q_h.c b/tests/tcg/mips/user/ase/msa/fixed-multiply/test_msa_mulr_q_h.c index fd0a5fa7a8..e35af2fb7e 100644 --- a/tests/tcg/mips/user/ase/msa/int-multiply/test_msa_mulr_q_h.c +++ b/tests/tcg/mips/user/ase/msa/fixed-multiply/test_msa_mulr_q_h.c @@ -1,8 +1,10 @@ /* * Test program for MSA instruction MULR_Q.H * - * Copyright (C) 2018 Wave Computing, Inc. - * Copyright (C) 2018 Mateja Marjanovic <mateja.marjanovic@rt-rk.com> + * Copyright (C) 2019 Wave Computing, Inc. + * Copyright (C) 2019 Aleksandar Markovic <amarkovic@wavecomp.com> + * Copyright (C) 2019 RT-RK Computer Based Systems LLC + * Copyright (C) 2019 Mateja Marjanovic <mateja.marjanovic@rt-rk.com> * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -23,8 +25,8 @@ #include <stdint.h> #include "../../../../include/wrappers_msa.h" -#include "../../../../include/test_inputs.h" -#include "../../../../include/test_utils.h" +#include "../../../../include/test_inputs_128.h" +#include "../../../../include/test_utils_128.h" #define TEST_COUNT_TOTAL ( \ (PATTERN_INPUTS_SHORT_COUNT) * (PATTERN_INPUTS_SHORT_COUNT) + \ @@ -119,8 +121,12 @@ int32_t main(void) { 0xb69bf1d4cc591b07ULL, 0xdc7f3511397df77eULL, }, { 0x9713fb9c1db7ec39ULL, 0xbccff56b01081259ULL, }, { 0xfc44001139160d37ULL, 0xef1a4023f19aecf5ULL, }, + { 0xb69bf1d4cc591b07ULL, 0xdc7f3511397df77eULL, }, + { 0x628a03e3455006e4ULL, 0x65a36eec3ac806beULL, }, }; + reset_msa_registers(); + gettimeofday(&start, NULL); for (i = 0; i < PATTERN_INPUTS_SHORT_COUNT; i++) { diff --git a/tests/tcg/mips/user/ase/msa/int-multiply/test_msa_mulr_q_w.c b/tests/tcg/mips/user/ase/msa/fixed-multiply/test_msa_mulr_q_w.c index f28b0d0a20..3cedf672af 100644 --- a/tests/tcg/mips/user/ase/msa/int-multiply/test_msa_mulr_q_w.c +++ b/tests/tcg/mips/user/ase/msa/fixed-multiply/test_msa_mulr_q_w.c @@ -1,8 +1,10 @@ /* * Test program for MSA instruction MULR_Q.W * - * Copyright (C) 2018 Wave Computing, Inc. - * Copyright (C) 2018 Mateja Marjanovic <mateja.marjanovic@rt-rk.com> + * Copyright (C) 2019 Wave Computing, Inc. + * Copyright (C) 2019 Aleksandar Markovic <amarkovic@wavecomp.com> + * Copyright (C) 2019 RT-RK Computer Based Systems LLC + * Copyright (C) 2019 Mateja Marjanovic <mateja.marjanovic@rt-rk.com> * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -23,8 +25,8 @@ #include <stdint.h> #include "../../../../include/wrappers_msa.h" -#include "../../../../include/test_inputs.h" -#include "../../../../include/test_utils.h" +#include "../../../../include/test_inputs_128.h" +#include "../../../../include/test_utils_128.h" #define TEST_COUNT_TOTAL ( \ (PATTERN_INPUTS_SHORT_COUNT) * (PATTERN_INPUTS_SHORT_COUNT) + \ @@ -119,8 +121,12 @@ int32_t main(void) { 0xb69baa3acc590fcdULL, 0xdc7e6df7397c58daULL, }, { 0x9713a7171db7f3a6ULL, 0xbccfb46a0107236fULL, }, { 0xfc439edd3916c1e4ULL, 0xef19389cf19a0fdeULL, }, + { 0xb69baa3acc590fcdULL, 0xdc7e6df7397c58daULL, }, + { 0x628a97e4455157d3ULL, 0x65a1c5e23ac736e2ULL, }, }; + reset_msa_registers(); + gettimeofday(&start, NULL); for (i = 0; i < PATTERN_INPUTS_SHORT_COUNT; i++) { diff --git a/tests/tcg/mips/user/ase/msa/float-max-min/test_msa_fmax_a_d.c b/tests/tcg/mips/user/ase/msa/float-max-min/test_msa_fmax_a_d.c new file mode 100644 index 0000000000..1807cabdd5 --- /dev/null +++ b/tests/tcg/mips/user/ase/msa/float-max-min/test_msa_fmax_a_d.c @@ -0,0 +1,155 @@ +/* + * Test program for MSA instruction FMAX_A.D + * + * Copyright (C) 2019 Wave Computing, Inc. + * Copyright (C) 2019 Aleksandar Markovic <amarkovic@wavecomp.com> + * + * This program 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, see <https://www.gnu.org/licenses/>. + * + */ + +#include <sys/time.h> +#include <stdint.h> + +#include "../../../../include/wrappers_msa.h" +#include "../../../../include/test_inputs_128.h" +#include "../../../../include/test_utils_128.h" + +#define TEST_COUNT_TOTAL ( \ + (PATTERN_INPUTS_SHORT_COUNT) * (PATTERN_INPUTS_SHORT_COUNT) + \ + (RANDOM_INPUTS_SHORT_COUNT) * (RANDOM_INPUTS_SHORT_COUNT)) + + +int32_t main(void) +{ + char *instruction_name = "FMAX_A.D"; + int32_t ret; + uint32_t i, j; + struct timeval start, end; + double elapsed_time; + + uint64_t b128_result[TEST_COUNT_TOTAL][2]; + uint64_t b128_expect[TEST_COUNT_TOTAL][2] = { + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 0 */ + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, }, + { 0x5555555555555555ULL, 0x5555555555555555ULL, }, + { 0xccccccccccccccccULL, 0xccccccccccccccccULL, }, + { 0x3333333333333333ULL, 0x3333333333333333ULL, }, + { 0xe38e38e38e38e38eULL, 0x38e38e38e38e38e3ULL, }, + { 0x1c71c71c71c71c71ULL, 0xc71c71c71c71c71cULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, /* 8 */ + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, }, + { 0x5555555555555555ULL, 0x5555555555555555ULL, }, + { 0xccccccccccccccccULL, 0xccccccccccccccccULL, }, + { 0x3333333333333333ULL, 0x3333333333333333ULL, }, + { 0xe38e38e38e38e38eULL, 0x38e38e38e38e38e3ULL, }, + { 0x1c71c71c71c71c71ULL, 0xc71c71c71c71c71cULL, }, + { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, }, /* 16 */ + { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, }, + { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, }, + { 0x5555555555555555ULL, 0x5555555555555555ULL, }, + { 0xccccccccccccccccULL, 0xccccccccccccccccULL, }, + { 0x3333333333333333ULL, 0x3333333333333333ULL, }, + { 0xe38e38e38e38e38eULL, 0x38e38e38e38e38e3ULL, }, + { 0xaaaaaaaaaaaaaaaaULL, 0xc71c71c71c71c71cULL, }, + { 0x5555555555555555ULL, 0x5555555555555555ULL, }, /* 24 */ + { 0x5555555555555555ULL, 0x5555555555555555ULL, }, + { 0x5555555555555555ULL, 0x5555555555555555ULL, }, + { 0x5555555555555555ULL, 0x5555555555555555ULL, }, + { 0x5555555555555555ULL, 0x5555555555555555ULL, }, + { 0x5555555555555555ULL, 0x5555555555555555ULL, }, + { 0xe38e38e38e38e38eULL, 0x5555555555555555ULL, }, + { 0x5555555555555555ULL, 0x5555555555555555ULL, }, + { 0xccccccccccccccccULL, 0xccccccccccccccccULL, }, /* 32 */ + { 0xccccccccccccccccULL, 0xccccccccccccccccULL, }, + { 0xccccccccccccccccULL, 0xccccccccccccccccULL, }, + { 0x5555555555555555ULL, 0x5555555555555555ULL, }, + { 0xccccccccccccccccULL, 0xccccccccccccccccULL, }, + { 0xccccccccccccccccULL, 0xccccccccccccccccULL, }, + { 0xe38e38e38e38e38eULL, 0xccccccccccccccccULL, }, + { 0xccccccccccccccccULL, 0xccccccccccccccccULL, }, + { 0x3333333333333333ULL, 0x3333333333333333ULL, }, /* 40 */ + { 0x3333333333333333ULL, 0x3333333333333333ULL, }, + { 0x3333333333333333ULL, 0x3333333333333333ULL, }, + { 0x5555555555555555ULL, 0x5555555555555555ULL, }, + { 0xccccccccccccccccULL, 0xccccccccccccccccULL, }, + { 0x3333333333333333ULL, 0x3333333333333333ULL, }, + { 0xe38e38e38e38e38eULL, 0x38e38e38e38e38e3ULL, }, + { 0x3333333333333333ULL, 0xc71c71c71c71c71cULL, }, + { 0xe38e38e38e38e38eULL, 0x38e38e38e38e38e3ULL, }, /* 48 */ + { 0xe38e38e38e38e38eULL, 0x38e38e38e38e38e3ULL, }, + { 0xe38e38e38e38e38eULL, 0x38e38e38e38e38e3ULL, }, + { 0xe38e38e38e38e38eULL, 0x5555555555555555ULL, }, + { 0xe38e38e38e38e38eULL, 0xccccccccccccccccULL, }, + { 0xe38e38e38e38e38eULL, 0x38e38e38e38e38e3ULL, }, + { 0xe38e38e38e38e38eULL, 0x38e38e38e38e38e3ULL, }, + { 0xe38e38e38e38e38eULL, 0xc71c71c71c71c71cULL, }, + { 0x1c71c71c71c71c71ULL, 0xc71c71c71c71c71cULL, }, /* 56 */ + { 0x1c71c71c71c71c71ULL, 0xc71c71c71c71c71cULL, }, + { 0xaaaaaaaaaaaaaaaaULL, 0xc71c71c71c71c71cULL, }, + { 0x5555555555555555ULL, 0x5555555555555555ULL, }, + { 0xccccccccccccccccULL, 0xccccccccccccccccULL, }, + { 0x3333333333333333ULL, 0xc71c71c71c71c71cULL, }, + { 0xe38e38e38e38e38eULL, 0xc71c71c71c71c71cULL, }, + { 0x1c71c71c71c71c71ULL, 0xc71c71c71c71c71cULL, }, + { 0x886ae6cc28625540ULL, 0x4b670b5efe7bb00cULL, }, /* 64 */ + { 0xfbbe00634d93c708ULL, 0x4b670b5efe7bb00cULL, }, + { 0xac5aaeaab9cf8b80ULL, 0x4b670b5efe7bb00cULL, }, + { 0x704f164d5e31e24eULL, 0x4b670b5efe7bb00cULL, }, + { 0xfbbe00634d93c708ULL, 0x4b670b5efe7bb00cULL, }, + { 0xfbbe00634d93c708ULL, 0x12f7bb1a153f52fcULL, }, + { 0xfbbe00634d93c708ULL, 0x27d8c6ffab2b2514ULL, }, + { 0xfbbe00634d93c708ULL, 0x12f7bb1a153f52fcULL, }, + { 0xac5aaeaab9cf8b80ULL, 0x4b670b5efe7bb00cULL, }, /* 72 */ + { 0xfbbe00634d93c708ULL, 0x27d8c6ffab2b2514ULL, }, + { 0xac5aaeaab9cf8b80ULL, 0x27d8c6ffab2b2514ULL, }, + { 0x704f164d5e31e24eULL, 0x27d8c6ffab2b2514ULL, }, + { 0x704f164d5e31e24eULL, 0x4b670b5efe7bb00cULL, }, + { 0xfbbe00634d93c708ULL, 0x12f7bb1a153f52fcULL, }, + { 0x704f164d5e31e24eULL, 0x27d8c6ffab2b2514ULL, }, + { 0x704f164d5e31e24eULL, 0x8df188d8a942e2a0ULL, }, +}; + + reset_msa_registers(); + + gettimeofday(&start, NULL); + + for (i = 0; i < PATTERN_INPUTS_SHORT_COUNT; i++) { + for (j = 0; j < PATTERN_INPUTS_SHORT_COUNT; j++) { + do_msa_FMAX_A_D(b128_pattern[i], b128_pattern[j], + b128_result[PATTERN_INPUTS_SHORT_COUNT * i + j]); + } + } + + for (i = 0; i < RANDOM_INPUTS_SHORT_COUNT; i++) { + for (j = 0; j < RANDOM_INPUTS_SHORT_COUNT; j++) { + do_msa_FMAX_A_D(b128_random[i], b128_random[j], + b128_result[((PATTERN_INPUTS_SHORT_COUNT) * + (PATTERN_INPUTS_SHORT_COUNT)) + + RANDOM_INPUTS_SHORT_COUNT * i + j]); + } + } + + gettimeofday(&end, NULL); + + elapsed_time = (end.tv_sec - start.tv_sec) * 1000.0; + elapsed_time += (end.tv_usec - start.tv_usec) / 1000.0; + + ret = check_results(instruction_name, TEST_COUNT_TOTAL, elapsed_time, + &b128_result[0][0], &b128_expect[0][0]); + + return ret; +} diff --git a/tests/tcg/mips/user/ase/msa/float-max-min/test_msa_fmax_a_w.c b/tests/tcg/mips/user/ase/msa/float-max-min/test_msa_fmax_a_w.c new file mode 100644 index 0000000000..b999b1fdb5 --- /dev/null +++ b/tests/tcg/mips/user/ase/msa/float-max-min/test_msa_fmax_a_w.c @@ -0,0 +1,155 @@ +/* + * Test program for MSA instruction FMAX_A.W + * + * Copyright (C) 2019 Wave Computing, Inc. + * Copyright (C) 2019 Aleksandar Markovic <amarkovic@wavecomp.com> + * + * This program 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, see <https://www.gnu.org/licenses/>. + * + */ + +#include <sys/time.h> +#include <stdint.h> + +#include "../../../../include/wrappers_msa.h" +#include "../../../../include/test_inputs_128.h" +#include "../../../../include/test_utils_128.h" + +#define TEST_COUNT_TOTAL ( \ + (PATTERN_INPUTS_SHORT_COUNT) * (PATTERN_INPUTS_SHORT_COUNT) + \ + (RANDOM_INPUTS_SHORT_COUNT) * (RANDOM_INPUTS_SHORT_COUNT)) + + +int32_t main(void) +{ + char *instruction_name = "FMAX_A.W"; + int32_t ret; + uint32_t i, j; + struct timeval start, end; + double elapsed_time; + + uint64_t b128_result[TEST_COUNT_TOTAL][2]; + uint64_t b128_expect[TEST_COUNT_TOTAL][2] = { + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 0 */ + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, }, + { 0x5555555555555555ULL, 0x5555555555555555ULL, }, + { 0xccccccccccccccccULL, 0xccccccccccccccccULL, }, + { 0x3333333333333333ULL, 0x3333333333333333ULL, }, + { 0xe38e38e38e38e38eULL, 0x38e38e38e38e38e3ULL, }, + { 0x1c71c71c71c71c71ULL, 0xc71c71c71c71c71cULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, /* 8 */ + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, }, + { 0x5555555555555555ULL, 0x5555555555555555ULL, }, + { 0xccccccccccccccccULL, 0xccccccccccccccccULL, }, + { 0x3333333333333333ULL, 0x3333333333333333ULL, }, + { 0xe38e38e38e38e38eULL, 0x38e38e38e38e38e3ULL, }, + { 0x1c71c71c71c71c71ULL, 0xc71c71c71c71c71cULL, }, + { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, }, /* 16 */ + { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, }, + { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, }, + { 0x5555555555555555ULL, 0x5555555555555555ULL, }, + { 0xccccccccccccccccULL, 0xccccccccccccccccULL, }, + { 0x3333333333333333ULL, 0x3333333333333333ULL, }, + { 0xe38e38e3aaaaaaaaULL, 0x38e38e38e38e38e3ULL, }, + { 0xaaaaaaaa71c71c71ULL, 0xc71c71c7aaaaaaaaULL, }, + { 0x5555555555555555ULL, 0x5555555555555555ULL, }, /* 24 */ + { 0x5555555555555555ULL, 0x5555555555555555ULL, }, + { 0x5555555555555555ULL, 0x5555555555555555ULL, }, + { 0x5555555555555555ULL, 0x5555555555555555ULL, }, + { 0x5555555555555555ULL, 0x5555555555555555ULL, }, + { 0x5555555555555555ULL, 0x5555555555555555ULL, }, + { 0xe38e38e355555555ULL, 0x55555555e38e38e3ULL, }, + { 0x5555555571c71c71ULL, 0x5555555555555555ULL, }, + { 0xccccccccccccccccULL, 0xccccccccccccccccULL, }, /* 32 */ + { 0xccccccccccccccccULL, 0xccccccccccccccccULL, }, + { 0xccccccccccccccccULL, 0xccccccccccccccccULL, }, + { 0x5555555555555555ULL, 0x5555555555555555ULL, }, + { 0xccccccccccccccccULL, 0xccccccccccccccccULL, }, + { 0xccccccccccccccccULL, 0xccccccccccccccccULL, }, + { 0xe38e38e3ccccccccULL, 0xcccccccce38e38e3ULL, }, + { 0xcccccccc71c71c71ULL, 0xccccccccccccccccULL, }, + { 0x3333333333333333ULL, 0x3333333333333333ULL, }, /* 40 */ + { 0x3333333333333333ULL, 0x3333333333333333ULL, }, + { 0x3333333333333333ULL, 0x3333333333333333ULL, }, + { 0x5555555555555555ULL, 0x5555555555555555ULL, }, + { 0xccccccccccccccccULL, 0xccccccccccccccccULL, }, + { 0x3333333333333333ULL, 0x3333333333333333ULL, }, + { 0xe38e38e333333333ULL, 0x38e38e38e38e38e3ULL, }, + { 0x3333333371c71c71ULL, 0xc71c71c733333333ULL, }, + { 0xe38e38e38e38e38eULL, 0x38e38e38e38e38e3ULL, }, /* 48 */ + { 0xe38e38e38e38e38eULL, 0x38e38e38e38e38e3ULL, }, + { 0xe38e38e3aaaaaaaaULL, 0x38e38e38e38e38e3ULL, }, + { 0xe38e38e355555555ULL, 0x55555555e38e38e3ULL, }, + { 0xe38e38e3ccccccccULL, 0xcccccccce38e38e3ULL, }, + { 0xe38e38e333333333ULL, 0x38e38e38e38e38e3ULL, }, + { 0xe38e38e38e38e38eULL, 0x38e38e38e38e38e3ULL, }, + { 0xe38e38e371c71c71ULL, 0xc71c71c7e38e38e3ULL, }, + { 0x1c71c71c71c71c71ULL, 0xc71c71c71c71c71cULL, }, /* 56 */ + { 0x1c71c71c71c71c71ULL, 0xc71c71c71c71c71cULL, }, + { 0xaaaaaaaa71c71c71ULL, 0xc71c71c7aaaaaaaaULL, }, + { 0x5555555571c71c71ULL, 0x5555555555555555ULL, }, + { 0xcccccccc71c71c71ULL, 0xccccccccccccccccULL, }, + { 0x3333333371c71c71ULL, 0xc71c71c733333333ULL, }, + { 0xe38e38e371c71c71ULL, 0xc71c71c7e38e38e3ULL, }, + { 0x1c71c71c71c71c71ULL, 0xc71c71c71c71c71cULL, }, + { 0x886ae6cc28625540ULL, 0x4b670b5efe7bb00cULL, }, /* 64 */ + { 0xfbbe00634d93c708ULL, 0x4b670b5efe7bb00cULL, }, + { 0xac5aaeaab9cf8b80ULL, 0x4b670b5efe7bb00cULL, }, + { 0x704f164d5e31e24eULL, 0x4b670b5efe7bb00cULL, }, + { 0xfbbe00634d93c708ULL, 0x4b670b5efe7bb00cULL, }, + { 0xfbbe00634d93c708ULL, 0x12f7bb1a153f52fcULL, }, + { 0xfbbe00634d93c708ULL, 0x27d8c6ffab2b2514ULL, }, + { 0xfbbe00635e31e24eULL, 0x12f7bb1aa942e2a0ULL, }, + { 0xac5aaeaab9cf8b80ULL, 0x4b670b5efe7bb00cULL, }, /* 72 */ + { 0xfbbe00634d93c708ULL, 0x27d8c6ffab2b2514ULL, }, + { 0xac5aaeaab9cf8b80ULL, 0x27d8c6ffab2b2514ULL, }, + { 0x704f164d5e31e24eULL, 0x27d8c6ffab2b2514ULL, }, + { 0x704f164d5e31e24eULL, 0x4b670b5efe7bb00cULL, }, + { 0xfbbe00635e31e24eULL, 0x12f7bb1aa942e2a0ULL, }, + { 0x704f164d5e31e24eULL, 0x27d8c6ffab2b2514ULL, }, + { 0x704f164d5e31e24eULL, 0x8df188d8a942e2a0ULL, }, +}; + + reset_msa_registers(); + + gettimeofday(&start, NULL); + + for (i = 0; i < PATTERN_INPUTS_SHORT_COUNT; i++) { + for (j = 0; j < PATTERN_INPUTS_SHORT_COUNT; j++) { + do_msa_FMAX_A_W(b128_pattern[i], b128_pattern[j], + b128_result[PATTERN_INPUTS_SHORT_COUNT * i + j]); + } + } + + for (i = 0; i < RANDOM_INPUTS_SHORT_COUNT; i++) { + for (j = 0; j < RANDOM_INPUTS_SHORT_COUNT; j++) { + do_msa_FMAX_A_W(b128_random[i], b128_random[j], + b128_result[((PATTERN_INPUTS_SHORT_COUNT) * + (PATTERN_INPUTS_SHORT_COUNT)) + + RANDOM_INPUTS_SHORT_COUNT * i + j]); + } + } + + gettimeofday(&end, NULL); + + elapsed_time = (end.tv_sec - start.tv_sec) * 1000.0; + elapsed_time += (end.tv_usec - start.tv_usec) / 1000.0; + + ret = check_results(instruction_name, TEST_COUNT_TOTAL, elapsed_time, + &b128_result[0][0], &b128_expect[0][0]); + + return ret; +} diff --git a/tests/tcg/mips/user/ase/msa/float-max-min/test_msa_fmax_d.c b/tests/tcg/mips/user/ase/msa/float-max-min/test_msa_fmax_d.c new file mode 100644 index 0000000000..b5ce6c7543 --- /dev/null +++ b/tests/tcg/mips/user/ase/msa/float-max-min/test_msa_fmax_d.c @@ -0,0 +1,155 @@ +/* + * Test program for MSA instruction FMAX.D + * + * Copyright (C) 2019 Wave Computing, Inc. + * Copyright (C) 2019 Aleksandar Markovic <amarkovic@wavecomp.com> + * + * This program 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, see <https://www.gnu.org/licenses/>. + * + */ + +#include <sys/time.h> +#include <stdint.h> + +#include "../../../../include/wrappers_msa.h" +#include "../../../../include/test_inputs_128.h" +#include "../../../../include/test_utils_128.h" + +#define TEST_COUNT_TOTAL ( \ + (PATTERN_INPUTS_SHORT_COUNT) * (PATTERN_INPUTS_SHORT_COUNT) + \ + (RANDOM_INPUTS_SHORT_COUNT) * (RANDOM_INPUTS_SHORT_COUNT)) + + +int32_t main(void) +{ + char *instruction_name = "FMAX.D"; + int32_t ret; + uint32_t i, j; + struct timeval start, end; + double elapsed_time; + + uint64_t b128_result[TEST_COUNT_TOTAL][2]; + uint64_t b128_expect[TEST_COUNT_TOTAL][2] = { + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 0 */ + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, }, + { 0x5555555555555555ULL, 0x5555555555555555ULL, }, + { 0xccccccccccccccccULL, 0xccccccccccccccccULL, }, + { 0x3333333333333333ULL, 0x3333333333333333ULL, }, + { 0xe38e38e38e38e38eULL, 0x38e38e38e38e38e3ULL, }, + { 0x1c71c71c71c71c71ULL, 0xc71c71c71c71c71cULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, /* 8 */ + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x5555555555555555ULL, 0x5555555555555555ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x3333333333333333ULL, 0x3333333333333333ULL, }, + { 0x0000000000000000ULL, 0x38e38e38e38e38e3ULL, }, + { 0x1c71c71c71c71c71ULL, 0x0000000000000000ULL, }, + { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, }, /* 16 */ + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, }, + { 0x5555555555555555ULL, 0x5555555555555555ULL, }, + { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, }, + { 0x3333333333333333ULL, 0x3333333333333333ULL, }, + { 0xaaaaaaaaaaaaaaaaULL, 0x38e38e38e38e38e3ULL, }, + { 0x1c71c71c71c71c71ULL, 0xaaaaaaaaaaaaaaaaULL, }, + { 0x5555555555555555ULL, 0x5555555555555555ULL, }, /* 24 */ + { 0x5555555555555555ULL, 0x5555555555555555ULL, }, + { 0x5555555555555555ULL, 0x5555555555555555ULL, }, + { 0x5555555555555555ULL, 0x5555555555555555ULL, }, + { 0x5555555555555555ULL, 0x5555555555555555ULL, }, + { 0x5555555555555555ULL, 0x5555555555555555ULL, }, + { 0x5555555555555555ULL, 0x5555555555555555ULL, }, + { 0x5555555555555555ULL, 0x5555555555555555ULL, }, + { 0xccccccccccccccccULL, 0xccccccccccccccccULL, }, /* 32 */ + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, }, + { 0x5555555555555555ULL, 0x5555555555555555ULL, }, + { 0xccccccccccccccccULL, 0xccccccccccccccccULL, }, + { 0x3333333333333333ULL, 0x3333333333333333ULL, }, + { 0xccccccccccccccccULL, 0x38e38e38e38e38e3ULL, }, + { 0x1c71c71c71c71c71ULL, 0xc71c71c71c71c71cULL, }, + { 0x3333333333333333ULL, 0x3333333333333333ULL, }, /* 40 */ + { 0x3333333333333333ULL, 0x3333333333333333ULL, }, + { 0x3333333333333333ULL, 0x3333333333333333ULL, }, + { 0x5555555555555555ULL, 0x5555555555555555ULL, }, + { 0x3333333333333333ULL, 0x3333333333333333ULL, }, + { 0x3333333333333333ULL, 0x3333333333333333ULL, }, + { 0x3333333333333333ULL, 0x38e38e38e38e38e3ULL, }, + { 0x3333333333333333ULL, 0x3333333333333333ULL, }, + { 0xe38e38e38e38e38eULL, 0x38e38e38e38e38e3ULL, }, /* 48 */ + { 0x0000000000000000ULL, 0x38e38e38e38e38e3ULL, }, + { 0xaaaaaaaaaaaaaaaaULL, 0x38e38e38e38e38e3ULL, }, + { 0x5555555555555555ULL, 0x5555555555555555ULL, }, + { 0xccccccccccccccccULL, 0x38e38e38e38e38e3ULL, }, + { 0x3333333333333333ULL, 0x38e38e38e38e38e3ULL, }, + { 0xe38e38e38e38e38eULL, 0x38e38e38e38e38e3ULL, }, + { 0x1c71c71c71c71c71ULL, 0x38e38e38e38e38e3ULL, }, + { 0x1c71c71c71c71c71ULL, 0xc71c71c71c71c71cULL, }, /* 56 */ + { 0x1c71c71c71c71c71ULL, 0x0000000000000000ULL, }, + { 0x1c71c71c71c71c71ULL, 0xaaaaaaaaaaaaaaaaULL, }, + { 0x5555555555555555ULL, 0x5555555555555555ULL, }, + { 0x1c71c71c71c71c71ULL, 0xc71c71c71c71c71cULL, }, + { 0x3333333333333333ULL, 0x3333333333333333ULL, }, + { 0x1c71c71c71c71c71ULL, 0x38e38e38e38e38e3ULL, }, + { 0x1c71c71c71c71c71ULL, 0xc71c71c71c71c71cULL, }, + { 0x886ae6cc28625540ULL, 0x4b670b5efe7bb00cULL, }, /* 64 */ + { 0x886ae6cc28625540ULL, 0x4b670b5efe7bb00cULL, }, + { 0x886ae6cc28625540ULL, 0x4b670b5efe7bb00cULL, }, + { 0x704f164d5e31e24eULL, 0x4b670b5efe7bb00cULL, }, + { 0x886ae6cc28625540ULL, 0x4b670b5efe7bb00cULL, }, + { 0xfbbe00634d93c708ULL, 0x12f7bb1a153f52fcULL, }, + { 0xac5aaeaab9cf8b80ULL, 0x27d8c6ffab2b2514ULL, }, + { 0x704f164d5e31e24eULL, 0x12f7bb1a153f52fcULL, }, + { 0x886ae6cc28625540ULL, 0x4b670b5efe7bb00cULL, }, /* 72 */ + { 0xac5aaeaab9cf8b80ULL, 0x27d8c6ffab2b2514ULL, }, + { 0xac5aaeaab9cf8b80ULL, 0x27d8c6ffab2b2514ULL, }, + { 0x704f164d5e31e24eULL, 0x27d8c6ffab2b2514ULL, }, + { 0x704f164d5e31e24eULL, 0x4b670b5efe7bb00cULL, }, + { 0x704f164d5e31e24eULL, 0x12f7bb1a153f52fcULL, }, + { 0x704f164d5e31e24eULL, 0x27d8c6ffab2b2514ULL, }, + { 0x704f164d5e31e24eULL, 0x8df188d8a942e2a0ULL, }, +}; + + reset_msa_registers(); + + gettimeofday(&start, NULL); + + for (i = 0; i < PATTERN_INPUTS_SHORT_COUNT; i++) { + for (j = 0; j < PATTERN_INPUTS_SHORT_COUNT; j++) { + do_msa_FMAX_D(b128_pattern[i], b128_pattern[j], + b128_result[PATTERN_INPUTS_SHORT_COUNT * i + j]); + } + } + + for (i = 0; i < RANDOM_INPUTS_SHORT_COUNT; i++) { + for (j = 0; j < RANDOM_INPUTS_SHORT_COUNT; j++) { + do_msa_FMAX_D(b128_random[i], b128_random[j], + b128_result[((PATTERN_INPUTS_SHORT_COUNT) * + (PATTERN_INPUTS_SHORT_COUNT)) + + RANDOM_INPUTS_SHORT_COUNT * i + j]); + } + } + + gettimeofday(&end, NULL); + + elapsed_time = (end.tv_sec - start.tv_sec) * 1000.0; + elapsed_time += (end.tv_usec - start.tv_usec) / 1000.0; + + ret = check_results(instruction_name, TEST_COUNT_TOTAL, elapsed_time, + &b128_result[0][0], &b128_expect[0][0]); + + return ret; +} diff --git a/tests/tcg/mips/user/ase/msa/float-max-min/test_msa_fmax_w.c b/tests/tcg/mips/user/ase/msa/float-max-min/test_msa_fmax_w.c new file mode 100644 index 0000000000..5fafd3080f --- /dev/null +++ b/tests/tcg/mips/user/ase/msa/float-max-min/test_msa_fmax_w.c @@ -0,0 +1,155 @@ +/* + * Test program for MSA instruction FMAX.W + * + * Copyright (C) 2019 Wave Computing, Inc. + * Copyright (C) 2019 Aleksandar Markovic <amarkovic@wavecomp.com> + * + * This program 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, see <https://www.gnu.org/licenses/>. + * + */ + +#include <sys/time.h> +#include <stdint.h> + +#include "../../../../include/wrappers_msa.h" +#include "../../../../include/test_inputs_128.h" +#include "../../../../include/test_utils_128.h" + +#define TEST_COUNT_TOTAL ( \ + (PATTERN_INPUTS_SHORT_COUNT) * (PATTERN_INPUTS_SHORT_COUNT) + \ + (RANDOM_INPUTS_SHORT_COUNT) * (RANDOM_INPUTS_SHORT_COUNT)) + + +int32_t main(void) +{ + char *instruction_name = "FMAX.W"; + int32_t ret; + uint32_t i, j; + struct timeval start, end; + double elapsed_time; + + uint64_t b128_result[TEST_COUNT_TOTAL][2]; + uint64_t b128_expect[TEST_COUNT_TOTAL][2] = { + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 0 */ + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, }, + { 0x5555555555555555ULL, 0x5555555555555555ULL, }, + { 0xccccccccccccccccULL, 0xccccccccccccccccULL, }, + { 0x3333333333333333ULL, 0x3333333333333333ULL, }, + { 0xe38e38e38e38e38eULL, 0x38e38e38e38e38e3ULL, }, + { 0x1c71c71c71c71c71ULL, 0xc71c71c71c71c71cULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, /* 8 */ + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x5555555555555555ULL, 0x5555555555555555ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x3333333333333333ULL, 0x3333333333333333ULL, }, + { 0x0000000000000000ULL, 0x38e38e3800000000ULL, }, + { 0x1c71c71c71c71c71ULL, 0x000000001c71c71cULL, }, + { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, }, /* 16 */ + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, }, + { 0x5555555555555555ULL, 0x5555555555555555ULL, }, + { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, }, + { 0x3333333333333333ULL, 0x3333333333333333ULL, }, + { 0xaaaaaaaa8e38e38eULL, 0x38e38e38aaaaaaaaULL, }, + { 0x1c71c71c71c71c71ULL, 0xaaaaaaaa1c71c71cULL, }, + { 0x5555555555555555ULL, 0x5555555555555555ULL, }, /* 24 */ + { 0x5555555555555555ULL, 0x5555555555555555ULL, }, + { 0x5555555555555555ULL, 0x5555555555555555ULL, }, + { 0x5555555555555555ULL, 0x5555555555555555ULL, }, + { 0x5555555555555555ULL, 0x5555555555555555ULL, }, + { 0x5555555555555555ULL, 0x5555555555555555ULL, }, + { 0x5555555555555555ULL, 0x5555555555555555ULL, }, + { 0x5555555571c71c71ULL, 0x5555555555555555ULL, }, + { 0xccccccccccccccccULL, 0xccccccccccccccccULL, }, /* 32 */ + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, }, + { 0x5555555555555555ULL, 0x5555555555555555ULL, }, + { 0xccccccccccccccccULL, 0xccccccccccccccccULL, }, + { 0x3333333333333333ULL, 0x3333333333333333ULL, }, + { 0xcccccccc8e38e38eULL, 0x38e38e38ccccccccULL, }, + { 0x1c71c71c71c71c71ULL, 0xc71c71c71c71c71cULL, }, + { 0x3333333333333333ULL, 0x3333333333333333ULL, }, /* 40 */ + { 0x3333333333333333ULL, 0x3333333333333333ULL, }, + { 0x3333333333333333ULL, 0x3333333333333333ULL, }, + { 0x5555555555555555ULL, 0x5555555555555555ULL, }, + { 0x3333333333333333ULL, 0x3333333333333333ULL, }, + { 0x3333333333333333ULL, 0x3333333333333333ULL, }, + { 0x3333333333333333ULL, 0x38e38e3833333333ULL, }, + { 0x3333333371c71c71ULL, 0x3333333333333333ULL, }, + { 0xe38e38e38e38e38eULL, 0x38e38e38e38e38e3ULL, }, /* 48 */ + { 0x0000000000000000ULL, 0x38e38e3800000000ULL, }, + { 0xaaaaaaaa8e38e38eULL, 0x38e38e38aaaaaaaaULL, }, + { 0x5555555555555555ULL, 0x5555555555555555ULL, }, + { 0xcccccccc8e38e38eULL, 0x38e38e38ccccccccULL, }, + { 0x3333333333333333ULL, 0x38e38e3833333333ULL, }, + { 0xe38e38e38e38e38eULL, 0x38e38e38e38e38e3ULL, }, + { 0x1c71c71c71c71c71ULL, 0x38e38e381c71c71cULL, }, + { 0x1c71c71c71c71c71ULL, 0xc71c71c71c71c71cULL, }, /* 56 */ + { 0x1c71c71c71c71c71ULL, 0x000000001c71c71cULL, }, + { 0x1c71c71c71c71c71ULL, 0xaaaaaaaa1c71c71cULL, }, + { 0x5555555571c71c71ULL, 0x5555555555555555ULL, }, + { 0x1c71c71c71c71c71ULL, 0xc71c71c71c71c71cULL, }, + { 0x3333333371c71c71ULL, 0x3333333333333333ULL, }, + { 0x1c71c71c71c71c71ULL, 0x38e38e381c71c71cULL, }, + { 0x1c71c71c71c71c71ULL, 0xc71c71c71c71c71cULL, }, + { 0x886ae6cc28625540ULL, 0x4b670b5efe7bb00cULL, }, /* 64 */ + { 0x886ae6cc4d93c708ULL, 0x4b670b5e153f52fcULL, }, + { 0x886ae6cc28625540ULL, 0x4b670b5eab2b2514ULL, }, + { 0x704f164d5e31e24eULL, 0x4b670b5ea942e2a0ULL, }, + { 0x886ae6cc4d93c708ULL, 0x4b670b5e153f52fcULL, }, + { 0xfbbe00634d93c708ULL, 0x12f7bb1a153f52fcULL, }, + { 0xac5aaeaa4d93c708ULL, 0x27d8c6ff153f52fcULL, }, + { 0x704f164d5e31e24eULL, 0x12f7bb1a153f52fcULL, }, + { 0x886ae6cc28625540ULL, 0x4b670b5eab2b2514ULL, }, /* 72 */ + { 0xac5aaeaa4d93c708ULL, 0x27d8c6ff153f52fcULL, }, + { 0xac5aaeaab9cf8b80ULL, 0x27d8c6ffab2b2514ULL, }, + { 0x704f164d5e31e24eULL, 0x27d8c6ffa942e2a0ULL, }, + { 0x704f164d5e31e24eULL, 0x4b670b5ea942e2a0ULL, }, + { 0x704f164d5e31e24eULL, 0x12f7bb1a153f52fcULL, }, + { 0x704f164d5e31e24eULL, 0x27d8c6ffa942e2a0ULL, }, + { 0x704f164d5e31e24eULL, 0x8df188d8a942e2a0ULL, }, +}; + + reset_msa_registers(); + + gettimeofday(&start, NULL); + + for (i = 0; i < PATTERN_INPUTS_SHORT_COUNT; i++) { + for (j = 0; j < PATTERN_INPUTS_SHORT_COUNT; j++) { + do_msa_FMAX_W(b128_pattern[i], b128_pattern[j], + b128_result[PATTERN_INPUTS_SHORT_COUNT * i + j]); + } + } + + for (i = 0; i < RANDOM_INPUTS_SHORT_COUNT; i++) { + for (j = 0; j < RANDOM_INPUTS_SHORT_COUNT; j++) { + do_msa_FMAX_W(b128_random[i], b128_random[j], + b128_result[((PATTERN_INPUTS_SHORT_COUNT) * + (PATTERN_INPUTS_SHORT_COUNT)) + + RANDOM_INPUTS_SHORT_COUNT * i + j]); + } + } + + gettimeofday(&end, NULL); + + elapsed_time = (end.tv_sec - start.tv_sec) * 1000.0; + elapsed_time += (end.tv_usec - start.tv_usec) / 1000.0; + + ret = check_results(instruction_name, TEST_COUNT_TOTAL, elapsed_time, + &b128_result[0][0], &b128_expect[0][0]); + + return ret; +} diff --git a/tests/tcg/mips/user/ase/msa/float-max-min/test_msa_fmin_a_d.c b/tests/tcg/mips/user/ase/msa/float-max-min/test_msa_fmin_a_d.c new file mode 100644 index 0000000000..c0b4001eb1 --- /dev/null +++ b/tests/tcg/mips/user/ase/msa/float-max-min/test_msa_fmin_a_d.c @@ -0,0 +1,155 @@ +/* + * Test program for MSA instruction FMIN_A.D + * + * Copyright (C) 2019 Wave Computing, Inc. + * Copyright (C) 2019 Aleksandar Markovic <amarkovic@wavecomp.com> + * + * This program 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, see <https://www.gnu.org/licenses/>. + * + */ + +#include <sys/time.h> +#include <stdint.h> + +#include "../../../../include/wrappers_msa.h" +#include "../../../../include/test_inputs_128.h" +#include "../../../../include/test_utils_128.h" + +#define TEST_COUNT_TOTAL ( \ + (PATTERN_INPUTS_SHORT_COUNT) * (PATTERN_INPUTS_SHORT_COUNT) + \ + (RANDOM_INPUTS_SHORT_COUNT) * (RANDOM_INPUTS_SHORT_COUNT)) + + +int32_t main(void) +{ + char *instruction_name = "FMIN_A.D"; + int32_t ret; + uint32_t i, j; + struct timeval start, end; + double elapsed_time; + + uint64_t b128_result[TEST_COUNT_TOTAL][2]; + uint64_t b128_expect[TEST_COUNT_TOTAL][2] = { + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 0 */ + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, }, + { 0x5555555555555555ULL, 0x5555555555555555ULL, }, + { 0xccccccccccccccccULL, 0xccccccccccccccccULL, }, + { 0x3333333333333333ULL, 0x3333333333333333ULL, }, + { 0xe38e38e38e38e38eULL, 0x38e38e38e38e38e3ULL, }, + { 0x1c71c71c71c71c71ULL, 0xc71c71c71c71c71cULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, /* 8 */ + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, }, /* 16 */ + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, }, + { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, }, + { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, }, + { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, }, + { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, }, + { 0x1c71c71c71c71c71ULL, 0xaaaaaaaaaaaaaaaaULL, }, + { 0x5555555555555555ULL, 0x5555555555555555ULL, }, /* 24 */ + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, }, + { 0x5555555555555555ULL, 0x5555555555555555ULL, }, + { 0xccccccccccccccccULL, 0xccccccccccccccccULL, }, + { 0x3333333333333333ULL, 0x3333333333333333ULL, }, + { 0x5555555555555555ULL, 0x38e38e38e38e38e3ULL, }, + { 0x1c71c71c71c71c71ULL, 0xc71c71c71c71c71cULL, }, + { 0xccccccccccccccccULL, 0xccccccccccccccccULL, }, /* 32 */ + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, }, + { 0xccccccccccccccccULL, 0xccccccccccccccccULL, }, + { 0xccccccccccccccccULL, 0xccccccccccccccccULL, }, + { 0x3333333333333333ULL, 0x3333333333333333ULL, }, + { 0xccccccccccccccccULL, 0x38e38e38e38e38e3ULL, }, + { 0x1c71c71c71c71c71ULL, 0xc71c71c71c71c71cULL, }, + { 0x3333333333333333ULL, 0x3333333333333333ULL, }, /* 40 */ + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, }, + { 0x3333333333333333ULL, 0x3333333333333333ULL, }, + { 0x3333333333333333ULL, 0x3333333333333333ULL, }, + { 0x3333333333333333ULL, 0x3333333333333333ULL, }, + { 0x3333333333333333ULL, 0x3333333333333333ULL, }, + { 0x1c71c71c71c71c71ULL, 0x3333333333333333ULL, }, + { 0xe38e38e38e38e38eULL, 0x38e38e38e38e38e3ULL, }, /* 48 */ + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, }, + { 0x5555555555555555ULL, 0x38e38e38e38e38e3ULL, }, + { 0xccccccccccccccccULL, 0x38e38e38e38e38e3ULL, }, + { 0x3333333333333333ULL, 0x3333333333333333ULL, }, + { 0xe38e38e38e38e38eULL, 0x38e38e38e38e38e3ULL, }, + { 0x1c71c71c71c71c71ULL, 0x38e38e38e38e38e3ULL, }, + { 0x1c71c71c71c71c71ULL, 0xc71c71c71c71c71cULL, }, /* 56 */ + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x1c71c71c71c71c71ULL, 0xaaaaaaaaaaaaaaaaULL, }, + { 0x1c71c71c71c71c71ULL, 0xc71c71c71c71c71cULL, }, + { 0x1c71c71c71c71c71ULL, 0xc71c71c71c71c71cULL, }, + { 0x1c71c71c71c71c71ULL, 0x3333333333333333ULL, }, + { 0x1c71c71c71c71c71ULL, 0x38e38e38e38e38e3ULL, }, + { 0x1c71c71c71c71c71ULL, 0xc71c71c71c71c71cULL, }, + { 0x886ae6cc28625540ULL, 0x4b670b5efe7bb00cULL, }, /* 64 */ + { 0x886ae6cc28625540ULL, 0x12f7bb1a153f52fcULL, }, + { 0x886ae6cc28625540ULL, 0x27d8c6ffab2b2514ULL, }, + { 0x886ae6cc28625540ULL, 0x8df188d8a942e2a0ULL, }, + { 0x886ae6cc28625540ULL, 0x12f7bb1a153f52fcULL, }, + { 0xfbbe00634d93c708ULL, 0x12f7bb1a153f52fcULL, }, + { 0xac5aaeaab9cf8b80ULL, 0x12f7bb1a153f52fcULL, }, + { 0x704f164d5e31e24eULL, 0x8df188d8a942e2a0ULL, }, + { 0x886ae6cc28625540ULL, 0x27d8c6ffab2b2514ULL, }, /* 72 */ + { 0xac5aaeaab9cf8b80ULL, 0x12f7bb1a153f52fcULL, }, + { 0xac5aaeaab9cf8b80ULL, 0x27d8c6ffab2b2514ULL, }, + { 0xac5aaeaab9cf8b80ULL, 0x8df188d8a942e2a0ULL, }, + { 0x886ae6cc28625540ULL, 0x8df188d8a942e2a0ULL, }, + { 0x704f164d5e31e24eULL, 0x8df188d8a942e2a0ULL, }, + { 0xac5aaeaab9cf8b80ULL, 0x8df188d8a942e2a0ULL, }, + { 0x704f164d5e31e24eULL, 0x8df188d8a942e2a0ULL, }, +}; + + reset_msa_registers(); + + gettimeofday(&start, NULL); + + for (i = 0; i < PATTERN_INPUTS_SHORT_COUNT; i++) { + for (j = 0; j < PATTERN_INPUTS_SHORT_COUNT; j++) { + do_msa_FMIN_A_D(b128_pattern[i], b128_pattern[j], + b128_result[PATTERN_INPUTS_SHORT_COUNT * i + j]); + } + } + + for (i = 0; i < RANDOM_INPUTS_SHORT_COUNT; i++) { + for (j = 0; j < RANDOM_INPUTS_SHORT_COUNT; j++) { + do_msa_FMIN_A_D(b128_random[i], b128_random[j], + b128_result[((PATTERN_INPUTS_SHORT_COUNT) * + (PATTERN_INPUTS_SHORT_COUNT)) + + RANDOM_INPUTS_SHORT_COUNT * i + j]); + } + } + + gettimeofday(&end, NULL); + + elapsed_time = (end.tv_sec - start.tv_sec) * 1000.0; + elapsed_time += (end.tv_usec - start.tv_usec) / 1000.0; + + ret = check_results(instruction_name, TEST_COUNT_TOTAL, elapsed_time, + &b128_result[0][0], &b128_expect[0][0]); + + return ret; +} diff --git a/tests/tcg/mips/user/ase/msa/float-max-min/test_msa_fmin_a_w.c b/tests/tcg/mips/user/ase/msa/float-max-min/test_msa_fmin_a_w.c new file mode 100644 index 0000000000..d174fcd669 --- /dev/null +++ b/tests/tcg/mips/user/ase/msa/float-max-min/test_msa_fmin_a_w.c @@ -0,0 +1,155 @@ +/* + * Test program for MSA instruction FMIN_A.W + * + * Copyright (C) 2019 Wave Computing, Inc. + * Copyright (C) 2019 Aleksandar Markovic <amarkovic@wavecomp.com> + * + * This program 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, see <https://www.gnu.org/licenses/>. + * + */ + +#include <sys/time.h> +#include <stdint.h> + +#include "../../../../include/wrappers_msa.h" +#include "../../../../include/test_inputs_128.h" +#include "../../../../include/test_utils_128.h" + +#define TEST_COUNT_TOTAL ( \ + (PATTERN_INPUTS_SHORT_COUNT) * (PATTERN_INPUTS_SHORT_COUNT) + \ + (RANDOM_INPUTS_SHORT_COUNT) * (RANDOM_INPUTS_SHORT_COUNT)) + + +int32_t main(void) +{ + char *instruction_name = "FMIN_A.W"; + int32_t ret; + uint32_t i, j; + struct timeval start, end; + double elapsed_time; + + uint64_t b128_result[TEST_COUNT_TOTAL][2]; + uint64_t b128_expect[TEST_COUNT_TOTAL][2] = { + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 0 */ + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, }, + { 0x5555555555555555ULL, 0x5555555555555555ULL, }, + { 0xccccccccccccccccULL, 0xccccccccccccccccULL, }, + { 0x3333333333333333ULL, 0x3333333333333333ULL, }, + { 0xe38e38e38e38e38eULL, 0x38e38e38e38e38e3ULL, }, + { 0x1c71c71c71c71c71ULL, 0xc71c71c71c71c71cULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, /* 8 */ + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, }, /* 16 */ + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, }, + { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, }, + { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, }, + { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, }, + { 0xaaaaaaaa8e38e38eULL, 0xaaaaaaaaaaaaaaaaULL, }, + { 0x1c71c71caaaaaaaaULL, 0xaaaaaaaa1c71c71cULL, }, + { 0x5555555555555555ULL, 0x5555555555555555ULL, }, /* 24 */ + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, }, + { 0x5555555555555555ULL, 0x5555555555555555ULL, }, + { 0xccccccccccccccccULL, 0xccccccccccccccccULL, }, + { 0x3333333333333333ULL, 0x3333333333333333ULL, }, + { 0x555555558e38e38eULL, 0x38e38e3855555555ULL, }, + { 0x1c71c71c55555555ULL, 0xc71c71c71c71c71cULL, }, + { 0xccccccccccccccccULL, 0xccccccccccccccccULL, }, /* 32 */ + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, }, + { 0xccccccccccccccccULL, 0xccccccccccccccccULL, }, + { 0xccccccccccccccccULL, 0xccccccccccccccccULL, }, + { 0x3333333333333333ULL, 0x3333333333333333ULL, }, + { 0xcccccccc8e38e38eULL, 0x38e38e38ccccccccULL, }, + { 0x1c71c71cccccccccULL, 0xc71c71c71c71c71cULL, }, + { 0x3333333333333333ULL, 0x3333333333333333ULL, }, /* 40 */ + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, }, + { 0x3333333333333333ULL, 0x3333333333333333ULL, }, + { 0x3333333333333333ULL, 0x3333333333333333ULL, }, + { 0x3333333333333333ULL, 0x3333333333333333ULL, }, + { 0x333333338e38e38eULL, 0x3333333333333333ULL, }, + { 0x1c71c71c33333333ULL, 0x333333331c71c71cULL, }, + { 0xe38e38e38e38e38eULL, 0x38e38e38e38e38e3ULL, }, /* 48 */ + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0xaaaaaaaa8e38e38eULL, 0xaaaaaaaaaaaaaaaaULL, }, + { 0x555555558e38e38eULL, 0x38e38e3855555555ULL, }, + { 0xcccccccc8e38e38eULL, 0x38e38e38ccccccccULL, }, + { 0x333333338e38e38eULL, 0x3333333333333333ULL, }, + { 0xe38e38e38e38e38eULL, 0x38e38e38e38e38e3ULL, }, + { 0x1c71c71c8e38e38eULL, 0x38e38e381c71c71cULL, }, + { 0x1c71c71c71c71c71ULL, 0xc71c71c71c71c71cULL, }, /* 56 */ + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x1c71c71caaaaaaaaULL, 0xaaaaaaaa1c71c71cULL, }, + { 0x1c71c71c55555555ULL, 0xc71c71c71c71c71cULL, }, + { 0x1c71c71cccccccccULL, 0xc71c71c71c71c71cULL, }, + { 0x1c71c71c33333333ULL, 0x333333331c71c71cULL, }, + { 0x1c71c71c8e38e38eULL, 0x38e38e381c71c71cULL, }, + { 0x1c71c71c71c71c71ULL, 0xc71c71c71c71c71cULL, }, + { 0x886ae6cc28625540ULL, 0x4b670b5efe7bb00cULL, }, /* 64 */ + { 0x886ae6cc28625540ULL, 0x12f7bb1a153f52fcULL, }, + { 0x886ae6cc28625540ULL, 0x27d8c6ffab2b2514ULL, }, + { 0x886ae6cc28625540ULL, 0x8df188d8a942e2a0ULL, }, + { 0x886ae6cc28625540ULL, 0x12f7bb1a153f52fcULL, }, + { 0xfbbe00634d93c708ULL, 0x12f7bb1a153f52fcULL, }, + { 0xac5aaeaab9cf8b80ULL, 0x12f7bb1a153f52fcULL, }, + { 0x704f164d4d93c708ULL, 0x8df188d8153f52fcULL, }, + { 0x886ae6cc28625540ULL, 0x27d8c6ffab2b2514ULL, }, /* 72 */ + { 0xac5aaeaab9cf8b80ULL, 0x12f7bb1a153f52fcULL, }, + { 0xac5aaeaab9cf8b80ULL, 0x27d8c6ffab2b2514ULL, }, + { 0xac5aaeaab9cf8b80ULL, 0x8df188d8a942e2a0ULL, }, + { 0x886ae6cc28625540ULL, 0x8df188d8a942e2a0ULL, }, + { 0x704f164d4d93c708ULL, 0x8df188d8153f52fcULL, }, + { 0xac5aaeaab9cf8b80ULL, 0x8df188d8a942e2a0ULL, }, + { 0x704f164d5e31e24eULL, 0x8df188d8a942e2a0ULL, }, +}; + + reset_msa_registers(); + + gettimeofday(&start, NULL); + + for (i = 0; i < PATTERN_INPUTS_SHORT_COUNT; i++) { + for (j = 0; j < PATTERN_INPUTS_SHORT_COUNT; j++) { + do_msa_FMIN_A_W(b128_pattern[i], b128_pattern[j], + b128_result[PATTERN_INPUTS_SHORT_COUNT * i + j]); + } + } + + for (i = 0; i < RANDOM_INPUTS_SHORT_COUNT; i++) { + for (j = 0; j < RANDOM_INPUTS_SHORT_COUNT; j++) { + do_msa_FMIN_A_W(b128_random[i], b128_random[j], + b128_result[((PATTERN_INPUTS_SHORT_COUNT) * + (PATTERN_INPUTS_SHORT_COUNT)) + + RANDOM_INPUTS_SHORT_COUNT * i + j]); + } + } + + gettimeofday(&end, NULL); + + elapsed_time = (end.tv_sec - start.tv_sec) * 1000.0; + elapsed_time += (end.tv_usec - start.tv_usec) / 1000.0; + + ret = check_results(instruction_name, TEST_COUNT_TOTAL, elapsed_time, + &b128_result[0][0], &b128_expect[0][0]); + + return ret; +} diff --git a/tests/tcg/mips/user/ase/msa/float-max-min/test_msa_fmin_d.c b/tests/tcg/mips/user/ase/msa/float-max-min/test_msa_fmin_d.c new file mode 100644 index 0000000000..62c149f83a --- /dev/null +++ b/tests/tcg/mips/user/ase/msa/float-max-min/test_msa_fmin_d.c @@ -0,0 +1,155 @@ +/* + * Test program for MSA instruction FMIN.D + * + * Copyright (C) 2019 Wave Computing, Inc. + * Copyright (C) 2019 Aleksandar Markovic <amarkovic@wavecomp.com> + * + * This program 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, see <https://www.gnu.org/licenses/>. + * + */ + +#include <sys/time.h> +#include <stdint.h> + +#include "../../../../include/wrappers_msa.h" +#include "../../../../include/test_inputs_128.h" +#include "../../../../include/test_utils_128.h" + +#define TEST_COUNT_TOTAL ( \ + (PATTERN_INPUTS_SHORT_COUNT) * (PATTERN_INPUTS_SHORT_COUNT) + \ + (RANDOM_INPUTS_SHORT_COUNT) * (RANDOM_INPUTS_SHORT_COUNT)) + + +int32_t main(void) +{ + char *instruction_name = "FMIN.D"; + int32_t ret; + uint32_t i, j; + struct timeval start, end; + double elapsed_time; + + uint64_t b128_result[TEST_COUNT_TOTAL][2]; + uint64_t b128_expect[TEST_COUNT_TOTAL][2] = { + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 0 */ + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, }, + { 0x5555555555555555ULL, 0x5555555555555555ULL, }, + { 0xccccccccccccccccULL, 0xccccccccccccccccULL, }, + { 0x3333333333333333ULL, 0x3333333333333333ULL, }, + { 0xe38e38e38e38e38eULL, 0x38e38e38e38e38e3ULL, }, + { 0x1c71c71c71c71c71ULL, 0xc71c71c71c71c71cULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, /* 8 */ + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0xccccccccccccccccULL, 0xccccccccccccccccULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0xe38e38e38e38e38eULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0xc71c71c71c71c71cULL, }, + { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, }, /* 16 */ + { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, }, + { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, }, + { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, }, + { 0xccccccccccccccccULL, 0xccccccccccccccccULL, }, + { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, }, + { 0xe38e38e38e38e38eULL, 0xaaaaaaaaaaaaaaaaULL, }, + { 0xaaaaaaaaaaaaaaaaULL, 0xc71c71c71c71c71cULL, }, + { 0x5555555555555555ULL, 0x5555555555555555ULL, }, /* 24 */ + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, }, + { 0x5555555555555555ULL, 0x5555555555555555ULL, }, + { 0xccccccccccccccccULL, 0xccccccccccccccccULL, }, + { 0x3333333333333333ULL, 0x3333333333333333ULL, }, + { 0xe38e38e38e38e38eULL, 0x38e38e38e38e38e3ULL, }, + { 0x1c71c71c71c71c71ULL, 0xc71c71c71c71c71cULL, }, + { 0xccccccccccccccccULL, 0xccccccccccccccccULL, }, /* 32 */ + { 0xccccccccccccccccULL, 0xccccccccccccccccULL, }, + { 0xccccccccccccccccULL, 0xccccccccccccccccULL, }, + { 0xccccccccccccccccULL, 0xccccccccccccccccULL, }, + { 0xccccccccccccccccULL, 0xccccccccccccccccULL, }, + { 0xccccccccccccccccULL, 0xccccccccccccccccULL, }, + { 0xe38e38e38e38e38eULL, 0xccccccccccccccccULL, }, + { 0xccccccccccccccccULL, 0xccccccccccccccccULL, }, + { 0x3333333333333333ULL, 0x3333333333333333ULL, }, /* 40 */ + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, }, + { 0x3333333333333333ULL, 0x3333333333333333ULL, }, + { 0xccccccccccccccccULL, 0xccccccccccccccccULL, }, + { 0x3333333333333333ULL, 0x3333333333333333ULL, }, + { 0xe38e38e38e38e38eULL, 0x3333333333333333ULL, }, + { 0x1c71c71c71c71c71ULL, 0xc71c71c71c71c71cULL, }, + { 0xe38e38e38e38e38eULL, 0x38e38e38e38e38e3ULL, }, /* 48 */ + { 0xe38e38e38e38e38eULL, 0x0000000000000000ULL, }, + { 0xe38e38e38e38e38eULL, 0xaaaaaaaaaaaaaaaaULL, }, + { 0xe38e38e38e38e38eULL, 0x38e38e38e38e38e3ULL, }, + { 0xe38e38e38e38e38eULL, 0xccccccccccccccccULL, }, + { 0xe38e38e38e38e38eULL, 0x3333333333333333ULL, }, + { 0xe38e38e38e38e38eULL, 0x38e38e38e38e38e3ULL, }, + { 0xe38e38e38e38e38eULL, 0xc71c71c71c71c71cULL, }, + { 0x1c71c71c71c71c71ULL, 0xc71c71c71c71c71cULL, }, /* 56 */ + { 0x0000000000000000ULL, 0xc71c71c71c71c71cULL, }, + { 0xaaaaaaaaaaaaaaaaULL, 0xc71c71c71c71c71cULL, }, + { 0x1c71c71c71c71c71ULL, 0xc71c71c71c71c71cULL, }, + { 0xccccccccccccccccULL, 0xccccccccccccccccULL, }, + { 0x1c71c71c71c71c71ULL, 0xc71c71c71c71c71cULL, }, + { 0xe38e38e38e38e38eULL, 0xc71c71c71c71c71cULL, }, + { 0x1c71c71c71c71c71ULL, 0xc71c71c71c71c71cULL, }, + { 0x886ae6cc28625540ULL, 0x4b670b5efe7bb00cULL, }, /* 64 */ + { 0xfbbe00634d93c708ULL, 0x12f7bb1a153f52fcULL, }, + { 0xac5aaeaab9cf8b80ULL, 0x27d8c6ffab2b2514ULL, }, + { 0x886ae6cc28625540ULL, 0x8df188d8a942e2a0ULL, }, + { 0xfbbe00634d93c708ULL, 0x12f7bb1a153f52fcULL, }, + { 0xfbbe00634d93c708ULL, 0x12f7bb1a153f52fcULL, }, + { 0xfbbe00634d93c708ULL, 0x12f7bb1a153f52fcULL, }, + { 0xfbbe00634d93c708ULL, 0x8df188d8a942e2a0ULL, }, + { 0xac5aaeaab9cf8b80ULL, 0x27d8c6ffab2b2514ULL, }, /* 72 */ + { 0xfbbe00634d93c708ULL, 0x12f7bb1a153f52fcULL, }, + { 0xac5aaeaab9cf8b80ULL, 0x27d8c6ffab2b2514ULL, }, + { 0xac5aaeaab9cf8b80ULL, 0x8df188d8a942e2a0ULL, }, + { 0x886ae6cc28625540ULL, 0x8df188d8a942e2a0ULL, }, + { 0xfbbe00634d93c708ULL, 0x8df188d8a942e2a0ULL, }, + { 0xac5aaeaab9cf8b80ULL, 0x8df188d8a942e2a0ULL, }, + { 0x704f164d5e31e24eULL, 0x8df188d8a942e2a0ULL, }, +}; + + reset_msa_registers(); + + gettimeofday(&start, NULL); + + for (i = 0; i < PATTERN_INPUTS_SHORT_COUNT; i++) { + for (j = 0; j < PATTERN_INPUTS_SHORT_COUNT; j++) { + do_msa_FMIN_D(b128_pattern[i], b128_pattern[j], + b128_result[PATTERN_INPUTS_SHORT_COUNT * i + j]); + } + } + + for (i = 0; i < RANDOM_INPUTS_SHORT_COUNT; i++) { + for (j = 0; j < RANDOM_INPUTS_SHORT_COUNT; j++) { + do_msa_FMIN_D(b128_random[i], b128_random[j], + b128_result[((PATTERN_INPUTS_SHORT_COUNT) * + (PATTERN_INPUTS_SHORT_COUNT)) + + RANDOM_INPUTS_SHORT_COUNT * i + j]); + } + } + + gettimeofday(&end, NULL); + + elapsed_time = (end.tv_sec - start.tv_sec) * 1000.0; + elapsed_time += (end.tv_usec - start.tv_usec) / 1000.0; + + ret = check_results(instruction_name, TEST_COUNT_TOTAL, elapsed_time, + &b128_result[0][0], &b128_expect[0][0]); + + return ret; +} diff --git a/tests/tcg/mips/user/ase/msa/float-max-min/test_msa_fmin_w.c b/tests/tcg/mips/user/ase/msa/float-max-min/test_msa_fmin_w.c new file mode 100644 index 0000000000..c5815a66ab --- /dev/null +++ b/tests/tcg/mips/user/ase/msa/float-max-min/test_msa_fmin_w.c @@ -0,0 +1,155 @@ +/* + * Test program for MSA instruction FMIN.W + * + * Copyright (C) 2019 Wave Computing, Inc. + * Copyright (C) 2019 Aleksandar Markovic <amarkovic@wavecomp.com> + * + * This program 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, see <https://www.gnu.org/licenses/>. + * + */ + +#include <sys/time.h> +#include <stdint.h> + +#include "../../../../include/wrappers_msa.h" +#include "../../../../include/test_inputs_128.h" +#include "../../../../include/test_utils_128.h" + +#define TEST_COUNT_TOTAL ( \ + (PATTERN_INPUTS_SHORT_COUNT) * (PATTERN_INPUTS_SHORT_COUNT) + \ + (RANDOM_INPUTS_SHORT_COUNT) * (RANDOM_INPUTS_SHORT_COUNT)) + + +int32_t main(void) +{ + char *instruction_name = "FMIN.W"; + int32_t ret; + uint32_t i, j; + struct timeval start, end; + double elapsed_time; + + uint64_t b128_result[TEST_COUNT_TOTAL][2]; + uint64_t b128_expect[TEST_COUNT_TOTAL][2] = { + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 0 */ + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, }, + { 0x5555555555555555ULL, 0x5555555555555555ULL, }, + { 0xccccccccccccccccULL, 0xccccccccccccccccULL, }, + { 0x3333333333333333ULL, 0x3333333333333333ULL, }, + { 0xe38e38e38e38e38eULL, 0x38e38e38e38e38e3ULL, }, + { 0x1c71c71c71c71c71ULL, 0xc71c71c71c71c71cULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, /* 8 */ + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0xccccccccccccccccULL, 0xccccccccccccccccULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0xe38e38e38e38e38eULL, 0x00000000e38e38e3ULL, }, + { 0x0000000000000000ULL, 0xc71c71c700000000ULL, }, + { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, }, /* 16 */ + { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, }, + { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, }, + { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, }, + { 0xccccccccccccccccULL, 0xccccccccccccccccULL, }, + { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, }, + { 0xe38e38e3aaaaaaaaULL, 0xaaaaaaaae38e38e3ULL, }, + { 0xaaaaaaaaaaaaaaaaULL, 0xc71c71c7aaaaaaaaULL, }, + { 0x5555555555555555ULL, 0x5555555555555555ULL, }, /* 24 */ + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, }, + { 0x5555555555555555ULL, 0x5555555555555555ULL, }, + { 0xccccccccccccccccULL, 0xccccccccccccccccULL, }, + { 0x3333333333333333ULL, 0x3333333333333333ULL, }, + { 0xe38e38e38e38e38eULL, 0x38e38e38e38e38e3ULL, }, + { 0x1c71c71c55555555ULL, 0xc71c71c71c71c71cULL, }, + { 0xccccccccccccccccULL, 0xccccccccccccccccULL, }, /* 32 */ + { 0xccccccccccccccccULL, 0xccccccccccccccccULL, }, + { 0xccccccccccccccccULL, 0xccccccccccccccccULL, }, + { 0xccccccccccccccccULL, 0xccccccccccccccccULL, }, + { 0xccccccccccccccccULL, 0xccccccccccccccccULL, }, + { 0xccccccccccccccccULL, 0xccccccccccccccccULL, }, + { 0xe38e38e3ccccccccULL, 0xcccccccce38e38e3ULL, }, + { 0xccccccccccccccccULL, 0xccccccccccccccccULL, }, + { 0x3333333333333333ULL, 0x3333333333333333ULL, }, /* 40 */ + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, }, + { 0x3333333333333333ULL, 0x3333333333333333ULL, }, + { 0xccccccccccccccccULL, 0xccccccccccccccccULL, }, + { 0x3333333333333333ULL, 0x3333333333333333ULL, }, + { 0xe38e38e38e38e38eULL, 0x33333333e38e38e3ULL, }, + { 0x1c71c71c33333333ULL, 0xc71c71c71c71c71cULL, }, + { 0xe38e38e38e38e38eULL, 0x38e38e38e38e38e3ULL, }, /* 48 */ + { 0xe38e38e38e38e38eULL, 0x00000000e38e38e3ULL, }, + { 0xe38e38e3aaaaaaaaULL, 0xaaaaaaaae38e38e3ULL, }, + { 0xe38e38e38e38e38eULL, 0x38e38e38e38e38e3ULL, }, + { 0xe38e38e3ccccccccULL, 0xcccccccce38e38e3ULL, }, + { 0xe38e38e38e38e38eULL, 0x33333333e38e38e3ULL, }, + { 0xe38e38e38e38e38eULL, 0x38e38e38e38e38e3ULL, }, + { 0xe38e38e38e38e38eULL, 0xc71c71c7e38e38e3ULL, }, + { 0x1c71c71c71c71c71ULL, 0xc71c71c71c71c71cULL, }, /* 56 */ + { 0x0000000000000000ULL, 0xc71c71c700000000ULL, }, + { 0xaaaaaaaaaaaaaaaaULL, 0xc71c71c7aaaaaaaaULL, }, + { 0x1c71c71c55555555ULL, 0xc71c71c71c71c71cULL, }, + { 0xccccccccccccccccULL, 0xccccccccccccccccULL, }, + { 0x1c71c71c33333333ULL, 0xc71c71c71c71c71cULL, }, + { 0xe38e38e38e38e38eULL, 0xc71c71c7e38e38e3ULL, }, + { 0x1c71c71c71c71c71ULL, 0xc71c71c71c71c71cULL, }, + { 0x886ae6cc28625540ULL, 0x4b670b5efe7bb00cULL, }, /* 64 */ + { 0xfbbe006328625540ULL, 0x12f7bb1afe7bb00cULL, }, + { 0xac5aaeaab9cf8b80ULL, 0x27d8c6fffe7bb00cULL, }, + { 0x886ae6cc28625540ULL, 0x8df188d8fe7bb00cULL, }, + { 0xfbbe006328625540ULL, 0x12f7bb1afe7bb00cULL, }, + { 0xfbbe00634d93c708ULL, 0x12f7bb1a153f52fcULL, }, + { 0xfbbe0063b9cf8b80ULL, 0x12f7bb1aab2b2514ULL, }, + { 0xfbbe00634d93c708ULL, 0x8df188d8a942e2a0ULL, }, + { 0xac5aaeaab9cf8b80ULL, 0x27d8c6fffe7bb00cULL, }, /* 72 */ + { 0xfbbe0063b9cf8b80ULL, 0x12f7bb1aab2b2514ULL, }, + { 0xac5aaeaab9cf8b80ULL, 0x27d8c6ffab2b2514ULL, }, + { 0xac5aaeaab9cf8b80ULL, 0x8df188d8ab2b2514ULL, }, + { 0x886ae6cc28625540ULL, 0x8df188d8fe7bb00cULL, }, + { 0xfbbe00634d93c708ULL, 0x8df188d8a942e2a0ULL, }, + { 0xac5aaeaab9cf8b80ULL, 0x8df188d8ab2b2514ULL, }, + { 0x704f164d5e31e24eULL, 0x8df188d8a942e2a0ULL, }, +}; + + reset_msa_registers(); + + gettimeofday(&start, NULL); + + for (i = 0; i < PATTERN_INPUTS_SHORT_COUNT; i++) { + for (j = 0; j < PATTERN_INPUTS_SHORT_COUNT; j++) { + do_msa_FMIN_W(b128_pattern[i], b128_pattern[j], + b128_result[PATTERN_INPUTS_SHORT_COUNT * i + j]); + } + } + + for (i = 0; i < RANDOM_INPUTS_SHORT_COUNT; i++) { + for (j = 0; j < RANDOM_INPUTS_SHORT_COUNT; j++) { + do_msa_FMIN_W(b128_random[i], b128_random[j], + b128_result[((PATTERN_INPUTS_SHORT_COUNT) * + (PATTERN_INPUTS_SHORT_COUNT)) + + RANDOM_INPUTS_SHORT_COUNT * i + j]); + } + } + + gettimeofday(&end, NULL); + + elapsed_time = (end.tv_sec - start.tv_sec) * 1000.0; + elapsed_time += (end.tv_usec - start.tv_usec) / 1000.0; + + ret = check_results(instruction_name, TEST_COUNT_TOTAL, elapsed_time, + &b128_result[0][0], &b128_expect[0][0]); + + return ret; +} diff --git a/tests/tcg/mips/user/ase/msa/int-add/test_msa_add_a_b.c b/tests/tcg/mips/user/ase/msa/int-add/test_msa_add_a_b.c index d2ea54f43d..e96e4fdf72 100644 --- a/tests/tcg/mips/user/ase/msa/int-add/test_msa_add_a_b.c +++ b/tests/tcg/mips/user/ase/msa/int-add/test_msa_add_a_b.c @@ -1,6 +1,8 @@ /* * Test program for MSA instruction ADD_A.B * + * Copyright (C) 2019 Wave Computing, Inc. + * Copyright (C) 2019 Aleksandar Markovic <amarkovic@wavecomp.com> * Copyright (C) 2019 RT-RK Computer Based Systems LLC * Copyright (C) 2019 Mateja Marjanovic <mateja.marjanovic@rt-rk.com> * @@ -119,8 +121,12 @@ int32_t main(void) { 0xc4a968a3a56293ceULL, 0x9a37b229ac6d4374ULL, }, { 0xe8b930818693738eULL, 0xbe76838659bd6e6cULL, }, { 0x759116b0ab9e5756ULL, 0x8518bd426c817064ULL, }, + { 0xc4a968a3a56293ceULL, 0x9a37b229ac6d4374ULL, }, + { 0xe09e2c9abc623c9cULL, 0xe61ef050ae843cc0ULL, }, }; + reset_msa_registers(); + gettimeofday(&start, NULL); for (i = 0; i < PATTERN_INPUTS_SHORT_COUNT; i++) { diff --git a/tests/tcg/mips/user/ase/msa/int-add/test_msa_add_a_d.c b/tests/tcg/mips/user/ase/msa/int-add/test_msa_add_a_d.c index 56b81f9090..ec025b6210 100644 --- a/tests/tcg/mips/user/ase/msa/int-add/test_msa_add_a_d.c +++ b/tests/tcg/mips/user/ase/msa/int-add/test_msa_add_a_d.c @@ -1,6 +1,8 @@ /* * Test program for MSA instruction ADD_A.D * + * Copyright (C) 2019 Wave Computing, Inc. + * Copyright (C) 2019 Aleksandar Markovic <amarkovic@wavecomp.com> * Copyright (C) 2019 RT-RK Computer Based Systems LLC * Copyright (C) 2019 Mateja Marjanovic <mateja.marjanovic@rt-rk.com> * @@ -119,8 +121,12 @@ int32_t main(void) { 0xc3f467a2a46256ceULL, 0x99e73e2701e84274ULL, }, { 0xe7e42f8135cf8d0eULL, 0xbd7582865538cd6cULL, }, { 0x749115ea109e1b46ULL, 0x850632416bfc705cULL, }, + { 0xc3f467a2a46256ceULL, 0x99e73e2701e84274ULL, }, + { 0xe09e2c9abc63c49cULL, 0xe41cee4ead7a3ac0ULL, }, }; + reset_msa_registers(); + gettimeofday(&start, NULL); for (i = 0; i < PATTERN_INPUTS_SHORT_COUNT; i++) { diff --git a/tests/tcg/mips/user/ase/msa/int-add/test_msa_add_a_h.c b/tests/tcg/mips/user/ase/msa/int-add/test_msa_add_a_h.c index fe3c664997..d04b3a5abe 100644 --- a/tests/tcg/mips/user/ase/msa/int-add/test_msa_add_a_h.c +++ b/tests/tcg/mips/user/ase/msa/int-add/test_msa_add_a_h.c @@ -1,6 +1,8 @@ /* * Test program for MSA instruction ADD_A.H * + * Copyright (C) 2019 Wave Computing, Inc. + * Copyright (C) 2019 Aleksandar Markovic <amarkovic@wavecomp.com> * Copyright (C) 2019 RT-RK Computer Based Systems LLC * Copyright (C) 2019 Mateja Marjanovic <mateja.marjanovic@rt-rk.com> * @@ -119,8 +121,12 @@ int32_t main(void) { 0xc3f567a3a4629232ULL, 0x99e7b029ab934274ULL, }, { 0xe7e52f81869372f2ULL, 0xbd76828658436d54ULL, }, { 0x749116b0abc456aaULL, 0x8506bc0e6bfd705cULL, }, + { 0xc3f567a3a4629232ULL, 0x99e7b029ab934274ULL, }, + { 0xe09e2c9abc623b64ULL, 0xe41eee50ad7c3ac0ULL, }, }; + reset_msa_registers(); + gettimeofday(&start, NULL); for (i = 0; i < PATTERN_INPUTS_SHORT_COUNT; i++) { diff --git a/tests/tcg/mips/user/ase/msa/int-add/test_msa_add_a_w.c b/tests/tcg/mips/user/ase/msa/int-add/test_msa_add_a_w.c index 205117ea95..7ae90a3daf 100644 --- a/tests/tcg/mips/user/ase/msa/int-add/test_msa_add_a_w.c +++ b/tests/tcg/mips/user/ase/msa/int-add/test_msa_add_a_w.c @@ -1,6 +1,8 @@ /* * Test program for MSA instruction ADD_A.W * + * Copyright (C) 2019 Wave Computing, Inc. + * Copyright (C) 2019 Aleksandar Markovic <amarkovic@wavecomp.com> * Copyright (C) 2019 RT-RK Computer Based Systems LLC * Copyright (C) 2019 Mateja Marjanovic <mateja.marjanovic@rt-rk.com> * @@ -119,8 +121,12 @@ int32_t main(void) { 0xc3f467a3a46256ceULL, 0x99e73e27ab91f84cULL, }, { 0xe7e42f818694378eULL, 0xbd75828658416d54ULL, }, { 0x749115eaabc5a956ULL, 0x850632426bfc705cULL, }, + { 0xc3f467a3a46256ceULL, 0x99e73e27ab91f84cULL, }, + { 0xe09e2c9abc63c49cULL, 0xe41cee50ad7a3ac0ULL, }, }; + reset_msa_registers(); + gettimeofday(&start, NULL); for (i = 0; i < PATTERN_INPUTS_SHORT_COUNT; i++) { diff --git a/tests/tcg/mips/user/ase/msa/int-add/test_msa_adds_a_b.c b/tests/tcg/mips/user/ase/msa/int-add/test_msa_adds_a_b.c index 6939e91fe4..05712a1f05 100644 --- a/tests/tcg/mips/user/ase/msa/int-add/test_msa_adds_a_b.c +++ b/tests/tcg/mips/user/ase/msa/int-add/test_msa_adds_a_b.c @@ -1,6 +1,8 @@ /* * Test program for MSA instruction ADDS_A.B * + * Copyright (C) 2019 Wave Computing, Inc. + * Copyright (C) 2019 Aleksandar Markovic <amarkovic@wavecomp.com> * Copyright (C) 2019 RT-RK Computer Based Systems LLC * Copyright (C) 2019 Mateja Marjanovic <mateja.marjanovic@rt-rk.com> * @@ -119,8 +121,12 @@ int32_t main(void) { 0x7f7f687f7f627f7fULL, 0x7f377f297f6d4374ULL, }, { 0x7f7f307f7f7f737fULL, 0x7f767f7f597f6e6cULL, }, { 0x757f167f7f7f5756ULL, 0x7f187f426c7f7064ULL, }, + { 0x7f7f687f7f627f7fULL, 0x7f377f297f6d4374ULL, }, + { 0x7f7f2c7f7f623c7fULL, 0x7f1e7f507f7f3c7fULL, }, }; + reset_msa_registers(); + gettimeofday(&start, NULL); for (i = 0; i < PATTERN_INPUTS_SHORT_COUNT; i++) { diff --git a/tests/tcg/mips/user/ase/msa/int-add/test_msa_adds_a_d.c b/tests/tcg/mips/user/ase/msa/int-add/test_msa_adds_a_d.c index af0f3d3700..c222a9529f 100644 --- a/tests/tcg/mips/user/ase/msa/int-add/test_msa_adds_a_d.c +++ b/tests/tcg/mips/user/ase/msa/int-add/test_msa_adds_a_d.c @@ -1,6 +1,8 @@ /* * Test program for MSA instruction ADDS_A.D * + * Copyright (C) 2019 Wave Computing, Inc. + * Copyright (C) 2019 Aleksandar Markovic <amarkovic@wavecomp.com> * Copyright (C) 2019 RT-RK Computer Based Systems LLC * Copyright (C) 2019 Mateja Marjanovic <mateja.marjanovic@rt-rk.com> * @@ -119,8 +121,12 @@ int32_t main(void) { 0x7fffffffffffffffULL, 0x7fffffffffffffffULL, }, { 0x7fffffffffffffffULL, 0x7fffffffffffffffULL, }, { 0x749115ea109e1b46ULL, 0x7fffffffffffffffULL, }, + { 0x7fffffffffffffffULL, 0x7fffffffffffffffULL, }, + { 0x7fffffffffffffffULL, 0x7fffffffffffffffULL, }, }; + reset_msa_registers(); + gettimeofday(&start, NULL); for (i = 0; i < PATTERN_INPUTS_SHORT_COUNT; i++) { diff --git a/tests/tcg/mips/user/ase/msa/int-add/test_msa_adds_a_h.c b/tests/tcg/mips/user/ase/msa/int-add/test_msa_adds_a_h.c index 4d3774fef2..0348f8ca47 100644 --- a/tests/tcg/mips/user/ase/msa/int-add/test_msa_adds_a_h.c +++ b/tests/tcg/mips/user/ase/msa/int-add/test_msa_adds_a_h.c @@ -1,6 +1,8 @@ /* * Test program for MSA instruction ADDS_A.H * + * Copyright (C) 2019 Wave Computing, Inc. + * Copyright (C) 2019 Aleksandar Markovic <amarkovic@wavecomp.com> * Copyright (C) 2019 RT-RK Computer Based Systems LLC * Copyright (C) 2019 Mateja Marjanovic <mateja.marjanovic@rt-rk.com> * @@ -119,8 +121,12 @@ int32_t main(void) { 0x7fff67a37fff7fffULL, 0x7fff7fff7fff4274ULL, }, { 0x7fff2f817fff72f2ULL, 0x7fff7fff58436d54ULL, }, { 0x749116b07fff56aaULL, 0x7fff7fff6bfd705cULL, }, + { 0x7fff67a37fff7fffULL, 0x7fff7fff7fff4274ULL, }, + { 0x7fff2c9a7fff3b64ULL, 0x7fff7fff7fff3ac0ULL, }, }; + reset_msa_registers(); + gettimeofday(&start, NULL); for (i = 0; i < PATTERN_INPUTS_SHORT_COUNT; i++) { diff --git a/tests/tcg/mips/user/ase/msa/int-add/test_msa_adds_a_w.c b/tests/tcg/mips/user/ase/msa/int-add/test_msa_adds_a_w.c index 6f06fdc7cd..9ad9c569f8 100644 --- a/tests/tcg/mips/user/ase/msa/int-add/test_msa_adds_a_w.c +++ b/tests/tcg/mips/user/ase/msa/int-add/test_msa_adds_a_w.c @@ -1,6 +1,8 @@ /* * Test program for MSA instruction ADDS_A.W * + * Copyright (C) 2019 Wave Computing, Inc. + * Copyright (C) 2019 Aleksandar Markovic <amarkovic@wavecomp.com> * Copyright (C) 2019 RT-RK Computer Based Systems LLC * Copyright (C) 2019 Mateja Marjanovic <mateja.marjanovic@rt-rk.com> * @@ -119,8 +121,12 @@ int32_t main(void) { 0x7fffffff7fffffffULL, 0x7fffffff7fffffffULL, }, { 0x7fffffff7fffffffULL, 0x7fffffff58416d54ULL, }, { 0x749115ea7fffffffULL, 0x7fffffff6bfc705cULL, }, + { 0x7fffffff7fffffffULL, 0x7fffffff7fffffffULL, }, + { 0x7fffffff7fffffffULL, 0x7fffffff7fffffffULL, }, }; + reset_msa_registers(); + gettimeofday(&start, NULL); for (i = 0; i < PATTERN_INPUTS_SHORT_COUNT; i++) { diff --git a/tests/tcg/mips/user/ase/msa/int-add/test_msa_adds_s_b.c b/tests/tcg/mips/user/ase/msa/int-add/test_msa_adds_s_b.c index e6cb9871f5..a7f4de9260 100644 --- a/tests/tcg/mips/user/ase/msa/int-add/test_msa_adds_s_b.c +++ b/tests/tcg/mips/user/ase/msa/int-add/test_msa_adds_s_b.c @@ -1,6 +1,8 @@ /* * Test program for MSA instruction ADDS_S.B * + * Copyright (C) 2019 Wave Computing, Inc. + * Copyright (C) 2019 Aleksandar Markovic <amarkovic@wavecomp.com> * Copyright (C) 2019 RT-RK Computer Based Systems LLC * Copyright (C) 2019 Mateja Marjanovic <mateja.marjanovic@rt-rk.com> * @@ -119,8 +121,12 @@ int32_t main(void) { 0x1c7fc4f7170080ceULL, 0xb4c980d7806d07b4ULL, }, { 0xf87ffc197f7f377fULL, 0xd8589336a77f92acULL, }, { 0x6b0d167f7fc4a956ULL, 0x9fe880f2be7f349cULL, }, + { 0x1c7fc4f7170080ceULL, 0xb4c980d7806d07b4ULL, }, + { 0x7f7f2c7f7f62c47fULL, 0x80e280b0807fc480ULL, }, }; + reset_msa_registers(); + gettimeofday(&start, NULL); for (i = 0; i < PATTERN_INPUTS_SHORT_COUNT; i++) { diff --git a/tests/tcg/mips/user/ase/msa/int-add/test_msa_adds_s_d.c b/tests/tcg/mips/user/ase/msa/int-add/test_msa_adds_s_d.c index 2cda5d9661..d1048fcdd5 100644 --- a/tests/tcg/mips/user/ase/msa/int-add/test_msa_adds_s_d.c +++ b/tests/tcg/mips/user/ase/msa/int-add/test_msa_adds_s_d.c @@ -1,6 +1,8 @@ /* * Test program for MSA instruction ADDS_S.D * + * Copyright (C) 2019 Wave Computing, Inc. + * Copyright (C) 2019 Aleksandar Markovic <amarkovic@wavecomp.com> * Copyright (C) 2019 RT-RK Computer Based Systems LLC * Copyright (C) 2019 Mateja Marjanovic <mateja.marjanovic@rt-rk.com> * @@ -119,8 +121,12 @@ int32_t main(void) { 0x1ca9c4f818016dceULL, 0xb5ca4fd8546e07b4ULL, }, { 0xf8b9fd198694378eULL, 0xd9589437a7be92acULL, }, { 0x6c0d16b0abc5a956ULL, 0xa0e943f2be82359cULL, }, + { 0x1ca9c4f818016dceULL, 0xb5ca4fd8546e07b4ULL, }, + { 0x7fffffffffffffffULL, 0x8000000000000000ULL, }, }; + reset_msa_registers(); + gettimeofday(&start, NULL); for (i = 0; i < PATTERN_INPUTS_SHORT_COUNT; i++) { diff --git a/tests/tcg/mips/user/ase/msa/int-add/test_msa_adds_s_h.c b/tests/tcg/mips/user/ase/msa/int-add/test_msa_adds_s_h.c index 5539322423..6263616a63 100644 --- a/tests/tcg/mips/user/ase/msa/int-add/test_msa_adds_s_h.c +++ b/tests/tcg/mips/user/ase/msa/int-add/test_msa_adds_s_h.c @@ -1,6 +1,8 @@ /* * Test program for MSA instruction ADDS_S.H * + * Copyright (C) 2019 Wave Computing, Inc. + * Copyright (C) 2019 Aleksandar Markovic <amarkovic@wavecomp.com> * Copyright (C) 2019 RT-RK Computer Based Systems LLC * Copyright (C) 2019 Mateja Marjanovic <mateja.marjanovic@rt-rk.com> * @@ -119,8 +121,12 @@ int32_t main(void) { 0x1ca9c4f718008000ULL, 0xb5c98000800007b4ULL, }, { 0xf8b9fd197fff378eULL, 0xd9589436a7bd92acULL, }, { 0x6c0d16b07fffa956ULL, 0xa0e88000be81359cULL, }, + { 0x1ca9c4f718008000ULL, 0xb5c98000800007b4ULL, }, + { 0x7fff2c9a7fffc49cULL, 0x800080008000c540ULL, }, }; + reset_msa_registers(); + gettimeofday(&start, NULL); for (i = 0; i < PATTERN_INPUTS_SHORT_COUNT; i++) { diff --git a/tests/tcg/mips/user/ase/msa/int-add/test_msa_adds_s_w.c b/tests/tcg/mips/user/ase/msa/int-add/test_msa_adds_s_w.c index 4f2cc3862e..80b69f70cc 100644 --- a/tests/tcg/mips/user/ase/msa/int-add/test_msa_adds_s_w.c +++ b/tests/tcg/mips/user/ase/msa/int-add/test_msa_adds_s_w.c @@ -1,6 +1,8 @@ /* * Test program for MSA instruction ADDS_S.W * + * Copyright (C) 2019 Wave Computing, Inc. + * Copyright (C) 2019 Aleksandar Markovic <amarkovic@wavecomp.com> * Copyright (C) 2019 RT-RK Computer Based Systems LLC * Copyright (C) 2019 Mateja Marjanovic <mateja.marjanovic@rt-rk.com> * @@ -119,8 +121,12 @@ int32_t main(void) { 0x1ca9c4f718016dceULL, 0xb5ca4fd780000000ULL, }, { 0xf8b9fd197fffffffULL, 0xd9589436a7be92acULL, }, { 0x6c0d16b07fffffffULL, 0xa0e943f2be82359cULL, }, + { 0x1ca9c4f718016dceULL, 0xb5ca4fd780000000ULL, }, + { 0x7fffffff7fffffffULL, 0x8000000080000000ULL, }, }; + reset_msa_registers(); + gettimeofday(&start, NULL); for (i = 0; i < PATTERN_INPUTS_SHORT_COUNT; i++) { diff --git a/tests/tcg/mips/user/ase/msa/int-add/test_msa_adds_u_b.c b/tests/tcg/mips/user/ase/msa/int-add/test_msa_adds_u_b.c index e2d9be38e7..d61623fec5 100644 --- a/tests/tcg/mips/user/ase/msa/int-add/test_msa_adds_u_b.c +++ b/tests/tcg/mips/user/ase/msa/int-add/test_msa_adds_u_b.c @@ -1,6 +1,8 @@ /* * Test program for MSA instruction ADDS_U.B * + * Copyright (C) 2019 Wave Computing, Inc. + * Copyright (C) 2019 Aleksandar Markovic <amarkovic@wavecomp.com> * Copyright (C) 2019 RT-RK Computer Based Systems LLC * Copyright (C) 2019 Mateja Marjanovic <mateja.marjanovic@rt-rk.com> * @@ -119,8 +121,12 @@ int32_t main(void) { 0xffa9c4f7ffffffceULL, 0xb4ffffffff6dffb4ULL, }, { 0xf8b9fcff8693ff8eULL, 0xd8ff93ffffbdffacULL, }, { 0xffff16b0abc4ff56ULL, 0x9ffffff2be81ffffULL, }, + { 0xffa9c4f7ffffffceULL, 0xb4ffffffff6dffb4ULL, }, + { 0xe09e2c9abc62ff9cULL, 0xffffffffff84ffffULL, }, }; + reset_msa_registers(); + gettimeofday(&start, NULL); for (i = 0; i < PATTERN_INPUTS_SHORT_COUNT; i++) { diff --git a/tests/tcg/mips/user/ase/msa/int-add/test_msa_adds_u_d.c b/tests/tcg/mips/user/ase/msa/int-add/test_msa_adds_u_d.c index 8418c636b6..7b60457f1d 100644 --- a/tests/tcg/mips/user/ase/msa/int-add/test_msa_adds_u_d.c +++ b/tests/tcg/mips/user/ase/msa/int-add/test_msa_adds_u_d.c @@ -1,6 +1,8 @@ /* * Test program for MSA instruction ADDS_U.D * + * Copyright (C) 2019 Wave Computing, Inc. + * Copyright (C) 2019 Aleksandar Markovic <amarkovic@wavecomp.com> * Copyright (C) 2019 RT-RK Computer Based Systems LLC * Copyright (C) 2019 Mateja Marjanovic <mateja.marjanovic@rt-rk.com> * @@ -119,8 +121,12 @@ int32_t main(void) { 0xffffffffffffffffULL, 0xb5ca4fd8546e07b4ULL, }, { 0xf8b9fd198694378eULL, 0xd9589437a7be92acULL, }, { 0xffffffffffffffffULL, 0xa0e943f2be82359cULL, }, + { 0xffffffffffffffffULL, 0xb5ca4fd8546e07b4ULL, }, + { 0xe09e2c9abc63c49cULL, 0xffffffffffffffffULL, }, }; + reset_msa_registers(); + gettimeofday(&start, NULL); for (i = 0; i < PATTERN_INPUTS_SHORT_COUNT; i++) { diff --git a/tests/tcg/mips/user/ase/msa/int-add/test_msa_adds_u_h.c b/tests/tcg/mips/user/ase/msa/int-add/test_msa_adds_u_h.c index 8a3b5c5cf5..c8b226228c 100644 --- a/tests/tcg/mips/user/ase/msa/int-add/test_msa_adds_u_h.c +++ b/tests/tcg/mips/user/ase/msa/int-add/test_msa_adds_u_h.c @@ -1,6 +1,8 @@ /* * Test program for MSA instruction ADDS_U.H * + * Copyright (C) 2019 Wave Computing, Inc. + * Copyright (C) 2019 Aleksandar Markovic <amarkovic@wavecomp.com> * Copyright (C) 2019 RT-RK Computer Based Systems LLC * Copyright (C) 2019 Mateja Marjanovic <mateja.marjanovic@rt-rk.com> * @@ -119,8 +121,12 @@ int32_t main(void) { 0xffffc4f7ffffffffULL, 0xb5c9ffffffffffffULL, }, { 0xf8b9fd198693ffffULL, 0xd9589436ffffffffULL, }, { 0xffff16b0abc4ffffULL, 0xa0e8ffffbe81ffffULL, }, + { 0xffffc4f7ffffffffULL, 0xb5c9ffffffffffffULL, }, + { 0xe09e2c9abc62ffffULL, 0xffffffffffffffffULL, }, }; + reset_msa_registers(); + gettimeofday(&start, NULL); for (i = 0; i < PATTERN_INPUTS_SHORT_COUNT; i++) { diff --git a/tests/tcg/mips/user/ase/msa/int-add/test_msa_adds_u_w.c b/tests/tcg/mips/user/ase/msa/int-add/test_msa_adds_u_w.c index b18bdc3ea0..7880b03383 100644 --- a/tests/tcg/mips/user/ase/msa/int-add/test_msa_adds_u_w.c +++ b/tests/tcg/mips/user/ase/msa/int-add/test_msa_adds_u_w.c @@ -1,6 +1,8 @@ /* * Test program for MSA instruction ADDS_U.W * + * Copyright (C) 2019 Wave Computing, Inc. + * Copyright (C) 2019 Aleksandar Markovic <amarkovic@wavecomp.com> * Copyright (C) 2019 RT-RK Computer Based Systems LLC * Copyright (C) 2019 Mateja Marjanovic <mateja.marjanovic@rt-rk.com> * @@ -119,8 +121,12 @@ int32_t main(void) { 0xffffffffffffffffULL, 0xb5ca4fd7ffffffffULL, }, { 0xf8b9fd198694378eULL, 0xd9589436ffffffffULL, }, { 0xffffffffabc5a956ULL, 0xa0e943f2be82359cULL, }, + { 0xffffffffffffffffULL, 0xb5ca4fd7ffffffffULL, }, + { 0xe09e2c9abc63c49cULL, 0xffffffffffffffffULL, }, }; + reset_msa_registers(); + gettimeofday(&start, NULL); for (i = 0; i < PATTERN_INPUTS_SHORT_COUNT; i++) { diff --git a/tests/tcg/mips/user/ase/msa/int-add/test_msa_addv_b.c b/tests/tcg/mips/user/ase/msa/int-add/test_msa_addv_b.c index c86c99291e..dbfcd3800a 100644 --- a/tests/tcg/mips/user/ase/msa/int-add/test_msa_addv_b.c +++ b/tests/tcg/mips/user/ase/msa/int-add/test_msa_addv_b.c @@ -1,6 +1,8 @@ /* * Test program for MSA instruction ADDV.B * + * Copyright (C) 2019 Wave Computing, Inc. + * Copyright (C) 2019 Aleksandar Markovic <amarkovic@wavecomp.com> * Copyright (C) 2019 RT-RK Computer Based Systems LLC * Copyright (C) 2019 Mateja Marjanovic <mateja.marjanovic@rt-rk.com> * @@ -119,8 +121,12 @@ int32_t main(void) { 0x1ca9c4f717006dceULL, 0xb4c94ed7546d07b4ULL, }, { 0xf8b9fc198693378eULL, 0xd8589336a7bd92acULL, }, { 0x6b0d16b0abc4a956ULL, 0x9fe843f2be81349cULL, }, + { 0x1ca9c4f717006dceULL, 0xb4c94ed7546d07b4ULL, }, + { 0xe09e2c9abc62c49cULL, 0x1ae210b05284c440ULL, }, }; + reset_msa_registers(); + gettimeofday(&start, NULL); for (i = 0; i < PATTERN_INPUTS_SHORT_COUNT; i++) { diff --git a/tests/tcg/mips/user/ase/msa/int-add/test_msa_addv_d.c b/tests/tcg/mips/user/ase/msa/int-add/test_msa_addv_d.c index 0f301515b3..27b6d65686 100644 --- a/tests/tcg/mips/user/ase/msa/int-add/test_msa_addv_d.c +++ b/tests/tcg/mips/user/ase/msa/int-add/test_msa_addv_d.c @@ -1,6 +1,8 @@ /* * Test program for MSA instruction ADDV.D * + * Copyright (C) 2019 Wave Computing, Inc. + * Copyright (C) 2019 Aleksandar Markovic <amarkovic@wavecomp.com> * Copyright (C) 2019 RT-RK Computer Based Systems LLC * Copyright (C) 2019 Mateja Marjanovic <mateja.marjanovic@rt-rk.com> * @@ -119,8 +121,12 @@ int32_t main(void) { 0x1ca9c4f818016dceULL, 0xb5ca4fd8546e07b4ULL, }, { 0xf8b9fd198694378eULL, 0xd9589437a7be92acULL, }, { 0x6c0d16b0abc5a956ULL, 0xa0e943f2be82359cULL, }, + { 0x1ca9c4f818016dceULL, 0xb5ca4fd8546e07b4ULL, }, + { 0xe09e2c9abc63c49cULL, 0x1be311b15285c540ULL, }, }; + reset_msa_registers(); + gettimeofday(&start, NULL); for (i = 0; i < PATTERN_INPUTS_SHORT_COUNT; i++) { diff --git a/tests/tcg/mips/user/ase/msa/int-add/test_msa_addv_h.c b/tests/tcg/mips/user/ase/msa/int-add/test_msa_addv_h.c index c6b4cf697b..f7045f6151 100644 --- a/tests/tcg/mips/user/ase/msa/int-add/test_msa_addv_h.c +++ b/tests/tcg/mips/user/ase/msa/int-add/test_msa_addv_h.c @@ -1,6 +1,8 @@ /* * Test program for MSA instruction ADDV.H * + * Copyright (C) 2019 Wave Computing, Inc. + * Copyright (C) 2019 Aleksandar Markovic <amarkovic@wavecomp.com> * Copyright (C) 2019 RT-RK Computer Based Systems LLC * Copyright (C) 2019 Mateja Marjanovic <mateja.marjanovic@rt-rk.com> * @@ -119,8 +121,12 @@ int32_t main(void) { 0x1ca9c4f718006dceULL, 0xb5c94fd7546d07b4ULL, }, { 0xf8b9fd198693378eULL, 0xd9589436a7bd92acULL, }, { 0x6c0d16b0abc4a956ULL, 0xa0e843f2be81359cULL, }, + { 0x1ca9c4f718006dceULL, 0xb5c94fd7546d07b4ULL, }, + { 0xe09e2c9abc62c49cULL, 0x1be211b05284c540ULL, }, }; + reset_msa_registers(); + gettimeofday(&start, NULL); for (i = 0; i < PATTERN_INPUTS_SHORT_COUNT; i++) { diff --git a/tests/tcg/mips/user/ase/msa/int-add/test_msa_addv_w.c b/tests/tcg/mips/user/ase/msa/int-add/test_msa_addv_w.c index 2a565e8ed4..111e7c89e8 100644 --- a/tests/tcg/mips/user/ase/msa/int-add/test_msa_addv_w.c +++ b/tests/tcg/mips/user/ase/msa/int-add/test_msa_addv_w.c @@ -1,6 +1,8 @@ /* * Test program for MSA instruction ADDV.W * + * Copyright (C) 2019 Wave Computing, Inc. + * Copyright (C) 2019 Aleksandar Markovic <amarkovic@wavecomp.com> * Copyright (C) 2019 RT-RK Computer Based Systems LLC * Copyright (C) 2019 Mateja Marjanovic <mateja.marjanovic@rt-rk.com> * @@ -119,8 +121,12 @@ int32_t main(void) { 0x1ca9c4f718016dceULL, 0xb5ca4fd7546e07b4ULL, }, { 0xf8b9fd198694378eULL, 0xd9589436a7be92acULL, }, { 0x6c0d16b0abc5a956ULL, 0xa0e943f2be82359cULL, }, + { 0x1ca9c4f718016dceULL, 0xb5ca4fd7546e07b4ULL, }, + { 0xe09e2c9abc63c49cULL, 0x1be311b05285c540ULL, }, }; + reset_msa_registers(); + gettimeofday(&start, NULL); for (i = 0; i < PATTERN_INPUTS_SHORT_COUNT; i++) { diff --git a/tests/tcg/mips/user/ase/msa/int-add/test_msa_hadd_s_d.c b/tests/tcg/mips/user/ase/msa/int-add/test_msa_hadd_s_d.c index 7845dc0218..e6dffbf21f 100644 --- a/tests/tcg/mips/user/ase/msa/int-add/test_msa_hadd_s_d.c +++ b/tests/tcg/mips/user/ase/msa/int-add/test_msa_hadd_s_d.c @@ -1,6 +1,8 @@ /* * Test program for MSA instruction HADD_S.D * + * Copyright (C) 2019 Wave Computing, Inc. + * Copyright (C) 2019 Aleksandar Markovic <amarkovic@wavecomp.com> * Copyright (C) 2019 RT-RK Computer Based Systems LLC * Copyright (C) 2019 Mateja Marjanovic <mateja.marjanovic@rt-rk.com> * @@ -119,8 +121,12 @@ int32_t main(void) { 0x000000000a8c90f8ULL, 0xffffffffd11ba99fULL, }, { 0x0000000098b16b8dULL, 0xffffffff8c6d38e4ULL, }, { 0x00000000bde2dd55ULL, 0xffffffffa330dbd4ULL, }, + { 0x000000002a1ea1cdULL, 0xffffffff391cadecULL, }, + { 0x00000000ce80f89bULL, 0xffffffff37346b78ULL, }, }; + reset_msa_registers(); + gettimeofday(&start, NULL); for (i = 0; i < PATTERN_INPUTS_SHORT_COUNT; i++) { diff --git a/tests/tcg/mips/user/ase/msa/int-add/test_msa_hadd_s_h.c b/tests/tcg/mips/user/ase/msa/int-add/test_msa_hadd_s_h.c index ddc2de3ff2..211123aa9d 100644 --- a/tests/tcg/mips/user/ase/msa/int-add/test_msa_hadd_s_h.c +++ b/tests/tcg/mips/user/ase/msa/int-add/test_msa_hadd_s_h.c @@ -1,6 +1,8 @@ /* * Test program for MSA instruction HADD_S.H * + * Copyright (C) 2019 Wave Computing, Inc. + * Copyright (C) 2019 Aleksandar Markovic <amarkovic@wavecomp.com> * Copyright (C) 2019 RT-RK Computer Based Systems LLC * Copyright (C) 2019 Mateja Marjanovic <mateja.marjanovic@rt-rk.com> * @@ -119,8 +121,12 @@ int32_t main(void) { 0xfffbfffbffeaffd9ULL, 0x0018ff9effedffc5ULL, }, { 0x00daffe200c00022ULL, 0xfff4ffe60024ffeeULL, }, { 0x002e0079fff1ffeaULL, 0xff84ffa2ffe8ffdeULL, }, + { 0x00caffc0002dff62ULL, 0xff65ff87ffd4fff6ULL, }, + { 0x00bf0063008f0030ULL, 0xff7eff60ffebff82ULL, }, }; + reset_msa_registers(); + gettimeofday(&start, NULL); for (i = 0; i < PATTERN_INPUTS_SHORT_COUNT; i++) { diff --git a/tests/tcg/mips/user/ase/msa/int-add/test_msa_hadd_s_w.c b/tests/tcg/mips/user/ase/msa/int-add/test_msa_hadd_s_w.c index 887cd1cd5c..cdab49d7dc 100644 --- a/tests/tcg/mips/user/ase/msa/int-add/test_msa_hadd_s_w.c +++ b/tests/tcg/mips/user/ase/msa/int-add/test_msa_hadd_s_w.c @@ -1,6 +1,8 @@ /* * Test program for MSA instruction HADD_S.W * + * Copyright (C) 2019 Wave Computing, Inc. + * Copyright (C) 2019 Aleksandar Markovic <amarkovic@wavecomp.com> * Copyright (C) 2019 RT-RK Computer Based Systems LLC * Copyright (C) 2019 Mateja Marjanovic <mateja.marjanovic@rt-rk.com> * @@ -119,8 +121,12 @@ int32_t main(void) { 0xffffc2a7ffff9c1dULL, 0xffffb0b0ffff8dcbULL, }, { 0x0000571b0000b371ULL, 0xffff994fffff594eULL, }, { 0x000070b200002539ULL, 0xffff490bfffffc3eULL, }, + { 0x00001ef9ffffe9b1ULL, 0xffff54f0ffffce56ULL, }, + { 0x0000869c0000407fULL, 0xffff16c9ffff8be2ULL, }, }; + reset_msa_registers(); + gettimeofday(&start, NULL); for (i = 0; i < PATTERN_INPUTS_SHORT_COUNT; i++) { diff --git a/tests/tcg/mips/user/ase/msa/int-add/test_msa_hadd_u_d.c b/tests/tcg/mips/user/ase/msa/int-add/test_msa_hadd_u_d.c index f0710f15de..38c43cedf7 100644 --- a/tests/tcg/mips/user/ase/msa/int-add/test_msa_hadd_u_d.c +++ b/tests/tcg/mips/user/ase/msa/int-add/test_msa_hadd_u_d.c @@ -1,6 +1,8 @@ /* * Test program for MSA instruction HADD_U.D * + * Copyright (C) 2019 Wave Computing, Inc. + * Copyright (C) 2019 Aleksandar Markovic <amarkovic@wavecomp.com> * Copyright (C) 2019 RT-RK Computer Based Systems LLC * Copyright (C) 2019 Mateja Marjanovic <mateja.marjanovic@rt-rk.com> * @@ -119,8 +121,12 @@ int32_t main(void) { 0x000000010a8c90f8ULL, 0x00000000d11ba99fULL, }, { 0x0000000098b16b8dULL, 0x000000018c6d38e4ULL, }, { 0x00000000bde2dd55ULL, 0x00000000a330dbd4ULL, }, + { 0x000000012a1ea1cdULL, 0x00000001391cadecULL, }, + { 0x00000000ce80f89bULL, 0x0000000137346b78ULL, }, }; + reset_msa_registers(); + gettimeofday(&start, NULL); for (i = 0; i < PATTERN_INPUTS_SHORT_COUNT; i++) { diff --git a/tests/tcg/mips/user/ase/msa/int-add/test_msa_hadd_u_h.c b/tests/tcg/mips/user/ase/msa/int-add/test_msa_hadd_u_h.c index fe55d3eaee..41863f6cf8 100644 --- a/tests/tcg/mips/user/ase/msa/int-add/test_msa_hadd_u_h.c +++ b/tests/tcg/mips/user/ase/msa/int-add/test_msa_hadd_u_h.c @@ -1,6 +1,8 @@ /* * Test program for MSA instruction HADD_U.H * + * Copyright (C) 2019 Wave Computing, Inc. + * Copyright (C) 2019 Aleksandar Markovic <amarkovic@wavecomp.com> * Copyright (C) 2019 RT-RK Computer Based Systems LLC * Copyright (C) 2019 Mateja Marjanovic <mateja.marjanovic@rt-rk.com> * @@ -119,8 +121,12 @@ int32_t main(void) { 0x00fb00fb00ea00d9ULL, 0x0118019e00ed00c5ULL, }, { 0x00da00e200c00122ULL, 0x00f400e6012400eeULL, }, { 0x012e007900f100eaULL, 0x018400a200e801deULL, }, + { 0x00ca00c0012d0162ULL, 0x0165018700d400f6ULL, }, + { 0x00bf0063008f0130ULL, 0x017e016000eb0182ULL, }, }; + reset_msa_registers(); + gettimeofday(&start, NULL); for (i = 0; i < PATTERN_INPUTS_SHORT_COUNT; i++) { diff --git a/tests/tcg/mips/user/ase/msa/int-add/test_msa_hadd_u_w.c b/tests/tcg/mips/user/ase/msa/int-add/test_msa_hadd_u_w.c index babe04d586..c30c2663fc 100644 --- a/tests/tcg/mips/user/ase/msa/int-add/test_msa_hadd_u_w.c +++ b/tests/tcg/mips/user/ase/msa/int-add/test_msa_hadd_u_w.c @@ -1,6 +1,8 @@ /* * Test program for MSA instruction HADD_U.W * + * Copyright (C) 2019 Wave Computing, Inc. + * Copyright (C) 2019 Aleksandar Markovic <amarkovic@wavecomp.com> * Copyright (C) 2019 RT-RK Computer Based Systems LLC * Copyright (C) 2019 Mateja Marjanovic <mateja.marjanovic@rt-rk.com> * @@ -119,8 +121,12 @@ int32_t main(void) { 0x0000c2a700019c1dULL, 0x0000b0b000018dcbULL, }, { 0x0001571b0000b371ULL, 0x0000994f0001594eULL, }, { 0x000070b200012539ULL, 0x0001490b0000fc3eULL, }, + { 0x00011ef90000e9b1ULL, 0x000154f00000ce56ULL, }, + { 0x0000869c0001407fULL, 0x000116c900018be2ULL, }, }; + reset_msa_registers(); + gettimeofday(&start, NULL); for (i = 0; i < PATTERN_INPUTS_SHORT_COUNT; i++) { diff --git a/tests/tcg/mips/user/ase/msa/int-average/test_msa_ave_s_b.c b/tests/tcg/mips/user/ase/msa/int-average/test_msa_ave_s_b.c index 675fb90c72..bb73fca1a3 100644 --- a/tests/tcg/mips/user/ase/msa/int-average/test_msa_ave_s_b.c +++ b/tests/tcg/mips/user/ase/msa/int-average/test_msa_ave_s_b.c @@ -1,8 +1,10 @@ /* * Test program for MSA instruction AVE_S.B * - * Copyright (C) 2018 Wave Computing, Inc. - * Copyright (C) 2018 Mateja Marjanovic <mateja.marjanovic@rt-rk.com> + * Copyright (C) 2019 Wave Computing, Inc. + * Copyright (C) 2019 Aleksandar Markovic <amarkovic@wavecomp.com> + * Copyright (C) 2019 RT-RK Computer Based Systems LLC + * Copyright (C) 2019 Mateja Marjanovic <mateja.marjanovic@rt-rk.com> * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -23,8 +25,8 @@ #include <stdint.h> #include "../../../../include/wrappers_msa.h" -#include "../../../../include/test_inputs.h" -#include "../../../../include/test_utils.h" +#include "../../../../include/test_inputs_128.h" +#include "../../../../include/test_utils_128.h" #define TEST_COUNT_TOTAL ( \ (PATTERN_INPUTS_SHORT_COUNT) * (PATTERN_INPUTS_SHORT_COUNT) + \ @@ -119,8 +121,12 @@ int32_t main(void) { 0x0e54e2fb0b00b6e7ULL, 0xdae4a7ebaa3603daULL, }, { 0xfc5cfe0c43491b47ULL, 0xec2cc91bd35ec9d6ULL, }, { 0x35060b5855e2d42bULL, 0xcff4a1f9df401aceULL, }, + { 0x0e54e2fb0b00b6e7ULL, 0xdae4a7ebaa3603daULL, }, + { 0x704f164d5e31e24eULL, 0x8df188d8a942e2a0ULL, }, }; + reset_msa_registers(); + gettimeofday(&start, NULL); for (i = 0; i < PATTERN_INPUTS_SHORT_COUNT; i++) { diff --git a/tests/tcg/mips/user/ase/msa/int-average/test_msa_ave_s_d.c b/tests/tcg/mips/user/ase/msa/int-average/test_msa_ave_s_d.c index e87d414b5f..b8c5ab4dc1 100644 --- a/tests/tcg/mips/user/ase/msa/int-average/test_msa_ave_s_d.c +++ b/tests/tcg/mips/user/ase/msa/int-average/test_msa_ave_s_d.c @@ -1,8 +1,10 @@ /* * Test program for MSA instruction AVE_S.D * - * Copyright (C) 2018 Wave Computing, Inc. - * Copyright (C) 2018 Mateja Marjanovic <mateja.marjanovic@rt-rk.com> + * Copyright (C) 2019 Wave Computing, Inc. + * Copyright (C) 2019 Aleksandar Markovic <amarkovic@wavecomp.com> + * Copyright (C) 2019 RT-RK Computer Based Systems LLC + * Copyright (C) 2019 Mateja Marjanovic <mateja.marjanovic@rt-rk.com> * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -23,8 +25,8 @@ #include <stdint.h> #include "../../../../include/wrappers_msa.h" -#include "../../../../include/test_inputs.h" -#include "../../../../include/test_utils.h" +#include "../../../../include/test_inputs_128.h" +#include "../../../../include/test_utils_128.h" #define TEST_COUNT_TOTAL ( \ (PATTERN_INPUTS_SHORT_COUNT) * (PATTERN_INPUTS_SHORT_COUNT) + \ @@ -119,8 +121,12 @@ int32_t main(void) { 0x0e54e27c0c00b6e7ULL, 0xdae527ec2a3703daULL, }, { 0xfc5cfe8cc34a1bc7ULL, 0xecac4a1bd3df4956ULL, }, { 0x36068b5855e2d4abULL, 0xd074a1f95f411aceULL, }, + { 0x0e54e27c0c00b6e7ULL, 0xdae527ec2a3703daULL, }, + { 0x704f164d5e31e24eULL, 0x8df188d8a942e2a0ULL, }, }; + reset_msa_registers(); + gettimeofday(&start, NULL); for (i = 0; i < PATTERN_INPUTS_SHORT_COUNT; i++) { diff --git a/tests/tcg/mips/user/ase/msa/int-average/test_msa_ave_s_h.c b/tests/tcg/mips/user/ase/msa/int-average/test_msa_ave_s_h.c index c850543587..24aed155f6 100644 --- a/tests/tcg/mips/user/ase/msa/int-average/test_msa_ave_s_h.c +++ b/tests/tcg/mips/user/ase/msa/int-average/test_msa_ave_s_h.c @@ -1,8 +1,10 @@ /* * Test program for MSA instruction AVE_S.H * - * Copyright (C) 2018 Wave Computing, Inc. - * Copyright (C) 2018 Mateja Marjanovic <mateja.marjanovic@rt-rk.com> + * Copyright (C) 2019 Wave Computing, Inc. + * Copyright (C) 2019 Aleksandar Markovic <amarkovic@wavecomp.com> + * Copyright (C) 2019 RT-RK Computer Based Systems LLC + * Copyright (C) 2019 Mateja Marjanovic <mateja.marjanovic@rt-rk.com> * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -23,8 +25,8 @@ #include <stdint.h> #include "../../../../include/wrappers_msa.h" -#include "../../../../include/test_inputs.h" -#include "../../../../include/test_utils.h" +#include "../../../../include/test_inputs_128.h" +#include "../../../../include/test_utils_128.h" #define TEST_COUNT_TOTAL ( \ (PATTERN_INPUTS_SHORT_COUNT) * (PATTERN_INPUTS_SHORT_COUNT) + \ @@ -119,8 +121,12 @@ int32_t main(void) { 0x0e54e27b0c00b6e7ULL, 0xdae4a7ebaa3603daULL, }, { 0xfc5cfe8c43491bc7ULL, 0xecacca1bd3dec956ULL, }, { 0x36060b5855e2d4abULL, 0xd074a1f9df401aceULL, }, + { 0x0e54e27b0c00b6e7ULL, 0xdae4a7ebaa3603daULL, }, + { 0x704f164d5e31e24eULL, 0x8df188d8a942e2a0ULL, }, }; + reset_msa_registers(); + gettimeofday(&start, NULL); for (i = 0; i < PATTERN_INPUTS_SHORT_COUNT; i++) { diff --git a/tests/tcg/mips/user/ase/msa/int-average/test_msa_ave_s_w.c b/tests/tcg/mips/user/ase/msa/int-average/test_msa_ave_s_w.c index 3220574ca0..c0082d1cc4 100644 --- a/tests/tcg/mips/user/ase/msa/int-average/test_msa_ave_s_w.c +++ b/tests/tcg/mips/user/ase/msa/int-average/test_msa_ave_s_w.c @@ -1,8 +1,10 @@ /* * Test program for MSA instruction AVE_S.W * - * Copyright (C) 2018 Wave Computing, Inc. - * Copyright (C) 2018 Mateja Marjanovic <mateja.marjanovic@rt-rk.com> + * Copyright (C) 2019 Wave Computing, Inc. + * Copyright (C) 2019 Aleksandar Markovic <amarkovic@wavecomp.com> + * Copyright (C) 2019 RT-RK Computer Based Systems LLC + * Copyright (C) 2019 Mateja Marjanovic <mateja.marjanovic@rt-rk.com> * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -23,8 +25,8 @@ #include <stdint.h> #include "../../../../include/wrappers_msa.h" -#include "../../../../include/test_inputs.h" -#include "../../../../include/test_utils.h" +#include "../../../../include/test_inputs_128.h" +#include "../../../../include/test_utils_128.h" #define TEST_COUNT_TOTAL ( \ (PATTERN_INPUTS_SHORT_COUNT) * (PATTERN_INPUTS_SHORT_COUNT) + \ @@ -119,8 +121,12 @@ int32_t main(void) { 0x0e54e27b0c00b6e7ULL, 0xdae527ebaa3703daULL, }, { 0xfc5cfe8c434a1bc7ULL, 0xecac4a1bd3df4956ULL, }, { 0x36068b5855e2d4abULL, 0xd074a1f9df411aceULL, }, + { 0x0e54e27b0c00b6e7ULL, 0xdae527ebaa3703daULL, }, + { 0x704f164d5e31e24eULL, 0x8df188d8a942e2a0ULL, }, }; + reset_msa_registers(); + gettimeofday(&start, NULL); for (i = 0; i < PATTERN_INPUTS_SHORT_COUNT; i++) { diff --git a/tests/tcg/mips/user/ase/msa/int-average/test_msa_ave_u_b.c b/tests/tcg/mips/user/ase/msa/int-average/test_msa_ave_u_b.c index c3f96a6a5f..8c857c594e 100644 --- a/tests/tcg/mips/user/ase/msa/int-average/test_msa_ave_u_b.c +++ b/tests/tcg/mips/user/ase/msa/int-average/test_msa_ave_u_b.c @@ -1,8 +1,10 @@ /* * Test program for MSA instruction AVE_U.B * - * Copyright (C) 2018 Wave Computing, Inc. - * Copyright (C) 2018 Mateja Marjanovic <mateja.marjanovic@rt-rk.com> + * Copyright (C) 2019 Wave Computing, Inc. + * Copyright (C) 2019 Aleksandar Markovic <amarkovic@wavecomp.com> + * Copyright (C) 2019 RT-RK Computer Based Systems LLC + * Copyright (C) 2019 Mateja Marjanovic <mateja.marjanovic@rt-rk.com> * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -23,8 +25,8 @@ #include <stdint.h> #include "../../../../include/wrappers_msa.h" -#include "../../../../include/test_inputs.h" -#include "../../../../include/test_utils.h" +#include "../../../../include/test_inputs_128.h" +#include "../../../../include/test_utils_128.h" #define TEST_COUNT_TOTAL ( \ (PATTERN_INPUTS_SHORT_COUNT) * (PATTERN_INPUTS_SHORT_COUNT) + \ @@ -119,8 +121,12 @@ int32_t main(void) { 0x8e54627b8b80b667ULL, 0x5ae4a7ebaa36835aULL, }, { 0x7c5c7e8c43499b47ULL, 0x6cac499bd35ec956ULL, }, { 0xb5860b585562d42bULL, 0x4ff4a1795f409aceULL, }, + { 0x8e54627b8b80b667ULL, 0x5ae4a7ebaa36835aULL, }, + { 0x704f164d5e31e24eULL, 0x8df188d8a942e2a0ULL, }, }; + reset_msa_registers(); + gettimeofday(&start, NULL); for (i = 0; i < PATTERN_INPUTS_SHORT_COUNT; i++) { diff --git a/tests/tcg/mips/user/ase/msa/int-average/test_msa_ave_u_d.c b/tests/tcg/mips/user/ase/msa/int-average/test_msa_ave_u_d.c index 3a78629cd8..fd2a4b9d49 100644 --- a/tests/tcg/mips/user/ase/msa/int-average/test_msa_ave_u_d.c +++ b/tests/tcg/mips/user/ase/msa/int-average/test_msa_ave_u_d.c @@ -1,8 +1,10 @@ /* * Test program for MSA instruction AVE_U.D * - * Copyright (C) 2018 Wave Computing, Inc. - * Copyright (C) 2018 Mateja Marjanovic <mateja.marjanovic@rt-rk.com> + * Copyright (C) 2019 Wave Computing, Inc. + * Copyright (C) 2019 Aleksandar Markovic <amarkovic@wavecomp.com> + * Copyright (C) 2019 RT-RK Computer Based Systems LLC + * Copyright (C) 2019 Mateja Marjanovic <mateja.marjanovic@rt-rk.com> * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -23,8 +25,8 @@ #include <stdint.h> #include "../../../../include/wrappers_msa.h" -#include "../../../../include/test_inputs.h" -#include "../../../../include/test_utils.h" +#include "../../../../include/test_inputs_128.h" +#include "../../../../include/test_utils_128.h" #define TEST_COUNT_TOTAL ( \ (PATTERN_INPUTS_SHORT_COUNT) * (PATTERN_INPUTS_SHORT_COUNT) + \ @@ -119,8 +121,12 @@ int32_t main(void) { 0x8e54e27c0c00b6e7ULL, 0x5ae527ec2a3703daULL, }, { 0x7c5cfe8cc34a1bc7ULL, 0x6cac4a1bd3df4956ULL, }, { 0xb6068b5855e2d4abULL, 0x5074a1f95f411aceULL, }, + { 0x8e54e27c0c00b6e7ULL, 0x5ae527ec2a3703daULL, }, + { 0x704f164d5e31e24eULL, 0x8df188d8a942e2a0ULL, }, }; + reset_msa_registers(); + gettimeofday(&start, NULL); for (i = 0; i < PATTERN_INPUTS_SHORT_COUNT; i++) { diff --git a/tests/tcg/mips/user/ase/msa/int-average/test_msa_ave_u_h.c b/tests/tcg/mips/user/ase/msa/int-average/test_msa_ave_u_h.c index b7db518afb..6ab8f47f40 100644 --- a/tests/tcg/mips/user/ase/msa/int-average/test_msa_ave_u_h.c +++ b/tests/tcg/mips/user/ase/msa/int-average/test_msa_ave_u_h.c @@ -1,8 +1,10 @@ /* * Test program for MSA instruction AVE_U.H * - * Copyright (C) 2018 Wave Computing, Inc. - * Copyright (C) 2018 Mateja Marjanovic <mateja.marjanovic@rt-rk.com> + * Copyright (C) 2019 Wave Computing, Inc. + * Copyright (C) 2019 Aleksandar Markovic <amarkovic@wavecomp.com> + * Copyright (C) 2019 RT-RK Computer Based Systems LLC + * Copyright (C) 2019 Mateja Marjanovic <mateja.marjanovic@rt-rk.com> * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -23,8 +25,8 @@ #include <stdint.h> #include "../../../../include/wrappers_msa.h" -#include "../../../../include/test_inputs.h" -#include "../../../../include/test_utils.h" +#include "../../../../include/test_inputs_128.h" +#include "../../../../include/test_utils_128.h" #define TEST_COUNT_TOTAL ( \ (PATTERN_INPUTS_SHORT_COUNT) * (PATTERN_INPUTS_SHORT_COUNT) + \ @@ -119,8 +121,12 @@ int32_t main(void) { 0x8e54627b8c00b6e7ULL, 0x5ae4a7ebaa3683daULL, }, { 0x7c5c7e8c43499bc7ULL, 0x6cac4a1bd3dec956ULL, }, { 0xb6060b5855e2d4abULL, 0x5074a1f95f409aceULL, }, + { 0x8e54627b8c00b6e7ULL, 0x5ae4a7ebaa3683daULL, }, + { 0x704f164d5e31e24eULL, 0x8df188d8a942e2a0ULL, }, }; + reset_msa_registers(); + gettimeofday(&start, NULL); for (i = 0; i < PATTERN_INPUTS_SHORT_COUNT; i++) { diff --git a/tests/tcg/mips/user/ase/msa/int-average/test_msa_ave_u_w.c b/tests/tcg/mips/user/ase/msa/int-average/test_msa_ave_u_w.c index 75e2409f1f..be614bb238 100644 --- a/tests/tcg/mips/user/ase/msa/int-average/test_msa_ave_u_w.c +++ b/tests/tcg/mips/user/ase/msa/int-average/test_msa_ave_u_w.c @@ -1,8 +1,10 @@ /* * Test program for MSA instruction AVE_U.W * - * Copyright (C) 2018 Wave Computing, Inc. - * Copyright (C) 2018 Mateja Marjanovic <mateja.marjanovic@rt-rk.com> + * Copyright (C) 2019 Wave Computing, Inc. + * Copyright (C) 2019 Aleksandar Markovic <amarkovic@wavecomp.com> + * Copyright (C) 2019 RT-RK Computer Based Systems LLC + * Copyright (C) 2019 Mateja Marjanovic <mateja.marjanovic@rt-rk.com> * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -23,8 +25,8 @@ #include <stdint.h> #include "../../../../include/wrappers_msa.h" -#include "../../../../include/test_inputs.h" -#include "../../../../include/test_utils.h" +#include "../../../../include/test_inputs_128.h" +#include "../../../../include/test_utils_128.h" #define TEST_COUNT_TOTAL ( \ (PATTERN_INPUTS_SHORT_COUNT) * (PATTERN_INPUTS_SHORT_COUNT) + \ @@ -119,8 +121,12 @@ int32_t main(void) { 0x8e54e27b8c00b6e7ULL, 0x5ae527ebaa3703daULL, }, { 0x7c5cfe8c434a1bc7ULL, 0x6cac4a1bd3df4956ULL, }, { 0xb6068b5855e2d4abULL, 0x5074a1f95f411aceULL, }, + { 0x8e54e27b8c00b6e7ULL, 0x5ae527ebaa3703daULL, }, + { 0x704f164d5e31e24eULL, 0x8df188d8a942e2a0ULL, }, }; + reset_msa_registers(); + gettimeofday(&start, NULL); for (i = 0; i < PATTERN_INPUTS_SHORT_COUNT; i++) { diff --git a/tests/tcg/mips/user/ase/msa/int-average/test_msa_aver_s_b.c b/tests/tcg/mips/user/ase/msa/int-average/test_msa_aver_s_b.c index 59bba28d2e..bccb6ac892 100644 --- a/tests/tcg/mips/user/ase/msa/int-average/test_msa_aver_s_b.c +++ b/tests/tcg/mips/user/ase/msa/int-average/test_msa_aver_s_b.c @@ -1,8 +1,10 @@ /* * Test program for MSA instruction AVER_S.B * - * Copyright (C) 2018 Wave Computing, Inc. - * Copyright (C) 2018 Mateja Marjanovic <mateja.marjanovic@rt-rk.com> + * Copyright (C) 2019 Wave Computing, Inc. + * Copyright (C) 2019 Aleksandar Markovic <amarkovic@wavecomp.com> + * Copyright (C) 2019 RT-RK Computer Based Systems LLC + * Copyright (C) 2019 Mateja Marjanovic <mateja.marjanovic@rt-rk.com> * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -23,8 +25,8 @@ #include <stdint.h> #include "../../../../include/wrappers_msa.h" -#include "../../../../include/test_inputs.h" -#include "../../../../include/test_utils.h" +#include "../../../../include/test_inputs_128.h" +#include "../../../../include/test_utils_128.h" #define TEST_COUNT_TOTAL ( \ (PATTERN_INPUTS_SHORT_COUNT) * (PATTERN_INPUTS_SHORT_COUNT) + \ @@ -119,8 +121,12 @@ int32_t main(void) { 0x0e55e2fc0c00b7e7ULL, 0xdae5a7ecaa3704daULL, }, { 0xfc5dfe0d434a1c47ULL, 0xec2cca1bd45fc9d6ULL, }, { 0x36070b5856e2d52bULL, 0xd0f4a2f9df411aceULL, }, + { 0x0e55e2fc0c00b7e7ULL, 0xdae5a7ecaa3704daULL, }, + { 0x704f164d5e31e24eULL, 0x8df188d8a942e2a0ULL, }, }; + reset_msa_registers(); + gettimeofday(&start, NULL); for (i = 0; i < PATTERN_INPUTS_SHORT_COUNT; i++) { diff --git a/tests/tcg/mips/user/ase/msa/int-average/test_msa_aver_s_d.c b/tests/tcg/mips/user/ase/msa/int-average/test_msa_aver_s_d.c index 435c09f9bf..941d889790 100644 --- a/tests/tcg/mips/user/ase/msa/int-average/test_msa_aver_s_d.c +++ b/tests/tcg/mips/user/ase/msa/int-average/test_msa_aver_s_d.c @@ -1,8 +1,10 @@ /* * Test program for MSA instruction AVER_S.D * - * Copyright (C) 2018 Wave Computing, Inc. - * Copyright (C) 2018 Mateja Marjanovic <mateja.marjanovic@rt-rk.com> + * Copyright (C) 2019 Wave Computing, Inc. + * Copyright (C) 2019 Aleksandar Markovic <amarkovic@wavecomp.com> + * Copyright (C) 2019 RT-RK Computer Based Systems LLC + * Copyright (C) 2019 Mateja Marjanovic <mateja.marjanovic@rt-rk.com> * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -23,8 +25,8 @@ #include <stdint.h> #include "../../../../include/wrappers_msa.h" -#include "../../../../include/test_inputs.h" -#include "../../../../include/test_utils.h" +#include "../../../../include/test_inputs_128.h" +#include "../../../../include/test_utils_128.h" #define TEST_COUNT_TOTAL ( \ (PATTERN_INPUTS_SHORT_COUNT) * (PATTERN_INPUTS_SHORT_COUNT) + \ @@ -119,8 +121,12 @@ int32_t main(void) { 0x0e54e27c0c00b6e7ULL, 0xdae527ec2a3703daULL, }, { 0xfc5cfe8cc34a1bc7ULL, 0xecac4a1bd3df4956ULL, }, { 0x36068b5855e2d4abULL, 0xd074a1f95f411aceULL, }, + { 0x0e54e27c0c00b6e7ULL, 0xdae527ec2a3703daULL, }, + { 0x704f164d5e31e24eULL, 0x8df188d8a942e2a0ULL, }, }; + reset_msa_registers(); + gettimeofday(&start, NULL); for (i = 0; i < PATTERN_INPUTS_SHORT_COUNT; i++) { diff --git a/tests/tcg/mips/user/ase/msa/int-average/test_msa_aver_s_h.c b/tests/tcg/mips/user/ase/msa/int-average/test_msa_aver_s_h.c index 0902e508ec..b977aaceb4 100644 --- a/tests/tcg/mips/user/ase/msa/int-average/test_msa_aver_s_h.c +++ b/tests/tcg/mips/user/ase/msa/int-average/test_msa_aver_s_h.c @@ -1,8 +1,10 @@ /* * Test program for MSA instruction AVER_S.H * - * Copyright (C) 2018 Wave Computing, Inc. - * Copyright (C) 2018 Mateja Marjanovic <mateja.marjanovic@rt-rk.com> + * Copyright (C) 2019 Wave Computing, Inc. + * Copyright (C) 2019 Aleksandar Markovic <amarkovic@wavecomp.com> + * Copyright (C) 2019 RT-RK Computer Based Systems LLC + * Copyright (C) 2019 Mateja Marjanovic <mateja.marjanovic@rt-rk.com> * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -23,8 +25,8 @@ #include <stdint.h> #include "../../../../include/wrappers_msa.h" -#include "../../../../include/test_inputs.h" -#include "../../../../include/test_utils.h" +#include "../../../../include/test_inputs_128.h" +#include "../../../../include/test_utils_128.h" #define TEST_COUNT_TOTAL ( \ (PATTERN_INPUTS_SHORT_COUNT) * (PATTERN_INPUTS_SHORT_COUNT) + \ @@ -119,8 +121,12 @@ int32_t main(void) { 0x0e55e27c0c00b6e7ULL, 0xdae5a7ecaa3703daULL, }, { 0xfc5dfe8d434a1bc7ULL, 0xecacca1bd3dfc956ULL, }, { 0x36070b5855e2d4abULL, 0xd074a1f9df411aceULL, }, + { 0x0e55e27c0c00b6e7ULL, 0xdae5a7ecaa3703daULL, }, + { 0x704f164d5e31e24eULL, 0x8df188d8a942e2a0ULL, }, }; + reset_msa_registers(); + gettimeofday(&start, NULL); for (i = 0; i < PATTERN_INPUTS_SHORT_COUNT; i++) { diff --git a/tests/tcg/mips/user/ase/msa/int-average/test_msa_aver_s_w.c b/tests/tcg/mips/user/ase/msa/int-average/test_msa_aver_s_w.c index 31f4553916..c41a9b0479 100644 --- a/tests/tcg/mips/user/ase/msa/int-average/test_msa_aver_s_w.c +++ b/tests/tcg/mips/user/ase/msa/int-average/test_msa_aver_s_w.c @@ -1,8 +1,10 @@ /* * Test program for MSA instruction AVER_S.W * - * Copyright (C) 2018 Wave Computing, Inc. - * Copyright (C) 2018 Mateja Marjanovic <mateja.marjanovic@rt-rk.com> + * Copyright (C) 2019 Wave Computing, Inc. + * Copyright (C) 2019 Aleksandar Markovic <amarkovic@wavecomp.com> + * Copyright (C) 2019 RT-RK Computer Based Systems LLC + * Copyright (C) 2019 Mateja Marjanovic <mateja.marjanovic@rt-rk.com> * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -23,8 +25,8 @@ #include <stdint.h> #include "../../../../include/wrappers_msa.h" -#include "../../../../include/test_inputs.h" -#include "../../../../include/test_utils.h" +#include "../../../../include/test_inputs_128.h" +#include "../../../../include/test_utils_128.h" #define TEST_COUNT_TOTAL ( \ (PATTERN_INPUTS_SHORT_COUNT) * (PATTERN_INPUTS_SHORT_COUNT) + \ @@ -119,8 +121,12 @@ int32_t main(void) { 0x0e54e27c0c00b6e7ULL, 0xdae527ecaa3703daULL, }, { 0xfc5cfe8d434a1bc7ULL, 0xecac4a1bd3df4956ULL, }, { 0x36068b5855e2d4abULL, 0xd074a1f9df411aceULL, }, + { 0x0e54e27c0c00b6e7ULL, 0xdae527ecaa3703daULL, }, + { 0x704f164d5e31e24eULL, 0x8df188d8a942e2a0ULL, }, }; + reset_msa_registers(); + gettimeofday(&start, NULL); for (i = 0; i < PATTERN_INPUTS_SHORT_COUNT; i++) { diff --git a/tests/tcg/mips/user/ase/msa/int-average/test_msa_aver_u_b.c b/tests/tcg/mips/user/ase/msa/int-average/test_msa_aver_u_b.c index 8aa7ec6a41..ed9aa28fa0 100644 --- a/tests/tcg/mips/user/ase/msa/int-average/test_msa_aver_u_b.c +++ b/tests/tcg/mips/user/ase/msa/int-average/test_msa_aver_u_b.c @@ -1,8 +1,10 @@ /* * Test program for MSA instruction AVER_U.B * - * Copyright (C) 2018 Wave Computing, Inc. - * Copyright (C) 2018 Mateja Marjanovic <mateja.marjanovic@rt-rk.com> + * Copyright (C) 2019 Wave Computing, Inc. + * Copyright (C) 2019 Aleksandar Markovic <amarkovic@wavecomp.com> + * Copyright (C) 2019 RT-RK Computer Based Systems LLC + * Copyright (C) 2019 Mateja Marjanovic <mateja.marjanovic@rt-rk.com> * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -23,8 +25,8 @@ #include <stdint.h> #include "../../../../include/wrappers_msa.h" -#include "../../../../include/test_inputs.h" -#include "../../../../include/test_utils.h" +#include "../../../../include/test_inputs_128.h" +#include "../../../../include/test_utils_128.h" #define TEST_COUNT_TOTAL ( \ (PATTERN_INPUTS_SHORT_COUNT) * (PATTERN_INPUTS_SHORT_COUNT) + \ @@ -119,8 +121,12 @@ int32_t main(void) { 0x8e55627c8c80b767ULL, 0x5ae5a7ecaa37845aULL, }, { 0x7c5d7e8d434a9c47ULL, 0x6cac4a9bd45fc956ULL, }, { 0xb6870b585662d52bULL, 0x50f4a2795f419aceULL, }, + { 0x8e55627c8c80b767ULL, 0x5ae5a7ecaa37845aULL, }, + { 0x704f164d5e31e24eULL, 0x8df188d8a942e2a0ULL, }, }; + reset_msa_registers(); + gettimeofday(&start, NULL); for (i = 0; i < PATTERN_INPUTS_SHORT_COUNT; i++) { diff --git a/tests/tcg/mips/user/ase/msa/int-average/test_msa_aver_u_d.c b/tests/tcg/mips/user/ase/msa/int-average/test_msa_aver_u_d.c index 9b16e1250f..04fcea4d2a 100644 --- a/tests/tcg/mips/user/ase/msa/int-average/test_msa_aver_u_d.c +++ b/tests/tcg/mips/user/ase/msa/int-average/test_msa_aver_u_d.c @@ -1,8 +1,10 @@ /* * Test program for MSA instruction AVER_U.D * - * Copyright (C) 2018 Wave Computing, Inc. - * Copyright (C) 2018 Mateja Marjanovic <mateja.marjanovic@rt-rk.com> + * Copyright (C) 2019 Wave Computing, Inc. + * Copyright (C) 2019 Aleksandar Markovic <amarkovic@wavecomp.com> + * Copyright (C) 2019 RT-RK Computer Based Systems LLC + * Copyright (C) 2019 Mateja Marjanovic <mateja.marjanovic@rt-rk.com> * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -23,8 +25,8 @@ #include <stdint.h> #include "../../../../include/wrappers_msa.h" -#include "../../../../include/test_inputs.h" -#include "../../../../include/test_utils.h" +#include "../../../../include/test_inputs_128.h" +#include "../../../../include/test_utils_128.h" #define TEST_COUNT_TOTAL ( \ (PATTERN_INPUTS_SHORT_COUNT) * (PATTERN_INPUTS_SHORT_COUNT) + \ @@ -119,8 +121,12 @@ int32_t main(void) { 0x8e54e27c0c00b6e7ULL, 0x5ae527ec2a3703daULL, }, { 0x7c5cfe8cc34a1bc7ULL, 0x6cac4a1bd3df4956ULL, }, { 0xb6068b5855e2d4abULL, 0x5074a1f95f411aceULL, }, + { 0x8e54e27c0c00b6e7ULL, 0x5ae527ec2a3703daULL, }, + { 0x704f164d5e31e24eULL, 0x8df188d8a942e2a0ULL, }, }; + reset_msa_registers(); + gettimeofday(&start, NULL); for (i = 0; i < PATTERN_INPUTS_SHORT_COUNT; i++) { diff --git a/tests/tcg/mips/user/ase/msa/int-average/test_msa_aver_u_h.c b/tests/tcg/mips/user/ase/msa/int-average/test_msa_aver_u_h.c index 191e4acbdc..4305010389 100644 --- a/tests/tcg/mips/user/ase/msa/int-average/test_msa_aver_u_h.c +++ b/tests/tcg/mips/user/ase/msa/int-average/test_msa_aver_u_h.c @@ -1,8 +1,10 @@ /* * Test program for MSA instruction AVER_U.H * - * Copyright (C) 2018 Wave Computing, Inc. - * Copyright (C) 2018 Mateja Marjanovic <mateja.marjanovic@rt-rk.com> + * Copyright (C) 2019 Wave Computing, Inc. + * Copyright (C) 2019 Aleksandar Markovic <amarkovic@wavecomp.com> + * Copyright (C) 2019 RT-RK Computer Based Systems LLC + * Copyright (C) 2019 Mateja Marjanovic <mateja.marjanovic@rt-rk.com> * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -23,8 +25,8 @@ #include <stdint.h> #include "../../../../include/wrappers_msa.h" -#include "../../../../include/test_inputs.h" -#include "../../../../include/test_utils.h" +#include "../../../../include/test_inputs_128.h" +#include "../../../../include/test_utils_128.h" #define TEST_COUNT_TOTAL ( \ (PATTERN_INPUTS_SHORT_COUNT) * (PATTERN_INPUTS_SHORT_COUNT) + \ @@ -119,8 +121,12 @@ int32_t main(void) { 0x8e55627c8c00b6e7ULL, 0x5ae5a7ecaa3783daULL, }, { 0x7c5d7e8d434a9bc7ULL, 0x6cac4a1bd3dfc956ULL, }, { 0xb6070b5855e2d4abULL, 0x5074a1f95f419aceULL, }, + { 0x8e55627c8c00b6e7ULL, 0x5ae5a7ecaa3783daULL, }, + { 0x704f164d5e31e24eULL, 0x8df188d8a942e2a0ULL, }, }; + reset_msa_registers(); + gettimeofday(&start, NULL); for (i = 0; i < PATTERN_INPUTS_SHORT_COUNT; i++) { diff --git a/tests/tcg/mips/user/ase/msa/int-average/test_msa_aver_u_w.c b/tests/tcg/mips/user/ase/msa/int-average/test_msa_aver_u_w.c index e0d6b177c4..47cdc5c08f 100644 --- a/tests/tcg/mips/user/ase/msa/int-average/test_msa_aver_u_w.c +++ b/tests/tcg/mips/user/ase/msa/int-average/test_msa_aver_u_w.c @@ -1,8 +1,10 @@ /* * Test program for MSA instruction AVER_U.W * - * Copyright (C) 2018 Wave Computing, Inc. - * Copyright (C) 2018 Mateja Marjanovic <mateja.marjanovic@rt-rk.com> + * Copyright (C) 2019 Wave Computing, Inc. + * Copyright (C) 2019 Aleksandar Markovic <amarkovic@wavecomp.com> + * Copyright (C) 2019 RT-RK Computer Based Systems LLC + * Copyright (C) 2019 Mateja Marjanovic <mateja.marjanovic@rt-rk.com> * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -23,8 +25,8 @@ #include <stdint.h> #include "../../../../include/wrappers_msa.h" -#include "../../../../include/test_inputs.h" -#include "../../../../include/test_utils.h" +#include "../../../../include/test_inputs_128.h" +#include "../../../../include/test_utils_128.h" #define TEST_COUNT_TOTAL ( \ (PATTERN_INPUTS_SHORT_COUNT) * (PATTERN_INPUTS_SHORT_COUNT) + \ @@ -119,8 +121,12 @@ int32_t main(void) { 0x8e54e27c8c00b6e7ULL, 0x5ae527ecaa3703daULL, }, { 0x7c5cfe8d434a1bc7ULL, 0x6cac4a1bd3df4956ULL, }, { 0xb6068b5855e2d4abULL, 0x5074a1f95f411aceULL, }, + { 0x8e54e27c8c00b6e7ULL, 0x5ae527ecaa3703daULL, }, + { 0x704f164d5e31e24eULL, 0x8df188d8a942e2a0ULL, }, }; + reset_msa_registers(); + gettimeofday(&start, NULL); for (i = 0; i < PATTERN_INPUTS_SHORT_COUNT; i++) { diff --git a/tests/tcg/mips/user/ase/msa/int-compare/test_msa_ceq_b.c b/tests/tcg/mips/user/ase/msa/int-compare/test_msa_ceq_b.c index bb884ee752..3ffb27c237 100644 --- a/tests/tcg/mips/user/ase/msa/int-compare/test_msa_ceq_b.c +++ b/tests/tcg/mips/user/ase/msa/int-compare/test_msa_ceq_b.c @@ -3,6 +3,8 @@ * * Copyright (C) 2019 Wave Computing, Inc. * Copyright (C) 2019 Aleksandar Markovic <amarkovic@wavecomp.com> + * Copyright (C) 2019 RT-RK Computer Based Systems LLC + * Copyright (C) 2019 Mateja Marjanovic <mateja.marjanovic@rt-rk.com> * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -123,6 +125,8 @@ int32_t main(void) { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, }; + reset_msa_registers(); + gettimeofday(&start, NULL); for (i = 0; i < PATTERN_INPUTS_SHORT_COUNT; i++) { diff --git a/tests/tcg/mips/user/ase/msa/int-compare/test_msa_ceq_d.c b/tests/tcg/mips/user/ase/msa/int-compare/test_msa_ceq_d.c index ef13f7d05d..dc60868c27 100644 --- a/tests/tcg/mips/user/ase/msa/int-compare/test_msa_ceq_d.c +++ b/tests/tcg/mips/user/ase/msa/int-compare/test_msa_ceq_d.c @@ -3,6 +3,8 @@ * * Copyright (C) 2019 Wave Computing, Inc. * Copyright (C) 2019 Aleksandar Markovic <amarkovic@wavecomp.com> + * Copyright (C) 2019 RT-RK Computer Based Systems LLC + * Copyright (C) 2019 Mateja Marjanovic <mateja.marjanovic@rt-rk.com> * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -123,6 +125,8 @@ int32_t main(void) { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, }; + reset_msa_registers(); + gettimeofday(&start, NULL); for (i = 0; i < PATTERN_INPUTS_SHORT_COUNT; i++) { diff --git a/tests/tcg/mips/user/ase/msa/int-compare/test_msa_ceq_h.c b/tests/tcg/mips/user/ase/msa/int-compare/test_msa_ceq_h.c index 1c43d40ee1..a3073d784b 100644 --- a/tests/tcg/mips/user/ase/msa/int-compare/test_msa_ceq_h.c +++ b/tests/tcg/mips/user/ase/msa/int-compare/test_msa_ceq_h.c @@ -3,6 +3,8 @@ * * Copyright (C) 2019 Wave Computing, Inc. * Copyright (C) 2019 Aleksandar Markovic <amarkovic@wavecomp.com> + * Copyright (C) 2019 RT-RK Computer Based Systems LLC + * Copyright (C) 2019 Mateja Marjanovic <mateja.marjanovic@rt-rk.com> * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -123,6 +125,8 @@ int32_t main(void) { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, }; + reset_msa_registers(); + gettimeofday(&start, NULL); for (i = 0; i < PATTERN_INPUTS_SHORT_COUNT; i++) { diff --git a/tests/tcg/mips/user/ase/msa/int-compare/test_msa_ceq_w.c b/tests/tcg/mips/user/ase/msa/int-compare/test_msa_ceq_w.c index 1297d41f29..9e81665af7 100644 --- a/tests/tcg/mips/user/ase/msa/int-compare/test_msa_ceq_w.c +++ b/tests/tcg/mips/user/ase/msa/int-compare/test_msa_ceq_w.c @@ -3,6 +3,8 @@ * * Copyright (C) 2019 Wave Computing, Inc. * Copyright (C) 2019 Aleksandar Markovic <amarkovic@wavecomp.com> + * Copyright (C) 2019 RT-RK Computer Based Systems LLC + * Copyright (C) 2019 Mateja Marjanovic <mateja.marjanovic@rt-rk.com> * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -123,6 +125,8 @@ int32_t main(void) { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, }; + reset_msa_registers(); + gettimeofday(&start, NULL); for (i = 0; i < PATTERN_INPUTS_SHORT_COUNT; i++) { diff --git a/tests/tcg/mips/user/ase/msa/int-compare/test_msa_cle_s_b.c b/tests/tcg/mips/user/ase/msa/int-compare/test_msa_cle_s_b.c index afd5f635f0..4235d59da7 100644 --- a/tests/tcg/mips/user/ase/msa/int-compare/test_msa_cle_s_b.c +++ b/tests/tcg/mips/user/ase/msa/int-compare/test_msa_cle_s_b.c @@ -3,6 +3,8 @@ * * Copyright (C) 2019 Wave Computing, Inc. * Copyright (C) 2019 Aleksandar Markovic <amarkovic@wavecomp.com> + * Copyright (C) 2019 RT-RK Computer Based Systems LLC + * Copyright (C) 2019 Mateja Marjanovic <mateja.marjanovic@rt-rk.com> * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -123,6 +125,8 @@ int32_t main(void) { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, }; + reset_msa_registers(); + gettimeofday(&start, NULL); for (i = 0; i < PATTERN_INPUTS_SHORT_COUNT; i++) { diff --git a/tests/tcg/mips/user/ase/msa/int-compare/test_msa_cle_s_d.c b/tests/tcg/mips/user/ase/msa/int-compare/test_msa_cle_s_d.c index 04d58d103c..796f89abb7 100644 --- a/tests/tcg/mips/user/ase/msa/int-compare/test_msa_cle_s_d.c +++ b/tests/tcg/mips/user/ase/msa/int-compare/test_msa_cle_s_d.c @@ -3,6 +3,8 @@ * * Copyright (C) 2019 Wave Computing, Inc. * Copyright (C) 2019 Aleksandar Markovic <amarkovic@wavecomp.com> + * Copyright (C) 2019 RT-RK Computer Based Systems LLC + * Copyright (C) 2019 Mateja Marjanovic <mateja.marjanovic@rt-rk.com> * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -123,6 +125,8 @@ int32_t main(void) { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, }; + reset_msa_registers(); + gettimeofday(&start, NULL); for (i = 0; i < PATTERN_INPUTS_SHORT_COUNT; i++) { diff --git a/tests/tcg/mips/user/ase/msa/int-compare/test_msa_cle_s_h.c b/tests/tcg/mips/user/ase/msa/int-compare/test_msa_cle_s_h.c index ed1a1e21bd..0b63274022 100644 --- a/tests/tcg/mips/user/ase/msa/int-compare/test_msa_cle_s_h.c +++ b/tests/tcg/mips/user/ase/msa/int-compare/test_msa_cle_s_h.c @@ -3,6 +3,8 @@ * * Copyright (C) 2019 Wave Computing, Inc. * Copyright (C) 2019 Aleksandar Markovic <amarkovic@wavecomp.com> + * Copyright (C) 2019 RT-RK Computer Based Systems LLC + * Copyright (C) 2019 Mateja Marjanovic <mateja.marjanovic@rt-rk.com> * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -123,6 +125,8 @@ int32_t main(void) { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, }; + reset_msa_registers(); + gettimeofday(&start, NULL); for (i = 0; i < PATTERN_INPUTS_SHORT_COUNT; i++) { diff --git a/tests/tcg/mips/user/ase/msa/int-compare/test_msa_cle_s_w.c b/tests/tcg/mips/user/ase/msa/int-compare/test_msa_cle_s_w.c index ea4dc1a30b..8fcee89221 100644 --- a/tests/tcg/mips/user/ase/msa/int-compare/test_msa_cle_s_w.c +++ b/tests/tcg/mips/user/ase/msa/int-compare/test_msa_cle_s_w.c @@ -3,6 +3,8 @@ * * Copyright (C) 2019 Wave Computing, Inc. * Copyright (C) 2019 Aleksandar Markovic <amarkovic@wavecomp.com> + * Copyright (C) 2019 RT-RK Computer Based Systems LLC + * Copyright (C) 2019 Mateja Marjanovic <mateja.marjanovic@rt-rk.com> * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -123,6 +125,8 @@ int32_t main(void) { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, }; + reset_msa_registers(); + gettimeofday(&start, NULL); for (i = 0; i < PATTERN_INPUTS_SHORT_COUNT; i++) { diff --git a/tests/tcg/mips/user/ase/msa/int-compare/test_msa_cle_u_b.c b/tests/tcg/mips/user/ase/msa/int-compare/test_msa_cle_u_b.c index 6e4fdd83ec..dc50ed3cd8 100644 --- a/tests/tcg/mips/user/ase/msa/int-compare/test_msa_cle_u_b.c +++ b/tests/tcg/mips/user/ase/msa/int-compare/test_msa_cle_u_b.c @@ -3,6 +3,8 @@ * * Copyright (C) 2019 Wave Computing, Inc. * Copyright (C) 2019 Aleksandar Markovic <amarkovic@wavecomp.com> + * Copyright (C) 2019 RT-RK Computer Based Systems LLC + * Copyright (C) 2019 Mateja Marjanovic <mateja.marjanovic@rt-rk.com> * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -123,6 +125,8 @@ int32_t main(void) { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, }; + reset_msa_registers(); + gettimeofday(&start, NULL); for (i = 0; i < PATTERN_INPUTS_SHORT_COUNT; i++) { diff --git a/tests/tcg/mips/user/ase/msa/int-compare/test_msa_cle_u_d.c b/tests/tcg/mips/user/ase/msa/int-compare/test_msa_cle_u_d.c index b2b2f557b8..f6635f958c 100644 --- a/tests/tcg/mips/user/ase/msa/int-compare/test_msa_cle_u_d.c +++ b/tests/tcg/mips/user/ase/msa/int-compare/test_msa_cle_u_d.c @@ -3,6 +3,8 @@ * * Copyright (C) 2019 Wave Computing, Inc. * Copyright (C) 2019 Aleksandar Markovic <amarkovic@wavecomp.com> + * Copyright (C) 2019 RT-RK Computer Based Systems LLC + * Copyright (C) 2019 Mateja Marjanovic <mateja.marjanovic@rt-rk.com> * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -123,6 +125,8 @@ int32_t main(void) { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, }; + reset_msa_registers(); + gettimeofday(&start, NULL); for (i = 0; i < PATTERN_INPUTS_SHORT_COUNT; i++) { diff --git a/tests/tcg/mips/user/ase/msa/int-compare/test_msa_cle_u_h.c b/tests/tcg/mips/user/ase/msa/int-compare/test_msa_cle_u_h.c index b2267752eb..0d09304fcb 100644 --- a/tests/tcg/mips/user/ase/msa/int-compare/test_msa_cle_u_h.c +++ b/tests/tcg/mips/user/ase/msa/int-compare/test_msa_cle_u_h.c @@ -3,6 +3,8 @@ * * Copyright (C) 2019 Wave Computing, Inc. * Copyright (C) 2019 Aleksandar Markovic <amarkovic@wavecomp.com> + * Copyright (C) 2019 RT-RK Computer Based Systems LLC + * Copyright (C) 2019 Mateja Marjanovic <mateja.marjanovic@rt-rk.com> * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -123,6 +125,8 @@ int32_t main(void) { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, }; + reset_msa_registers(); + gettimeofday(&start, NULL); for (i = 0; i < PATTERN_INPUTS_SHORT_COUNT; i++) { diff --git a/tests/tcg/mips/user/ase/msa/int-compare/test_msa_cle_u_w.c b/tests/tcg/mips/user/ase/msa/int-compare/test_msa_cle_u_w.c index 00e930c0c7..4671eeee7f 100644 --- a/tests/tcg/mips/user/ase/msa/int-compare/test_msa_cle_u_w.c +++ b/tests/tcg/mips/user/ase/msa/int-compare/test_msa_cle_u_w.c @@ -3,6 +3,8 @@ * * Copyright (C) 2019 Wave Computing, Inc. * Copyright (C) 2019 Aleksandar Markovic <amarkovic@wavecomp.com> + * Copyright (C) 2019 RT-RK Computer Based Systems LLC + * Copyright (C) 2019 Mateja Marjanovic <mateja.marjanovic@rt-rk.com> * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -123,6 +125,8 @@ int32_t main(void) { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, }; + reset_msa_registers(); + gettimeofday(&start, NULL); for (i = 0; i < PATTERN_INPUTS_SHORT_COUNT; i++) { diff --git a/tests/tcg/mips/user/ase/msa/int-compare/test_msa_clt_s_b.c b/tests/tcg/mips/user/ase/msa/int-compare/test_msa_clt_s_b.c index 4a52ebe491..18d5706282 100644 --- a/tests/tcg/mips/user/ase/msa/int-compare/test_msa_clt_s_b.c +++ b/tests/tcg/mips/user/ase/msa/int-compare/test_msa_clt_s_b.c @@ -3,6 +3,8 @@ * * Copyright (C) 2019 Wave Computing, Inc. * Copyright (C) 2019 Aleksandar Markovic <amarkovic@wavecomp.com> + * Copyright (C) 2019 RT-RK Computer Based Systems LLC + * Copyright (C) 2019 Mateja Marjanovic <mateja.marjanovic@rt-rk.com> * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -123,6 +125,8 @@ int32_t main(void) { 0x0000000000000000ULL, 0x0000000000000000ULL, }, }; + reset_msa_registers(); + gettimeofday(&start, NULL); for (i = 0; i < PATTERN_INPUTS_SHORT_COUNT; i++) { diff --git a/tests/tcg/mips/user/ase/msa/int-compare/test_msa_clt_s_d.c b/tests/tcg/mips/user/ase/msa/int-compare/test_msa_clt_s_d.c index cc945cdf8d..15a31660d2 100644 --- a/tests/tcg/mips/user/ase/msa/int-compare/test_msa_clt_s_d.c +++ b/tests/tcg/mips/user/ase/msa/int-compare/test_msa_clt_s_d.c @@ -3,6 +3,8 @@ * * Copyright (C) 2019 Wave Computing, Inc. * Copyright (C) 2019 Aleksandar Markovic <amarkovic@wavecomp.com> + * Copyright (C) 2019 RT-RK Computer Based Systems LLC + * Copyright (C) 2019 Mateja Marjanovic <mateja.marjanovic@rt-rk.com> * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -123,6 +125,8 @@ int32_t main(void) { 0x0000000000000000ULL, 0x0000000000000000ULL, }, }; + reset_msa_registers(); + gettimeofday(&start, NULL); for (i = 0; i < PATTERN_INPUTS_SHORT_COUNT; i++) { diff --git a/tests/tcg/mips/user/ase/msa/int-compare/test_msa_clt_s_h.c b/tests/tcg/mips/user/ase/msa/int-compare/test_msa_clt_s_h.c index b228dfe7f5..89fcc2cfe6 100644 --- a/tests/tcg/mips/user/ase/msa/int-compare/test_msa_clt_s_h.c +++ b/tests/tcg/mips/user/ase/msa/int-compare/test_msa_clt_s_h.c @@ -3,6 +3,8 @@ * * Copyright (C) 2019 Wave Computing, Inc. * Copyright (C) 2019 Aleksandar Markovic <amarkovic@wavecomp.com> + * Copyright (C) 2019 RT-RK Computer Based Systems LLC + * Copyright (C) 2019 Mateja Marjanovic <mateja.marjanovic@rt-rk.com> * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -123,6 +125,8 @@ int32_t main(void) { 0x0000000000000000ULL, 0x0000000000000000ULL, }, }; + reset_msa_registers(); + gettimeofday(&start, NULL); for (i = 0; i < PATTERN_INPUTS_SHORT_COUNT; i++) { diff --git a/tests/tcg/mips/user/ase/msa/int-compare/test_msa_clt_s_w.c b/tests/tcg/mips/user/ase/msa/int-compare/test_msa_clt_s_w.c index 6cb192a851..c8481dfc7a 100644 --- a/tests/tcg/mips/user/ase/msa/int-compare/test_msa_clt_s_w.c +++ b/tests/tcg/mips/user/ase/msa/int-compare/test_msa_clt_s_w.c @@ -3,6 +3,8 @@ * * Copyright (C) 2019 Wave Computing, Inc. * Copyright (C) 2019 Aleksandar Markovic <amarkovic@wavecomp.com> + * Copyright (C) 2019 RT-RK Computer Based Systems LLC + * Copyright (C) 2019 Mateja Marjanovic <mateja.marjanovic@rt-rk.com> * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -123,6 +125,8 @@ int32_t main(void) { 0x0000000000000000ULL, 0x0000000000000000ULL, }, }; + reset_msa_registers(); + gettimeofday(&start, NULL); for (i = 0; i < PATTERN_INPUTS_SHORT_COUNT; i++) { diff --git a/tests/tcg/mips/user/ase/msa/int-compare/test_msa_clt_u_b.c b/tests/tcg/mips/user/ase/msa/int-compare/test_msa_clt_u_b.c index b6189d6b72..ee2b39c687 100644 --- a/tests/tcg/mips/user/ase/msa/int-compare/test_msa_clt_u_b.c +++ b/tests/tcg/mips/user/ase/msa/int-compare/test_msa_clt_u_b.c @@ -3,6 +3,8 @@ * * Copyright (C) 2019 Wave Computing, Inc. * Copyright (C) 2019 Aleksandar Markovic <amarkovic@wavecomp.com> + * Copyright (C) 2019 RT-RK Computer Based Systems LLC + * Copyright (C) 2019 Mateja Marjanovic <mateja.marjanovic@rt-rk.com> * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -123,6 +125,8 @@ int32_t main(void) { 0x0000000000000000ULL, 0x0000000000000000ULL, }, }; + reset_msa_registers(); + gettimeofday(&start, NULL); for (i = 0; i < PATTERN_INPUTS_SHORT_COUNT; i++) { diff --git a/tests/tcg/mips/user/ase/msa/int-compare/test_msa_clt_u_d.c b/tests/tcg/mips/user/ase/msa/int-compare/test_msa_clt_u_d.c index 4f547d8f0b..8fef047268 100644 --- a/tests/tcg/mips/user/ase/msa/int-compare/test_msa_clt_u_d.c +++ b/tests/tcg/mips/user/ase/msa/int-compare/test_msa_clt_u_d.c @@ -3,6 +3,8 @@ * * Copyright (C) 2019 Wave Computing, Inc. * Copyright (C) 2019 Aleksandar Markovic <amarkovic@wavecomp.com> + * Copyright (C) 2019 RT-RK Computer Based Systems LLC + * Copyright (C) 2019 Mateja Marjanovic <mateja.marjanovic@rt-rk.com> * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -123,6 +125,8 @@ int32_t main(void) { 0x0000000000000000ULL, 0x0000000000000000ULL, }, }; + reset_msa_registers(); + gettimeofday(&start, NULL); for (i = 0; i < PATTERN_INPUTS_SHORT_COUNT; i++) { diff --git a/tests/tcg/mips/user/ase/msa/int-compare/test_msa_clt_u_h.c b/tests/tcg/mips/user/ase/msa/int-compare/test_msa_clt_u_h.c index 9fcd81c653..5b236a7bea 100644 --- a/tests/tcg/mips/user/ase/msa/int-compare/test_msa_clt_u_h.c +++ b/tests/tcg/mips/user/ase/msa/int-compare/test_msa_clt_u_h.c @@ -3,6 +3,8 @@ * * Copyright (C) 2019 Wave Computing, Inc. * Copyright (C) 2019 Aleksandar Markovic <amarkovic@wavecomp.com> + * Copyright (C) 2019 RT-RK Computer Based Systems LLC + * Copyright (C) 2019 Mateja Marjanovic <mateja.marjanovic@rt-rk.com> * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -123,6 +125,8 @@ int32_t main(void) { 0x0000000000000000ULL, 0x0000000000000000ULL, }, }; + reset_msa_registers(); + gettimeofday(&start, NULL); for (i = 0; i < PATTERN_INPUTS_SHORT_COUNT; i++) { diff --git a/tests/tcg/mips/user/ase/msa/int-compare/test_msa_clt_u_w.c b/tests/tcg/mips/user/ase/msa/int-compare/test_msa_clt_u_w.c index 8f648afa62..918420c592 100644 --- a/tests/tcg/mips/user/ase/msa/int-compare/test_msa_clt_u_w.c +++ b/tests/tcg/mips/user/ase/msa/int-compare/test_msa_clt_u_w.c @@ -3,6 +3,8 @@ * * Copyright (C) 2019 Wave Computing, Inc. * Copyright (C) 2019 Aleksandar Markovic <amarkovic@wavecomp.com> + * Copyright (C) 2019 RT-RK Computer Based Systems LLC + * Copyright (C) 2019 Mateja Marjanovic <mateja.marjanovic@rt-rk.com> * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -123,6 +125,8 @@ int32_t main(void) { 0x0000000000000000ULL, 0x0000000000000000ULL, }, }; + reset_msa_registers(); + gettimeofday(&start, NULL); for (i = 0; i < PATTERN_INPUTS_SHORT_COUNT; i++) { diff --git a/tests/tcg/mips/user/ase/msa/int-divide/test_msa_div_s_b.c b/tests/tcg/mips/user/ase/msa/int-divide/test_msa_div_s_b.c index 38e3670422..1b11d93025 100644 --- a/tests/tcg/mips/user/ase/msa/int-divide/test_msa_div_s_b.c +++ b/tests/tcg/mips/user/ase/msa/int-divide/test_msa_div_s_b.c @@ -1,8 +1,10 @@ /* * Test program for MSA instruction DIV_S.B * - * Copyright (C) 2018 Wave Computing, Inc. - * Copyright (C) 2018 Mateja Marjanovic <mateja.marjanovic@rt-rk.com> + * Copyright (C) 2019 Wave Computing, Inc. + * Copyright (C) 2019 Aleksandar Markovic <amarkovic@wavecomp.com> + * Copyright (C) 2019 RT-RK Computer Based Systems LLC + * Copyright (C) 2019 Mateja Marjanovic <mateja.marjanovic@rt-rk.com> * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -23,8 +25,8 @@ #include <stdint.h> #include "../../../../include/wrappers_msa.h" -#include "../../../../include/test_inputs.h" -#include "../../../../include/test_utils.h" +#include "../../../../include/test_inputs_128.h" +#include "../../../../include/test_utils_128.h" #define TEST_COUNT_TOTAL ( \ (PATTERN_INPUTS_SHORT_COUNT) * (PATTERN_INPUTS_SHORT_COUNT) + \ @@ -119,8 +121,12 @@ int32_t main(void) { 0x0001fdff00ff03ffULL, 0x000200000000ff00ULL, }, { 0x000000ff02000001ULL, 0xff00f6002b0000f8ULL, }, { 0xeaffff0001000009ULL, 0xfa0101fffc010018ULL, }, + { 0xff000000ffff0000ULL, 0xfe000228010100fcULL, }, + { 0x0101010101010101ULL, 0x0101010101010101ULL, }, }; + reset_msa_registers(); + gettimeofday(&start, NULL); for (i = 0; i < PATTERN_INPUTS_SHORT_COUNT; i++) { diff --git a/tests/tcg/mips/user/ase/msa/int-divide/test_msa_div_s_d.c b/tests/tcg/mips/user/ase/msa/int-divide/test_msa_div_s_d.c index d92b6953e8..289cf6ae3f 100644 --- a/tests/tcg/mips/user/ase/msa/int-divide/test_msa_div_s_d.c +++ b/tests/tcg/mips/user/ase/msa/int-divide/test_msa_div_s_d.c @@ -1,8 +1,10 @@ /* * Test program for MSA instruction DIV_S.D * - * Copyright (C) 2018 Wave Computing, Inc. - * Copyright (C) 2018 Mateja Marjanovic <mateja.marjanovic@rt-rk.com> + * Copyright (C) 2019 Wave Computing, Inc. + * Copyright (C) 2019 Aleksandar Markovic <amarkovic@wavecomp.com> + * Copyright (C) 2019 RT-RK Computer Based Systems LLC + * Copyright (C) 2019 Mateja Marjanovic <mateja.marjanovic@rt-rk.com> * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -23,8 +25,8 @@ #include <stdint.h> #include "../../../../include/wrappers_msa.h" -#include "../../../../include/test_inputs.h" -#include "../../../../include/test_utils.h" +#include "../../../../include/test_inputs_128.h" +#include "../../../../include/test_utils_128.h" #define TEST_COUNT_TOTAL ( \ (PATTERN_INPUTS_SHORT_COUNT) * (PATTERN_INPUTS_SHORT_COUNT) + \ @@ -119,8 +121,12 @@ int32_t main(void) { 0x0000000000000000ULL, 0x0000000000000000ULL, }, { 0x0000000000000000ULL, 0xffffffffffffffffULL, }, { 0xffffffffffffffe6ULL, 0xfffffffffffffffaULL, }, + { 0xffffffffffffffffULL, 0xfffffffffffffffeULL, }, + { 0x0000000000000001ULL, 0x0000000000000001ULL, }, }; + reset_msa_registers(); + gettimeofday(&start, NULL); for (i = 0; i < PATTERN_INPUTS_SHORT_COUNT; i++) { diff --git a/tests/tcg/mips/user/ase/msa/int-divide/test_msa_div_s_h.c b/tests/tcg/mips/user/ase/msa/int-divide/test_msa_div_s_h.c index f191b985b1..af10a04352 100644 --- a/tests/tcg/mips/user/ase/msa/int-divide/test_msa_div_s_h.c +++ b/tests/tcg/mips/user/ase/msa/int-divide/test_msa_div_s_h.c @@ -1,8 +1,10 @@ /* * Test program for MSA instruction DIV_S.H * - * Copyright (C) 2018 Wave Computing, Inc. - * Copyright (C) 2018 Mateja Marjanovic <mateja.marjanovic@rt-rk.com> + * Copyright (C) 2019 Wave Computing, Inc. + * Copyright (C) 2019 Aleksandar Markovic <amarkovic@wavecomp.com> + * Copyright (C) 2019 RT-RK Computer Based Systems LLC + * Copyright (C) 2019 Mateja Marjanovic <mateja.marjanovic@rt-rk.com> * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -23,8 +25,8 @@ #include <stdint.h> #include "../../../../include/wrappers_msa.h" -#include "../../../../include/test_inputs.h" -#include "../../../../include/test_utils.h" +#include "../../../../include/test_inputs_128.h" +#include "../../../../include/test_utils_128.h" #define TEST_COUNT_TOTAL ( \ (PATTERN_INPUTS_SHORT_COUNT) * (PATTERN_INPUTS_SHORT_COUNT) + \ @@ -119,8 +121,12 @@ int32_t main(void) { 0x0000fffd00000003ULL, 0x000000000000ffffULL, }, { 0x0000000000020000ULL, 0xfffffff600390000ULL, }, { 0xffe6003900010000ULL, 0xfffa0001fffc0000ULL, }, + { 0xffff0000ffff0000ULL, 0xfffe000200010000ULL, }, + { 0x0001000100010001ULL, 0x0001000100010001ULL, }, }; + reset_msa_registers(); + gettimeofday(&start, NULL); for (i = 0; i < PATTERN_INPUTS_SHORT_COUNT; i++) { diff --git a/tests/tcg/mips/user/ase/msa/int-divide/test_msa_div_s_w.c b/tests/tcg/mips/user/ase/msa/int-divide/test_msa_div_s_w.c index 0baaff10f9..9d3920bc53 100644 --- a/tests/tcg/mips/user/ase/msa/int-divide/test_msa_div_s_w.c +++ b/tests/tcg/mips/user/ase/msa/int-divide/test_msa_div_s_w.c @@ -1,8 +1,10 @@ /* * Test program for MSA instruction DIV_S.W * - * Copyright (C) 2018 Wave Computing, Inc. - * Copyright (C) 2018 Mateja Marjanovic <mateja.marjanovic@rt-rk.com> + * Copyright (C) 2019 Wave Computing, Inc. + * Copyright (C) 2019 Aleksandar Markovic <amarkovic@wavecomp.com> + * Copyright (C) 2019 RT-RK Computer Based Systems LLC + * Copyright (C) 2019 Mateja Marjanovic <mateja.marjanovic@rt-rk.com> * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -23,8 +25,8 @@ #include <stdint.h> #include "../../../../include/wrappers_msa.h" -#include "../../../../include/test_inputs.h" -#include "../../../../include/test_utils.h" +#include "../../../../include/test_inputs_128.h" +#include "../../../../include/test_utils_128.h" #define TEST_COUNT_TOTAL ( \ (PATTERN_INPUTS_SHORT_COUNT) * (PATTERN_INPUTS_SHORT_COUNT) + \ @@ -119,8 +121,12 @@ int32_t main(void) { 0x0000000000000000ULL, 0x0000000000000000ULL, }, { 0x0000000000000002ULL, 0xffffffff00000039ULL, }, { 0xffffffe600000001ULL, 0xfffffffafffffffcULL, }, + { 0xffffffffffffffffULL, 0xfffffffe00000001ULL, }, + { 0x0000000100000001ULL, 0x0000000100000001ULL, }, }; + reset_msa_registers(); + gettimeofday(&start, NULL); for (i = 0; i < PATTERN_INPUTS_SHORT_COUNT; i++) { diff --git a/tests/tcg/mips/user/ase/msa/int-divide/test_msa_div_u_b.c b/tests/tcg/mips/user/ase/msa/int-divide/test_msa_div_u_b.c index 770544a2de..8c0623538f 100644 --- a/tests/tcg/mips/user/ase/msa/int-divide/test_msa_div_u_b.c +++ b/tests/tcg/mips/user/ase/msa/int-divide/test_msa_div_u_b.c @@ -1,8 +1,10 @@ /* * Test program for MSA instruction DIV_U.B * - * Copyright (C) 2018 Wave Computing, Inc. - * Copyright (C) 2018 Mateja Marjanovic <mateja.marjanovic@rt-rk.com> + * Copyright (C) 2019 Wave Computing, Inc. + * Copyright (C) 2019 Aleksandar Markovic <amarkovic@wavecomp.com> + * Copyright (C) 2019 RT-RK Computer Based Systems LLC + * Copyright (C) 2019 Mateja Marjanovic <mateja.marjanovic@rt-rk.com> * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -23,8 +25,8 @@ #include <stdint.h> #include "../../../../include/wrappers_msa.h" -#include "../../../../include/test_inputs.h" -#include "../../../../include/test_utils.h" +#include "../../../../include/test_inputs_128.h" +#include "../../../../include/test_utils_128.h" #define TEST_COUNT_TOTAL ( \ (PATTERN_INPUTS_SHORT_COUNT) * (PATTERN_INPUTS_SHORT_COUNT) + \ @@ -119,8 +121,12 @@ int32_t main(void) { 0x0101070201040001ULL, 0x0000010101000000ULL, }, { 0x0000000002000201ULL, 0x01020c020000010dULL, }, { 0x0000ff0001000109ULL, 0x0700000808010200ULL, }, + { 0x0000000000000100ULL, 0x0301000000010608ULL, }, + { 0x0101010101010101ULL, 0x0101010101010101ULL, }, }; + reset_msa_registers(); + gettimeofday(&start, NULL); for (i = 0; i < PATTERN_INPUTS_SHORT_COUNT; i++) { diff --git a/tests/tcg/mips/user/ase/msa/int-divide/test_msa_div_u_d.c b/tests/tcg/mips/user/ase/msa/int-divide/test_msa_div_u_d.c index 9653e7db5c..2a9bfff459 100644 --- a/tests/tcg/mips/user/ase/msa/int-divide/test_msa_div_u_d.c +++ b/tests/tcg/mips/user/ase/msa/int-divide/test_msa_div_u_d.c @@ -1,8 +1,10 @@ /* * Test program for MSA instruction DIV_U.D * - * Copyright (C) 2018 Wave Computing, Inc. - * Copyright (C) 2018 Mateja Marjanovic <mateja.marjanovic@rt-rk.com> + * Copyright (C) 2019 Wave Computing, Inc. + * Copyright (C) 2019 Aleksandar Markovic <amarkovic@wavecomp.com> + * Copyright (C) 2019 RT-RK Computer Based Systems LLC + * Copyright (C) 2019 Mateja Marjanovic <mateja.marjanovic@rt-rk.com> * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -23,8 +25,8 @@ #include <stdint.h> #include "../../../../include/wrappers_msa.h" -#include "../../../../include/test_inputs.h" -#include "../../../../include/test_utils.h" +#include "../../../../include/test_inputs_128.h" +#include "../../../../include/test_utils_128.h" #define TEST_COUNT_TOTAL ( \ (PATTERN_INPUTS_SHORT_COUNT) * (PATTERN_INPUTS_SHORT_COUNT) + \ @@ -119,8 +121,12 @@ int32_t main(void) { 0x0000000000000001ULL, 0x0000000000000000ULL, }, { 0x0000000000000000ULL, 0x0000000000000001ULL, }, { 0x0000000000000000ULL, 0x0000000000000007ULL, }, + { 0x0000000000000000ULL, 0x0000000000000003ULL, }, + { 0x0000000000000001ULL, 0x0000000000000001ULL, }, }; + reset_msa_registers(); + gettimeofday(&start, NULL); for (i = 0; i < PATTERN_INPUTS_SHORT_COUNT; i++) { diff --git a/tests/tcg/mips/user/ase/msa/int-divide/test_msa_div_u_h.c b/tests/tcg/mips/user/ase/msa/int-divide/test_msa_div_u_h.c index 3dcd30bee9..95da85b4b9 100644 --- a/tests/tcg/mips/user/ase/msa/int-divide/test_msa_div_u_h.c +++ b/tests/tcg/mips/user/ase/msa/int-divide/test_msa_div_u_h.c @@ -1,8 +1,10 @@ /* * Test program for MSA instruction DIV_U.H * - * Copyright (C) 2018 Wave Computing, Inc. - * Copyright (C) 2018 Mateja Marjanovic <mateja.marjanovic@rt-rk.com> + * Copyright (C) 2019 Wave Computing, Inc. + * Copyright (C) 2019 Aleksandar Markovic <amarkovic@wavecomp.com> + * Copyright (C) 2019 RT-RK Computer Based Systems LLC + * Copyright (C) 2019 Mateja Marjanovic <mateja.marjanovic@rt-rk.com> * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -23,8 +25,8 @@ #include <stdint.h> #include "../../../../include/wrappers_msa.h" -#include "../../../../include/test_inputs.h" -#include "../../../../include/test_utils.h" +#include "../../../../include/test_inputs_128.h" +#include "../../../../include/test_utils_128.h" #define TEST_COUNT_TOTAL ( \ (PATTERN_INPUTS_SHORT_COUNT) * (PATTERN_INPUTS_SHORT_COUNT) + \ @@ -119,8 +121,12 @@ int32_t main(void) { 0x0001000700010000ULL, 0x0000000100010000ULL, }, { 0x0000000000020002ULL, 0x0001000c00000001ULL, }, { 0x0000003900010001ULL, 0x0007000000070002ULL, }, + { 0x0000000000000001ULL, 0x0003000000000006ULL, }, + { 0x0001000100010001ULL, 0x0001000100010001ULL, }, }; + reset_msa_registers(); + gettimeofday(&start, NULL); for (i = 0; i < PATTERN_INPUTS_SHORT_COUNT; i++) { diff --git a/tests/tcg/mips/user/ase/msa/int-divide/test_msa_div_u_w.c b/tests/tcg/mips/user/ase/msa/int-divide/test_msa_div_u_w.c index fd395ef5e9..a3984b0790 100644 --- a/tests/tcg/mips/user/ase/msa/int-divide/test_msa_div_u_w.c +++ b/tests/tcg/mips/user/ase/msa/int-divide/test_msa_div_u_w.c @@ -1,8 +1,10 @@ /* * Test program for MSA instruction DIV_U.W * - * Copyright (C) 2018 Wave Computing, Inc. - * Copyright (C) 2018 Mateja Marjanovic <mateja.marjanovic@rt-rk.com> + * Copyright (C) 2019 Wave Computing, Inc. + * Copyright (C) 2019 Aleksandar Markovic <amarkovic@wavecomp.com> + * Copyright (C) 2019 RT-RK Computer Based Systems LLC + * Copyright (C) 2019 Mateja Marjanovic <mateja.marjanovic@rt-rk.com> * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -23,8 +25,8 @@ #include <stdint.h> #include "../../../../include/wrappers_msa.h" -#include "../../../../include/test_inputs.h" -#include "../../../../include/test_utils.h" +#include "../../../../include/test_inputs_128.h" +#include "../../../../include/test_utils_128.h" #define TEST_COUNT_TOTAL ( \ (PATTERN_INPUTS_SHORT_COUNT) * (PATTERN_INPUTS_SHORT_COUNT) + \ @@ -119,8 +121,12 @@ int32_t main(void) { 0x0000000100000001ULL, 0x0000000000000001ULL, }, { 0x0000000000000002ULL, 0x0000000100000000ULL, }, { 0x0000000000000001ULL, 0x0000000700000007ULL, }, + { 0x0000000000000000ULL, 0x0000000300000000ULL, }, + { 0x0000000100000001ULL, 0x0000000100000001ULL, }, }; + reset_msa_registers(); + gettimeofday(&start, NULL); for (i = 0; i < PATTERN_INPUTS_SHORT_COUNT; i++) { diff --git a/tests/tcg/mips/user/ase/msa/int-dot-product/test_msa_dotp_s_d.c b/tests/tcg/mips/user/ase/msa/int-dot-product/test_msa_dotp_s_d.c index af8d609bea..e6d72097a6 100644 --- a/tests/tcg/mips/user/ase/msa/int-dot-product/test_msa_dotp_s_d.c +++ b/tests/tcg/mips/user/ase/msa/int-dot-product/test_msa_dotp_s_d.c @@ -1,8 +1,10 @@ /* * Test program for MSA instruction DOTP_S.D * - * Copyright (C) 2018 Wave Computing, Inc. - * Copyright (C) 2018 Mateja Marjanovic <mateja.marjanovic@rt-rk.com> + * Copyright (C) 2019 Wave Computing, Inc. + * Copyright (C) 2019 Aleksandar Markovic <amarkovic@wavecomp.com> + * Copyright (C) 2019 RT-RK Computer Based Systems LLC + * Copyright (C) 2019 Mateja Marjanovic <mateja.marjanovic@rt-rk.com> * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -23,8 +25,8 @@ #include <stdint.h> #include "../../../../include/wrappers_msa.h" -#include "../../../../include/test_inputs.h" -#include "../../../../include/test_utils.h" +#include "../../../../include/test_inputs_128.h" +#include "../../../../include/test_utils_128.h" #define TEST_COUNT_TOTAL ( \ (PATTERN_INPUTS_SHORT_COUNT) * (PATTERN_INPUTS_SHORT_COUNT) + \ @@ -119,8 +121,12 @@ int32_t main(void) { 0xc17a5d0372a2a622ULL, 0x0afd6368668933a8ULL, }, { 0xda65cd5e9f696cdcULL, 0xdeeb6bec644a26d0ULL, }, { 0x1aad30609bff5437ULL, 0xf059a43d01b40370ULL, }, + { 0xc17a5d0372a2a622ULL, 0x0afd6368668933a8ULL, }, + { 0x53edf7dbd76122edULL, 0x50347e61c2f51a40ULL, }, }; + reset_msa_registers(); + gettimeofday(&start, NULL); for (i = 0; i < PATTERN_INPUTS_SHORT_COUNT; i++) { diff --git a/tests/tcg/mips/user/ase/msa/int-dot-product/test_msa_dotp_s_h.c b/tests/tcg/mips/user/ase/msa/int-dot-product/test_msa_dotp_s_h.c index 40de72ae97..20a7029bd2 100644 --- a/tests/tcg/mips/user/ase/msa/int-dot-product/test_msa_dotp_s_h.c +++ b/tests/tcg/mips/user/ase/msa/int-dot-product/test_msa_dotp_s_h.c @@ -1,8 +1,10 @@ /* * Test program for MSA instruction DOTP_S.H * - * Copyright (C) 2018 Wave Computing, Inc. - * Copyright (C) 2018 Mateja Marjanovic <mateja.marjanovic@rt-rk.com> + * Copyright (C) 2019 Wave Computing, Inc. + * Copyright (C) 2019 Aleksandar Markovic <amarkovic@wavecomp.com> + * Copyright (C) 2019 RT-RK Computer Based Systems LLC + * Copyright (C) 2019 Mateja Marjanovic <mateja.marjanovic@rt-rk.com> * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -23,8 +25,8 @@ #include <stdint.h> #include "../../../../include/wrappers_msa.h" -#include "../../../../include/test_inputs.h" -#include "../../../../include/test_utils.h" +#include "../../../../include/test_inputs_128.h" +#include "../../../../include/test_utils_128.h" #define TEST_COUNT_TOTAL ( \ (PATTERN_INPUTS_SHORT_COUNT) * (PATTERN_INPUTS_SHORT_COUNT) + \ @@ -119,8 +121,12 @@ int32_t main(void) { 0xf706df16dc8de6b6ULL, 0xf0d31b5827f9f42aULL, }, { 0xec36ee202172098aULL, 0xd846ec28206404e0ULL, }, { 0xe9721dc70769091eULL, 0xf8711c48091bf7e4ULL, }, + { 0xf706df16dc8de6b6ULL, 0xf0d31b5827f9f42aULL, }, + { 0x4961190d2be51b48ULL, 0x348a3e802e952784ULL, }, }; + reset_msa_registers(); + gettimeofday(&start, NULL); for (i = 0; i < PATTERN_INPUTS_SHORT_COUNT; i++) { diff --git a/tests/tcg/mips/user/ase/msa/int-dot-product/test_msa_dotp_s_w.c b/tests/tcg/mips/user/ase/msa/int-dot-product/test_msa_dotp_s_w.c index 2f1d23be6f..493fc10cd7 100644 --- a/tests/tcg/mips/user/ase/msa/int-dot-product/test_msa_dotp_s_w.c +++ b/tests/tcg/mips/user/ase/msa/int-dot-product/test_msa_dotp_s_w.c @@ -1,8 +1,10 @@ /* * Test program for MSA instruction DOTP_S.W * - * Copyright (C) 2018 Wave Computing, Inc. - * Copyright (C) 2018 Mateja Marjanovic <mateja.marjanovic@rt-rk.com> + * Copyright (C) 2019 Wave Computing, Inc. + * Copyright (C) 2019 Aleksandar Markovic <amarkovic@wavecomp.com> + * Copyright (C) 2019 RT-RK Computer Based Systems LLC + * Copyright (C) 2019 Mateja Marjanovic <mateja.marjanovic@rt-rk.com> * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -23,8 +25,8 @@ #include <stdint.h> #include "../../../../include/wrappers_msa.h" -#include "../../../../include/test_inputs.h" -#include "../../../../include/test_utils.h" +#include "../../../../include/test_inputs_128.h" +#include "../../../../include/test_utils_128.h" #define TEST_COUNT_TOTAL ( \ (PATTERN_INPUTS_SHORT_COUNT) * (PATTERN_INPUTS_SHORT_COUNT) + \ @@ -119,8 +121,12 @@ int32_t main(void) { 0xd437b4e8f3b0139fULL, 0x08c7d980187d5896ULL, }, { 0xc9576c1204f83042ULL, 0xd91d3e4709b06e36ULL, }, { 0xfe2a6f6923268793ULL, 0x179e9377ef4766beULL, }, + { 0xd437b4e8f3b0139fULL, 0x08c7d980187d5896ULL, }, + { 0x33368b8a2619d525ULL, 0x6a47932120c31904ULL, }, }; + reset_msa_registers(); + gettimeofday(&start, NULL); for (i = 0; i < PATTERN_INPUTS_SHORT_COUNT; i++) { diff --git a/tests/tcg/mips/user/ase/msa/int-dot-product/test_msa_dotp_u_d.c b/tests/tcg/mips/user/ase/msa/int-dot-product/test_msa_dotp_u_d.c index e998e00410..7c9bd57fa7 100644 --- a/tests/tcg/mips/user/ase/msa/int-dot-product/test_msa_dotp_u_d.c +++ b/tests/tcg/mips/user/ase/msa/int-dot-product/test_msa_dotp_u_d.c @@ -1,8 +1,10 @@ /* * Test program for MSA instruction DOTP_U.D * - * Copyright (C) 2018 Wave Computing, Inc. - * Copyright (C) 2018 Mateja Marjanovic <mateja.marjanovic@rt-rk.com> + * Copyright (C) 2019 Wave Computing, Inc. + * Copyright (C) 2019 Aleksandar Markovic <amarkovic@wavecomp.com> + * Copyright (C) 2019 RT-RK Computer Based Systems LLC + * Copyright (C) 2019 Mateja Marjanovic <mateja.marjanovic@rt-rk.com> * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -23,8 +25,8 @@ #include <stdint.h> #include "../../../../include/wrappers_msa.h" -#include "../../../../include/test_inputs.h" -#include "../../../../include/test_utils.h" +#include "../../../../include/test_inputs_128.h" +#include "../../../../include/test_utils_128.h" #define TEST_COUNT_TOTAL ( \ (PATTERN_INPUTS_SHORT_COUNT) * (PATTERN_INPUTS_SHORT_COUNT) + \ @@ -119,8 +121,12 @@ int32_t main(void) { 0x8ffb559e72a2a622ULL, 0x8744321b668933a8ULL, }, { 0x4ab4e3ab9f696cdcULL, 0xd21109f6644a26d0ULL, }, { 0x8afc46ad9bff5437ULL, 0x1890b25301b40370ULL, }, + { 0x8ffb559e72a2a622ULL, 0x8744321b668933a8ULL, }, + { 0x53edf7dbd76122edULL, 0xbe9d5551c2f51a40ULL, }, }; + reset_msa_registers(); + gettimeofday(&start, NULL); for (i = 0; i < PATTERN_INPUTS_SHORT_COUNT; i++) { diff --git a/tests/tcg/mips/user/ase/msa/int-dot-product/test_msa_dotp_u_h.c b/tests/tcg/mips/user/ase/msa/int-dot-product/test_msa_dotp_u_h.c index e8db601a74..5ca7164718 100644 --- a/tests/tcg/mips/user/ase/msa/int-dot-product/test_msa_dotp_u_h.c +++ b/tests/tcg/mips/user/ase/msa/int-dot-product/test_msa_dotp_u_h.c @@ -1,8 +1,10 @@ /* * Test program for MSA instruction DOTP_U.H * - * Copyright (C) 2018 Wave Computing, Inc. - * Copyright (C) 2018 Mateja Marjanovic <mateja.marjanovic@rt-rk.com> + * Copyright (C) 2019 Wave Computing, Inc. + * Copyright (C) 2019 Aleksandar Markovic <amarkovic@wavecomp.com> + * Copyright (C) 2019 RT-RK Computer Based Systems LLC + * Copyright (C) 2019 Mateja Marjanovic <mateja.marjanovic@rt-rk.com> * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -23,8 +25,8 @@ #include <stdint.h> #include "../../../../include/wrappers_msa.h" -#include "../../../../include/test_inputs.h" -#include "../../../../include/test_utils.h" +#include "../../../../include/test_inputs_128.h" +#include "../../../../include/test_utils_128.h" #define TEST_COUNT_TOTAL ( \ (PATTERN_INPUTS_SHORT_COUNT) * (PATTERN_INPUTS_SHORT_COUNT) + \ @@ -119,8 +121,12 @@ int32_t main(void) { 0x670642166b8da1b6ULL, 0xe0d340587bf92d2aULL, }, { 0x5c36512021725e8aULL, 0x8a465528c764a2e0ULL, }, { 0xa8721dc73869b21eULL, 0xf27179481e1be5e4ULL, }, + { 0x670642166b8da1b6ULL, 0xe0d340587bf92d2aULL, }, + { 0x4961190d2be5df48ULL, 0x308afe8080952b84ULL, }, }; + reset_msa_registers(); + gettimeofday(&start, NULL); for (i = 0; i < PATTERN_INPUTS_SHORT_COUNT; i++) { diff --git a/tests/tcg/mips/user/ase/msa/int-dot-product/test_msa_dotp_u_w.c b/tests/tcg/mips/user/ase/msa/int-dot-product/test_msa_dotp_u_w.c index cf5bd13f48..271666da05 100644 --- a/tests/tcg/mips/user/ase/msa/int-dot-product/test_msa_dotp_u_w.c +++ b/tests/tcg/mips/user/ase/msa/int-dot-product/test_msa_dotp_u_w.c @@ -1,8 +1,10 @@ /* * Test program for MSA instruction DOTP_U.W * - * Copyright (C) 2018 Wave Computing, Inc. - * Copyright (C) 2018 Mateja Marjanovic <mateja.marjanovic@rt-rk.com> + * Copyright (C) 2019 Wave Computing, Inc. + * Copyright (C) 2019 Aleksandar Markovic <amarkovic@wavecomp.com> + * Copyright (C) 2019 RT-RK Computer Based Systems LLC + * Copyright (C) 2019 Mateja Marjanovic <mateja.marjanovic@rt-rk.com> * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -23,8 +25,8 @@ #include <stdint.h> #include "../../../../include/wrappers_msa.h" -#include "../../../../include/test_inputs.h" -#include "../../../../include/test_utils.h" +#include "../../../../include/test_inputs_128.h" +#include "../../../../include/test_utils_128.h" #define TEST_COUNT_TOTAL ( \ (PATTERN_INPUTS_SHORT_COUNT) * (PATTERN_INPUTS_SHORT_COUNT) + \ @@ -119,8 +121,12 @@ int32_t main(void) { 0x5ad3b4e8bfaf139fULL, 0x8076d98091fe5896ULL, }, { 0x4ff36c125a383042ULL, 0x2fe23e4744196e36ULL, }, { 0x6e796f69cc7c8793ULL, 0x6e879377578266beULL, }, + { 0x5ad3b4e8bfaf139fULL, 0x8076d98091fe5896ULL, }, + { 0x33368b8aeab5d525ULL, 0x97d9932138871904ULL, }, }; + reset_msa_registers(); + gettimeofday(&start, NULL); for (i = 0; i < PATTERN_INPUTS_SHORT_COUNT; i++) { diff --git a/tests/tcg/mips/user/ase/msa/int-max-min/test_msa_max_a_b.c b/tests/tcg/mips/user/ase/msa/int-max-min/test_msa_max_a_b.c index 5fa2644c30..eabcd2a5cf 100644 --- a/tests/tcg/mips/user/ase/msa/int-max-min/test_msa_max_a_b.c +++ b/tests/tcg/mips/user/ase/msa/int-max-min/test_msa_max_a_b.c @@ -3,6 +3,8 @@ * * Copyright (C) 2019 Wave Computing, Inc. * Copyright (C) 2019 Aleksandar Markovic <amarkovic@wavecomp.com> + * Copyright (C) 2019 RT-RK Computer Based Systems LLC + * Copyright (C) 2019 Mateja Marjanovic <mateja.marjanovic@rt-rk.com> * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -123,6 +125,8 @@ int32_t main(void) { 0x704f164d5e31e24eULL, 0x8df188d8a942e2a0ULL, }, }; + reset_msa_registers(); + gettimeofday(&start, NULL); for (i = 0; i < PATTERN_INPUTS_SHORT_COUNT; i++) { diff --git a/tests/tcg/mips/user/ase/msa/int-max-min/test_msa_max_a_d.c b/tests/tcg/mips/user/ase/msa/int-max-min/test_msa_max_a_d.c index 9d97982ab5..866c6839f2 100644 --- a/tests/tcg/mips/user/ase/msa/int-max-min/test_msa_max_a_d.c +++ b/tests/tcg/mips/user/ase/msa/int-max-min/test_msa_max_a_d.c @@ -3,6 +3,8 @@ * * Copyright (C) 2019 Wave Computing, Inc. * Copyright (C) 2019 Aleksandar Markovic <amarkovic@wavecomp.com> + * Copyright (C) 2019 RT-RK Computer Based Systems LLC + * Copyright (C) 2019 Mateja Marjanovic <mateja.marjanovic@rt-rk.com> * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -123,6 +125,8 @@ int32_t main(void) { 0x704f164d5e31e24eULL, 0x8df188d8a942e2a0ULL, }, }; + reset_msa_registers(); + gettimeofday(&start, NULL); for (i = 0; i < PATTERN_INPUTS_SHORT_COUNT; i++) { diff --git a/tests/tcg/mips/user/ase/msa/int-max-min/test_msa_max_a_h.c b/tests/tcg/mips/user/ase/msa/int-max-min/test_msa_max_a_h.c index 3365f726a2..7f4c2406a7 100644 --- a/tests/tcg/mips/user/ase/msa/int-max-min/test_msa_max_a_h.c +++ b/tests/tcg/mips/user/ase/msa/int-max-min/test_msa_max_a_h.c @@ -3,6 +3,8 @@ * * Copyright (C) 2019 Wave Computing, Inc. * Copyright (C) 2019 Aleksandar Markovic <amarkovic@wavecomp.com> + * Copyright (C) 2019 RT-RK Computer Based Systems LLC + * Copyright (C) 2019 Mateja Marjanovic <mateja.marjanovic@rt-rk.com> * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -123,6 +125,8 @@ int32_t main(void) { 0x704f164d5e31e24eULL, 0x8df188d8a942e2a0ULL, }, }; + reset_msa_registers(); + gettimeofday(&start, NULL); for (i = 0; i < PATTERN_INPUTS_SHORT_COUNT; i++) { diff --git a/tests/tcg/mips/user/ase/msa/int-max-min/test_msa_max_a_w.c b/tests/tcg/mips/user/ase/msa/int-max-min/test_msa_max_a_w.c index b33f4b7d79..7fb278ea02 100644 --- a/tests/tcg/mips/user/ase/msa/int-max-min/test_msa_max_a_w.c +++ b/tests/tcg/mips/user/ase/msa/int-max-min/test_msa_max_a_w.c @@ -3,6 +3,8 @@ * * Copyright (C) 2019 Wave Computing, Inc. * Copyright (C) 2019 Aleksandar Markovic <amarkovic@wavecomp.com> + * Copyright (C) 2019 RT-RK Computer Based Systems LLC + * Copyright (C) 2019 Mateja Marjanovic <mateja.marjanovic@rt-rk.com> * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -123,6 +125,8 @@ int32_t main(void) { 0x704f164d5e31e24eULL, 0x8df188d8a942e2a0ULL, }, }; + reset_msa_registers(); + gettimeofday(&start, NULL); for (i = 0; i < PATTERN_INPUTS_SHORT_COUNT; i++) { diff --git a/tests/tcg/mips/user/ase/msa/int-max-min/test_msa_max_s_b.c b/tests/tcg/mips/user/ase/msa/int-max-min/test_msa_max_s_b.c index 71e571d0c4..7e35435e42 100644 --- a/tests/tcg/mips/user/ase/msa/int-max-min/test_msa_max_s_b.c +++ b/tests/tcg/mips/user/ase/msa/int-max-min/test_msa_max_s_b.c @@ -3,6 +3,8 @@ * * Copyright (C) 2019 Wave Computing, Inc. * Copyright (C) 2019 Aleksandar Markovic <amarkovic@wavecomp.com> + * Copyright (C) 2019 RT-RK Computer Based Systems LLC + * Copyright (C) 2019 Mateja Marjanovic <mateja.marjanovic@rt-rk.com> * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -123,6 +125,8 @@ int32_t main(void) { 0x704f164d5e31e24eULL, 0x8df188d8a942e2a0ULL, }, }; + reset_msa_registers(); + gettimeofday(&start, NULL); for (i = 0; i < PATTERN_INPUTS_SHORT_COUNT; i++) { diff --git a/tests/tcg/mips/user/ase/msa/int-max-min/test_msa_max_s_d.c b/tests/tcg/mips/user/ase/msa/int-max-min/test_msa_max_s_d.c index e088ab99e3..f0a341e08a 100644 --- a/tests/tcg/mips/user/ase/msa/int-max-min/test_msa_max_s_d.c +++ b/tests/tcg/mips/user/ase/msa/int-max-min/test_msa_max_s_d.c @@ -3,6 +3,8 @@ * * Copyright (C) 2019 Wave Computing, Inc. * Copyright (C) 2019 Aleksandar Markovic <amarkovic@wavecomp.com> + * Copyright (C) 2019 RT-RK Computer Based Systems LLC + * Copyright (C) 2019 Mateja Marjanovic <mateja.marjanovic@rt-rk.com> * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -123,6 +125,8 @@ int32_t main(void) { 0x704f164d5e31e24eULL, 0x8df188d8a942e2a0ULL, }, }; + reset_msa_registers(); + gettimeofday(&start, NULL); for (i = 0; i < PATTERN_INPUTS_SHORT_COUNT; i++) { diff --git a/tests/tcg/mips/user/ase/msa/int-max-min/test_msa_max_s_h.c b/tests/tcg/mips/user/ase/msa/int-max-min/test_msa_max_s_h.c index 6d1b81a119..52de98ba8f 100644 --- a/tests/tcg/mips/user/ase/msa/int-max-min/test_msa_max_s_h.c +++ b/tests/tcg/mips/user/ase/msa/int-max-min/test_msa_max_s_h.c @@ -3,6 +3,8 @@ * * Copyright (C) 2019 Wave Computing, Inc. * Copyright (C) 2019 Aleksandar Markovic <amarkovic@wavecomp.com> + * Copyright (C) 2019 RT-RK Computer Based Systems LLC + * Copyright (C) 2019 Mateja Marjanovic <mateja.marjanovic@rt-rk.com> * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -123,6 +125,8 @@ int32_t main(void) { 0x704f164d5e31e24eULL, 0x8df188d8a942e2a0ULL, }, }; + reset_msa_registers(); + gettimeofday(&start, NULL); for (i = 0; i < PATTERN_INPUTS_SHORT_COUNT; i++) { diff --git a/tests/tcg/mips/user/ase/msa/int-max-min/test_msa_max_s_w.c b/tests/tcg/mips/user/ase/msa/int-max-min/test_msa_max_s_w.c index bd64294322..b2d0a22ac4 100644 --- a/tests/tcg/mips/user/ase/msa/int-max-min/test_msa_max_s_w.c +++ b/tests/tcg/mips/user/ase/msa/int-max-min/test_msa_max_s_w.c @@ -3,6 +3,8 @@ * * Copyright (C) 2019 Wave Computing, Inc. * Copyright (C) 2019 Aleksandar Markovic <amarkovic@wavecomp.com> + * Copyright (C) 2019 RT-RK Computer Based Systems LLC + * Copyright (C) 2019 Mateja Marjanovic <mateja.marjanovic@rt-rk.com> * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -123,6 +125,8 @@ int32_t main(void) { 0x704f164d5e31e24eULL, 0x8df188d8a942e2a0ULL, }, }; + reset_msa_registers(); + gettimeofday(&start, NULL); for (i = 0; i < PATTERN_INPUTS_SHORT_COUNT; i++) { diff --git a/tests/tcg/mips/user/ase/msa/int-max-min/test_msa_max_u_b.c b/tests/tcg/mips/user/ase/msa/int-max-min/test_msa_max_u_b.c index 206d907a26..6fb023a4b7 100644 --- a/tests/tcg/mips/user/ase/msa/int-max-min/test_msa_max_u_b.c +++ b/tests/tcg/mips/user/ase/msa/int-max-min/test_msa_max_u_b.c @@ -3,6 +3,8 @@ * * Copyright (C) 2019 Wave Computing, Inc. * Copyright (C) 2019 Aleksandar Markovic <amarkovic@wavecomp.com> + * Copyright (C) 2019 RT-RK Computer Based Systems LLC + * Copyright (C) 2019 Mateja Marjanovic <mateja.marjanovic@rt-rk.com> * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -123,6 +125,8 @@ int32_t main(void) { 0x704f164d5e31e24eULL, 0x8df188d8a942e2a0ULL, }, }; + reset_msa_registers(); + gettimeofday(&start, NULL); for (i = 0; i < PATTERN_INPUTS_SHORT_COUNT; i++) { diff --git a/tests/tcg/mips/user/ase/msa/int-max-min/test_msa_max_u_d.c b/tests/tcg/mips/user/ase/msa/int-max-min/test_msa_max_u_d.c index 4dd247f54a..35ebf1fdab 100644 --- a/tests/tcg/mips/user/ase/msa/int-max-min/test_msa_max_u_d.c +++ b/tests/tcg/mips/user/ase/msa/int-max-min/test_msa_max_u_d.c @@ -3,6 +3,8 @@ * * Copyright (C) 2019 Wave Computing, Inc. * Copyright (C) 2019 Aleksandar Markovic <amarkovic@wavecomp.com> + * Copyright (C) 2019 RT-RK Computer Based Systems LLC + * Copyright (C) 2019 Mateja Marjanovic <mateja.marjanovic@rt-rk.com> * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -123,6 +125,8 @@ int32_t main(void) { 0x704f164d5e31e24eULL, 0x8df188d8a942e2a0ULL, }, }; + reset_msa_registers(); + gettimeofday(&start, NULL); for (i = 0; i < PATTERN_INPUTS_SHORT_COUNT; i++) { diff --git a/tests/tcg/mips/user/ase/msa/int-max-min/test_msa_max_u_h.c b/tests/tcg/mips/user/ase/msa/int-max-min/test_msa_max_u_h.c index 0e6a7651eb..0e7cf1e298 100644 --- a/tests/tcg/mips/user/ase/msa/int-max-min/test_msa_max_u_h.c +++ b/tests/tcg/mips/user/ase/msa/int-max-min/test_msa_max_u_h.c @@ -3,6 +3,8 @@ * * Copyright (C) 2019 Wave Computing, Inc. * Copyright (C) 2019 Aleksandar Markovic <amarkovic@wavecomp.com> + * Copyright (C) 2019 RT-RK Computer Based Systems LLC + * Copyright (C) 2019 Mateja Marjanovic <mateja.marjanovic@rt-rk.com> * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -123,6 +125,8 @@ int32_t main(void) { 0x704f164d5e31e24eULL, 0x8df188d8a942e2a0ULL, }, }; + reset_msa_registers(); + gettimeofday(&start, NULL); for (i = 0; i < PATTERN_INPUTS_SHORT_COUNT; i++) { diff --git a/tests/tcg/mips/user/ase/msa/int-max-min/test_msa_max_u_w.c b/tests/tcg/mips/user/ase/msa/int-max-min/test_msa_max_u_w.c index db61440551..9dee9973f3 100644 --- a/tests/tcg/mips/user/ase/msa/int-max-min/test_msa_max_u_w.c +++ b/tests/tcg/mips/user/ase/msa/int-max-min/test_msa_max_u_w.c @@ -3,6 +3,8 @@ * * Copyright (C) 2019 Wave Computing, Inc. * Copyright (C) 2019 Aleksandar Markovic <amarkovic@wavecomp.com> + * Copyright (C) 2019 RT-RK Computer Based Systems LLC + * Copyright (C) 2019 Mateja Marjanovic <mateja.marjanovic@rt-rk.com> * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -123,6 +125,8 @@ int32_t main(void) { 0x704f164d5e31e24eULL, 0x8df188d8a942e2a0ULL, }, }; + reset_msa_registers(); + gettimeofday(&start, NULL); for (i = 0; i < PATTERN_INPUTS_SHORT_COUNT; i++) { diff --git a/tests/tcg/mips/user/ase/msa/int-max-min/test_msa_min_a_b.c b/tests/tcg/mips/user/ase/msa/int-max-min/test_msa_min_a_b.c index d2a93a2e44..747f54d0ac 100644 --- a/tests/tcg/mips/user/ase/msa/int-max-min/test_msa_min_a_b.c +++ b/tests/tcg/mips/user/ase/msa/int-max-min/test_msa_min_a_b.c @@ -3,6 +3,8 @@ * * Copyright (C) 2019 Wave Computing, Inc. * Copyright (C) 2019 Aleksandar Markovic <amarkovic@wavecomp.com> + * Copyright (C) 2019 RT-RK Computer Based Systems LLC + * Copyright (C) 2019 Mateja Marjanovic <mateja.marjanovic@rt-rk.com> * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -123,6 +125,8 @@ int32_t main(void) { 0x704f164d5e31e24eULL, 0x8df188d8a942e2a0ULL, }, }; + reset_msa_registers(); + gettimeofday(&start, NULL); for (i = 0; i < PATTERN_INPUTS_SHORT_COUNT; i++) { diff --git a/tests/tcg/mips/user/ase/msa/int-max-min/test_msa_min_a_d.c b/tests/tcg/mips/user/ase/msa/int-max-min/test_msa_min_a_d.c index 69fd3c7662..49ded49fe0 100644 --- a/tests/tcg/mips/user/ase/msa/int-max-min/test_msa_min_a_d.c +++ b/tests/tcg/mips/user/ase/msa/int-max-min/test_msa_min_a_d.c @@ -3,6 +3,8 @@ * * Copyright (C) 2019 Wave Computing, Inc. * Copyright (C) 2019 Aleksandar Markovic <amarkovic@wavecomp.com> + * Copyright (C) 2019 RT-RK Computer Based Systems LLC + * Copyright (C) 2019 Mateja Marjanovic <mateja.marjanovic@rt-rk.com> * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -123,6 +125,8 @@ int32_t main(void) { 0x704f164d5e31e24eULL, 0x8df188d8a942e2a0ULL, }, }; + reset_msa_registers(); + gettimeofday(&start, NULL); for (i = 0; i < PATTERN_INPUTS_SHORT_COUNT; i++) { diff --git a/tests/tcg/mips/user/ase/msa/int-max-min/test_msa_min_a_h.c b/tests/tcg/mips/user/ase/msa/int-max-min/test_msa_min_a_h.c index 9f45b55539..f78104ecb6 100644 --- a/tests/tcg/mips/user/ase/msa/int-max-min/test_msa_min_a_h.c +++ b/tests/tcg/mips/user/ase/msa/int-max-min/test_msa_min_a_h.c @@ -3,6 +3,8 @@ * * Copyright (C) 2019 Wave Computing, Inc. * Copyright (C) 2019 Aleksandar Markovic <amarkovic@wavecomp.com> + * Copyright (C) 2019 RT-RK Computer Based Systems LLC + * Copyright (C) 2019 Mateja Marjanovic <mateja.marjanovic@rt-rk.com> * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -123,6 +125,8 @@ int32_t main(void) { 0x704f164d5e31e24eULL, 0x8df188d8a942e2a0ULL, }, }; + reset_msa_registers(); + gettimeofday(&start, NULL); for (i = 0; i < PATTERN_INPUTS_SHORT_COUNT; i++) { diff --git a/tests/tcg/mips/user/ase/msa/int-max-min/test_msa_min_a_w.c b/tests/tcg/mips/user/ase/msa/int-max-min/test_msa_min_a_w.c index b08231d65f..e0afa01746 100644 --- a/tests/tcg/mips/user/ase/msa/int-max-min/test_msa_min_a_w.c +++ b/tests/tcg/mips/user/ase/msa/int-max-min/test_msa_min_a_w.c @@ -3,6 +3,8 @@ * * Copyright (C) 2019 Wave Computing, Inc. * Copyright (C) 2019 Aleksandar Markovic <amarkovic@wavecomp.com> + * Copyright (C) 2019 RT-RK Computer Based Systems LLC + * Copyright (C) 2019 Mateja Marjanovic <mateja.marjanovic@rt-rk.com> * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -123,6 +125,8 @@ int32_t main(void) { 0x704f164d5e31e24eULL, 0x8df188d8a942e2a0ULL, }, }; + reset_msa_registers(); + gettimeofday(&start, NULL); for (i = 0; i < PATTERN_INPUTS_SHORT_COUNT; i++) { diff --git a/tests/tcg/mips/user/ase/msa/int-max-min/test_msa_min_s_b.c b/tests/tcg/mips/user/ase/msa/int-max-min/test_msa_min_s_b.c index 80b5201be1..248b9681c7 100644 --- a/tests/tcg/mips/user/ase/msa/int-max-min/test_msa_min_s_b.c +++ b/tests/tcg/mips/user/ase/msa/int-max-min/test_msa_min_s_b.c @@ -3,6 +3,8 @@ * * Copyright (C) 2019 Wave Computing, Inc. * Copyright (C) 2019 Aleksandar Markovic <amarkovic@wavecomp.com> + * Copyright (C) 2019 RT-RK Computer Based Systems LLC + * Copyright (C) 2019 Mateja Marjanovic <mateja.marjanovic@rt-rk.com> * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -123,6 +125,8 @@ int32_t main(void) { 0x704f164d5e31e24eULL, 0x8df188d8a942e2a0ULL, }, }; + reset_msa_registers(); + gettimeofday(&start, NULL); for (i = 0; i < PATTERN_INPUTS_SHORT_COUNT; i++) { diff --git a/tests/tcg/mips/user/ase/msa/int-max-min/test_msa_min_s_d.c b/tests/tcg/mips/user/ase/msa/int-max-min/test_msa_min_s_d.c index 0ed319024c..219029a520 100644 --- a/tests/tcg/mips/user/ase/msa/int-max-min/test_msa_min_s_d.c +++ b/tests/tcg/mips/user/ase/msa/int-max-min/test_msa_min_s_d.c @@ -3,6 +3,8 @@ * * Copyright (C) 2019 Wave Computing, Inc. * Copyright (C) 2019 Aleksandar Markovic <amarkovic@wavecomp.com> + * Copyright (C) 2019 RT-RK Computer Based Systems LLC + * Copyright (C) 2019 Mateja Marjanovic <mateja.marjanovic@rt-rk.com> * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -123,6 +125,8 @@ int32_t main(void) { 0x704f164d5e31e24eULL, 0x8df188d8a942e2a0ULL, }, }; + reset_msa_registers(); + gettimeofday(&start, NULL); for (i = 0; i < PATTERN_INPUTS_SHORT_COUNT; i++) { diff --git a/tests/tcg/mips/user/ase/msa/int-max-min/test_msa_min_s_h.c b/tests/tcg/mips/user/ase/msa/int-max-min/test_msa_min_s_h.c index b049054d9f..fb059af226 100644 --- a/tests/tcg/mips/user/ase/msa/int-max-min/test_msa_min_s_h.c +++ b/tests/tcg/mips/user/ase/msa/int-max-min/test_msa_min_s_h.c @@ -3,6 +3,8 @@ * * Copyright (C) 2019 Wave Computing, Inc. * Copyright (C) 2019 Aleksandar Markovic <amarkovic@wavecomp.com> + * Copyright (C) 2019 RT-RK Computer Based Systems LLC + * Copyright (C) 2019 Mateja Marjanovic <mateja.marjanovic@rt-rk.com> * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -123,6 +125,8 @@ int32_t main(void) { 0x704f164d5e31e24eULL, 0x8df188d8a942e2a0ULL, }, }; + reset_msa_registers(); + gettimeofday(&start, NULL); for (i = 0; i < PATTERN_INPUTS_SHORT_COUNT; i++) { diff --git a/tests/tcg/mips/user/ase/msa/int-max-min/test_msa_min_s_w.c b/tests/tcg/mips/user/ase/msa/int-max-min/test_msa_min_s_w.c index 2bcd0a00ef..dd479921f5 100644 --- a/tests/tcg/mips/user/ase/msa/int-max-min/test_msa_min_s_w.c +++ b/tests/tcg/mips/user/ase/msa/int-max-min/test_msa_min_s_w.c @@ -3,6 +3,8 @@ * * Copyright (C) 2019 Wave Computing, Inc. * Copyright (C) 2019 Aleksandar Markovic <amarkovic@wavecomp.com> + * Copyright (C) 2019 RT-RK Computer Based Systems LLC + * Copyright (C) 2019 Mateja Marjanovic <mateja.marjanovic@rt-rk.com> * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -123,6 +125,8 @@ int32_t main(void) { 0x704f164d5e31e24eULL, 0x8df188d8a942e2a0ULL, }, }; + reset_msa_registers(); + gettimeofday(&start, NULL); for (i = 0; i < PATTERN_INPUTS_SHORT_COUNT; i++) { diff --git a/tests/tcg/mips/user/ase/msa/int-max-min/test_msa_min_u_b.c b/tests/tcg/mips/user/ase/msa/int-max-min/test_msa_min_u_b.c index 2a06b43379..7985acf5e4 100644 --- a/tests/tcg/mips/user/ase/msa/int-max-min/test_msa_min_u_b.c +++ b/tests/tcg/mips/user/ase/msa/int-max-min/test_msa_min_u_b.c @@ -3,6 +3,8 @@ * * Copyright (C) 2019 Wave Computing, Inc. * Copyright (C) 2019 Aleksandar Markovic <amarkovic@wavecomp.com> + * Copyright (C) 2019 RT-RK Computer Based Systems LLC + * Copyright (C) 2019 Mateja Marjanovic <mateja.marjanovic@rt-rk.com> * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -123,6 +125,8 @@ int32_t main(void) { 0x704f164d5e31e24eULL, 0x8df188d8a942e2a0ULL, }, }; + reset_msa_registers(); + gettimeofday(&start, NULL); for (i = 0; i < PATTERN_INPUTS_SHORT_COUNT; i++) { diff --git a/tests/tcg/mips/user/ase/msa/int-max-min/test_msa_min_u_d.c b/tests/tcg/mips/user/ase/msa/int-max-min/test_msa_min_u_d.c index 37924f3038..45d91af127 100644 --- a/tests/tcg/mips/user/ase/msa/int-max-min/test_msa_min_u_d.c +++ b/tests/tcg/mips/user/ase/msa/int-max-min/test_msa_min_u_d.c @@ -3,6 +3,8 @@ * * Copyright (C) 2019 Wave Computing, Inc. * Copyright (C) 2019 Aleksandar Markovic <amarkovic@wavecomp.com> + * Copyright (C) 2019 RT-RK Computer Based Systems LLC + * Copyright (C) 2019 Mateja Marjanovic <mateja.marjanovic@rt-rk.com> * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -123,6 +125,8 @@ int32_t main(void) { 0x704f164d5e31e24eULL, 0x8df188d8a942e2a0ULL, }, }; + reset_msa_registers(); + gettimeofday(&start, NULL); for (i = 0; i < PATTERN_INPUTS_SHORT_COUNT; i++) { diff --git a/tests/tcg/mips/user/ase/msa/int-max-min/test_msa_min_u_h.c b/tests/tcg/mips/user/ase/msa/int-max-min/test_msa_min_u_h.c index 1846995ce4..eb527bbc2b 100644 --- a/tests/tcg/mips/user/ase/msa/int-max-min/test_msa_min_u_h.c +++ b/tests/tcg/mips/user/ase/msa/int-max-min/test_msa_min_u_h.c @@ -3,6 +3,8 @@ * * Copyright (C) 2019 Wave Computing, Inc. * Copyright (C) 2019 Aleksandar Markovic <amarkovic@wavecomp.com> + * Copyright (C) 2019 RT-RK Computer Based Systems LLC + * Copyright (C) 2019 Mateja Marjanovic <mateja.marjanovic@rt-rk.com> * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -123,6 +125,8 @@ int32_t main(void) { 0x704f164d5e31e24eULL, 0x8df188d8a942e2a0ULL, }, }; + reset_msa_registers(); + gettimeofday(&start, NULL); for (i = 0; i < PATTERN_INPUTS_SHORT_COUNT; i++) { diff --git a/tests/tcg/mips/user/ase/msa/int-max-min/test_msa_min_u_w.c b/tests/tcg/mips/user/ase/msa/int-max-min/test_msa_min_u_w.c index 8b20c05440..057f22accb 100644 --- a/tests/tcg/mips/user/ase/msa/int-max-min/test_msa_min_u_w.c +++ b/tests/tcg/mips/user/ase/msa/int-max-min/test_msa_min_u_w.c @@ -3,6 +3,8 @@ * * Copyright (C) 2019 Wave Computing, Inc. * Copyright (C) 2019 Aleksandar Markovic <amarkovic@wavecomp.com> + * Copyright (C) 2019 RT-RK Computer Based Systems LLC + * Copyright (C) 2019 Mateja Marjanovic <mateja.marjanovic@rt-rk.com> * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -123,6 +125,8 @@ int32_t main(void) { 0x704f164d5e31e24eULL, 0x8df188d8a942e2a0ULL, }, }; + reset_msa_registers(); + gettimeofday(&start, NULL); for (i = 0; i < PATTERN_INPUTS_SHORT_COUNT; i++) { diff --git a/tests/tcg/mips/user/ase/msa/int-modulo/test_msa_mod_s_b.c b/tests/tcg/mips/user/ase/msa/int-modulo/test_msa_mod_s_b.c new file mode 100644 index 0000000000..a8964eadf6 --- /dev/null +++ b/tests/tcg/mips/user/ase/msa/int-modulo/test_msa_mod_s_b.c @@ -0,0 +1,157 @@ +/* + * Test program for MSA instruction MOD_S.B + * + * Copyright (C) 2019 Wave Computing, Inc. + * Copyright (C) 2019 Aleksandar Markovic <amarkovic@wavecomp.com> + * Copyright (C) 2019 RT-RK Computer Based Systems LLC + * Copyright (C) 2019 Mateja Marjanovic <mateja.marjanovic@rt-rk.com> + * + * This program 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, see <https://www.gnu.org/licenses/>. + * + */ + +#include <sys/time.h> +#include <stdint.h> + +#include "../../../../include/wrappers_msa.h" +#include "../../../../include/test_inputs_128.h" +#include "../../../../include/test_utils_128.h" + +#define TEST_COUNT_TOTAL ( \ + (PATTERN_INPUTS_SHORT_COUNT) * (PATTERN_INPUTS_SHORT_COUNT) + \ + (RANDOM_INPUTS_SHORT_COUNT) * (RANDOM_INPUTS_SHORT_COUNT)) + + +int32_t main(void) +{ + char *instruction_name = "MOD_S.B"; + int32_t ret; + uint32_t i, j; + struct timeval start, end; + double elapsed_time; + + uint64_t b128_result[TEST_COUNT_TOTAL][2]; + uint64_t b128_expect[TEST_COUNT_TOTAL][2] = { + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, /* 0 */ + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, /* 8 */ + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, /* 16 */ + { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, + { 0xdedededededededeULL, 0xdedededededededeULL, }, + { 0xddddddddddddddddULL, 0xddddddddddddddddULL, }, + { 0xe4aae2e4aae2e4aaULL, 0xe2e4aae2e4aae2e4ULL, }, + { 0xfeaae3feaae3feaaULL, 0xe3feaae3feaae3feULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, /* 24 */ + { 0x5555555555555555ULL, 0x5555555555555555ULL, }, + { 0x5555555555555555ULL, 0x5555555555555555ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x2121212121212121ULL, 0x2121212121212121ULL, }, + { 0x2222222222222222ULL, 0x2222222222222222ULL, }, + { 0x1b551d1b551d1b55ULL, 0x1d1b551d1b551d1bULL, }, + { 0x01551c01551c0155ULL, 0x1c01551c01551c01ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, /* 32 */ + { 0xccccccccccccccccULL, 0xccccccccccccccccULL, }, + { 0xccccccccccccccccULL, 0xccccccccccccccccULL, }, + { 0xccccccccccccccccULL, 0xccccccccccccccccULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, + { 0xe9cccce9cccce9ccULL, 0xcce9cccce9cccce9ULL, }, + { 0xe8cccce8cccce8ccULL, 0xcce8cccce8cccce8ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, /* 40 */ + { 0x3333333333333333ULL, 0x3333333333333333ULL, }, + { 0x3333333333333333ULL, 0x3333333333333333ULL, }, + { 0x3333333333333333ULL, 0x3333333333333333ULL, }, + { 0x3333333333333333ULL, 0x3333333333333333ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x1633331633331633ULL, 0x3316333316333316ULL, }, + { 0x1733331733331733ULL, 0x3317333317333317ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, /* 48 */ + { 0xe38e38e38e38e38eULL, 0x38e38e38e38e38e3ULL, }, + { 0xe3e438e3e438e3e4ULL, 0x38e3e438e3e438e3ULL, }, + { 0xe3e338e3e338e3e3ULL, 0x38e3e338e3e338e3ULL, }, + { 0xe3f604e3f604e3f6ULL, 0x04e3f604e3f604e3ULL, }, + { 0xe3f405e3f405e3f4ULL, 0x05e3f405e3f405e3ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0xffff38ffff38ffffULL, 0x38ffff38ffff38ffULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, /* 56 */ + { 0x1c71c71c71c71c71ULL, 0xc71c71c71c71c71cULL, }, + { 0x1c1bc71c1bc71c1bULL, 0xc71c1bc71c1bc71cULL, }, + { 0x1c1cc71c1cc71c1cULL, 0xc71c1cc71c1cc71cULL, }, + { 0x1c09fb1c09fb1c09ULL, 0xfb1c09fb1c09fb1cULL, }, + { 0x1c0bfa1c0bfa1c0bULL, 0xfa1c0bfa1c0bfa1cULL, }, + { 0x1c71ff1c71ff1c71ULL, 0xff1c71ff1c71ff1cULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, /* 64 */ + { 0x0028e6cc28621c00ULL, 0x03040b10fe3cb000ULL, }, + { 0xdc10e6cc28005540ULL, 0x24170b00fe25fa0cULL, }, + { 0xf81bfccc28001940ULL, 0x4b0d0b0efe39ec0cULL, }, + { 0xfbbe002f25f5c708ULL, 0x12f7fd1a013f02fcULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0xfbbe000d06f5c708ULL, 0x12f7f500151408fcULL, }, + { 0xfbbe00164df5e508ULL, 0x12f7bb1a153f16fcULL, }, + { 0xac5afcdee1cfe000ULL, 0x27d8fdffff2b2508ULL, }, /* 72 */ + { 0xfc18aeaab9cffd00ULL, 0x03fcc6ffff2b2500ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0xac0bf0f7b900e5ceULL, 0x27f6c6ffab2b0714ULL, }, + { 0x704f16190e31e20eULL, 0xd8f1f6d8ff42e200ULL, }, + { 0x020d164d1131e206ULL, 0xf9facdf2fd03e200ULL, }, + { 0x1c4f164d1700e24eULL, 0xdbf1fc00fe17e2f0ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, +}; + + reset_msa_registers(); + + gettimeofday(&start, NULL); + + for (i = 0; i < PATTERN_INPUTS_SHORT_COUNT; i++) { + for (j = 0; j < PATTERN_INPUTS_SHORT_COUNT; j++) { + do_msa_MOD_S_B(b128_pattern[i], b128_pattern[j], + b128_result[PATTERN_INPUTS_SHORT_COUNT * i + j]); + } + } + + for (i = 0; i < RANDOM_INPUTS_SHORT_COUNT; i++) { + for (j = 0; j < RANDOM_INPUTS_SHORT_COUNT; j++) { + do_msa_MOD_S_B(b128_random[i], b128_random[j], + b128_result[((PATTERN_INPUTS_SHORT_COUNT) * + (PATTERN_INPUTS_SHORT_COUNT)) + + RANDOM_INPUTS_SHORT_COUNT * i + j]); + } + } + + gettimeofday(&end, NULL); + + elapsed_time = (end.tv_sec - start.tv_sec) * 1000.0; + elapsed_time += (end.tv_usec - start.tv_usec) / 1000.0; + + ret = check_results(instruction_name, TEST_COUNT_TOTAL, elapsed_time, + &b128_result[0][0], &b128_expect[0][0]); + + return ret; +} diff --git a/tests/tcg/mips/user/ase/msa/int-modulo/test_msa_mod_s_d.c b/tests/tcg/mips/user/ase/msa/int-modulo/test_msa_mod_s_d.c new file mode 100644 index 0000000000..3346d37d19 --- /dev/null +++ b/tests/tcg/mips/user/ase/msa/int-modulo/test_msa_mod_s_d.c @@ -0,0 +1,157 @@ +/* + * Test program for MSA instruction MOD_S.D + * + * Copyright (C) 2019 Wave Computing, Inc. + * Copyright (C) 2019 Aleksandar Markovic <amarkovic@wavecomp.com> + * Copyright (C) 2019 RT-RK Computer Based Systems LLC + * Copyright (C) 2019 Mateja Marjanovic <mateja.marjanovic@rt-rk.com> + * + * This program 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, see <https://www.gnu.org/licenses/>. + * + */ + +#include <sys/time.h> +#include <stdint.h> + +#include "../../../../include/wrappers_msa.h" +#include "../../../../include/test_inputs_128.h" +#include "../../../../include/test_utils_128.h" + +#define TEST_COUNT_TOTAL ( \ + (PATTERN_INPUTS_SHORT_COUNT) * (PATTERN_INPUTS_SHORT_COUNT) + \ + (RANDOM_INPUTS_SHORT_COUNT) * (RANDOM_INPUTS_SHORT_COUNT)) + + +int32_t main(void) +{ + char *instruction_name = "MOD_S.D"; + int32_t ret; + uint32_t i, j; + struct timeval start, end; + double elapsed_time; + + uint64_t b128_result[TEST_COUNT_TOTAL][2]; + uint64_t b128_expect[TEST_COUNT_TOTAL][2] = { + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, /* 0 */ + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, /* 8 */ + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, /* 16 */ + { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, + { 0xdddddddddddddddeULL, 0xdddddddddddddddeULL, }, + { 0xddddddddddddddddULL, 0xddddddddddddddddULL, }, + { 0x0000000000000000ULL, 0xe38e38e38e38e38dULL, }, + { 0xfffffffffffffffdULL, 0xe38e38e38e38e38eULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, /* 24 */ + { 0x5555555555555555ULL, 0x5555555555555555ULL, }, + { 0x5555555555555555ULL, 0x5555555555555555ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x2222222222222221ULL, 0x2222222222222221ULL, }, + { 0x2222222222222222ULL, 0x2222222222222222ULL, }, + { 0x1c71c71c71c71c71ULL, 0x1c71c71c71c71c72ULL, }, + { 0x0000000000000002ULL, 0x1c71c71c71c71c71ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, /* 32 */ + { 0xccccccccccccccccULL, 0xccccccccccccccccULL, }, + { 0xccccccccccccccccULL, 0xccccccccccccccccULL, }, + { 0xccccccccccccccccULL, 0xccccccccccccccccULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, + { 0xe93e93e93e93e93eULL, 0xccccccccccccccccULL, }, + { 0xe93e93e93e93e93dULL, 0xccccccccccccccccULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, /* 40 */ + { 0x3333333333333333ULL, 0x3333333333333333ULL, }, + { 0x3333333333333333ULL, 0x3333333333333333ULL, }, + { 0x3333333333333333ULL, 0x3333333333333333ULL, }, + { 0x3333333333333333ULL, 0x3333333333333333ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x16c16c16c16c16c1ULL, 0x3333333333333333ULL, }, + { 0x16c16c16c16c16c2ULL, 0x3333333333333333ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, /* 48 */ + { 0xe38e38e38e38e38eULL, 0x38e38e38e38e38e3ULL, }, + { 0xe38e38e38e38e38eULL, 0x38e38e38e38e38e3ULL, }, + { 0xe38e38e38e38e38eULL, 0x38e38e38e38e38e3ULL, }, + { 0xe38e38e38e38e38eULL, 0x05b05b05b05b05afULL, }, + { 0xe38e38e38e38e38eULL, 0x05b05b05b05b05b0ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0xffffffffffffffffULL, 0x38e38e38e38e38e3ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, /* 56 */ + { 0x1c71c71c71c71c71ULL, 0xc71c71c71c71c71cULL, }, + { 0x1c71c71c71c71c71ULL, 0xc71c71c71c71c71cULL, }, + { 0x1c71c71c71c71c71ULL, 0xc71c71c71c71c71cULL, }, + { 0x1c71c71c71c71c71ULL, 0xfa4fa4fa4fa4fa50ULL, }, + { 0x1c71c71c71c71c71ULL, 0xfa4fa4fa4fa4fa4fULL, }, + { 0x1c71c71c71c71c71ULL, 0xffffffffffffffffULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, /* 64 */ + { 0xffa2dbefac389060ULL, 0x127fda10bebdb718ULL, }, + { 0xdc1038216e92c9c0ULL, 0x238e445f53508af8ULL, }, + { 0xf8b9fd198694378eULL, 0x4b670b5efe7bb00cULL, }, + { 0xfbbe00634d93c708ULL, 0x12f7bb1a153f52fcULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0xfbbe00634d93c708ULL, 0x12f7bb1a153f52fcULL, }, + { 0xfbbe00634d93c708ULL, 0x12f7bb1a153f52fcULL, }, + { 0xac5aaeaab9cf8b80ULL, 0x27d8c6ffab2b2514ULL, }, /* 72 */ + { 0xfd40a74bf7d7c5e8ULL, 0x01e950cb80ac7f1cULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0xac5aaeaab9cf8b80ULL, 0x27d8c6ffab2b2514ULL, }, + { 0x704f164d5e31e24eULL, 0xd9589437a7be92acULL, }, + { 0x019b20633f34191eULL, 0xffbfeb7528bed488ULL, }, + { 0x1ca9c4f818016dceULL, 0xdda316d7ff992cc8ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, +}; + + reset_msa_registers(); + + gettimeofday(&start, NULL); + + for (i = 0; i < PATTERN_INPUTS_SHORT_COUNT; i++) { + for (j = 0; j < PATTERN_INPUTS_SHORT_COUNT; j++) { + do_msa_MOD_S_D(b128_pattern[i], b128_pattern[j], + b128_result[PATTERN_INPUTS_SHORT_COUNT * i + j]); + } + } + + for (i = 0; i < RANDOM_INPUTS_SHORT_COUNT; i++) { + for (j = 0; j < RANDOM_INPUTS_SHORT_COUNT; j++) { + do_msa_MOD_S_D(b128_random[i], b128_random[j], + b128_result[((PATTERN_INPUTS_SHORT_COUNT) * + (PATTERN_INPUTS_SHORT_COUNT)) + + RANDOM_INPUTS_SHORT_COUNT * i + j]); + } + } + + gettimeofday(&end, NULL); + + elapsed_time = (end.tv_sec - start.tv_sec) * 1000.0; + elapsed_time += (end.tv_usec - start.tv_usec) / 1000.0; + + ret = check_results(instruction_name, TEST_COUNT_TOTAL, elapsed_time, + &b128_result[0][0], &b128_expect[0][0]); + + return ret; +} diff --git a/tests/tcg/mips/user/ase/msa/int-modulo/test_msa_mod_s_h.c b/tests/tcg/mips/user/ase/msa/int-modulo/test_msa_mod_s_h.c new file mode 100644 index 0000000000..c28c2534f5 --- /dev/null +++ b/tests/tcg/mips/user/ase/msa/int-modulo/test_msa_mod_s_h.c @@ -0,0 +1,157 @@ +/* + * Test program for MSA instruction MOD_S.H + * + * Copyright (C) 2019 Wave Computing, Inc. + * Copyright (C) 2019 Aleksandar Markovic <amarkovic@wavecomp.com> + * Copyright (C) 2019 RT-RK Computer Based Systems LLC + * Copyright (C) 2019 Mateja Marjanovic <mateja.marjanovic@rt-rk.com> + * + * This program 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, see <https://www.gnu.org/licenses/>. + * + */ + +#include <sys/time.h> +#include <stdint.h> + +#include "../../../../include/wrappers_msa.h" +#include "../../../../include/test_inputs_128.h" +#include "../../../../include/test_utils_128.h" + +#define TEST_COUNT_TOTAL ( \ + (PATTERN_INPUTS_SHORT_COUNT) * (PATTERN_INPUTS_SHORT_COUNT) + \ + (RANDOM_INPUTS_SHORT_COUNT) * (RANDOM_INPUTS_SHORT_COUNT)) + + +int32_t main(void) +{ + char *instruction_name = "MOD_S.H"; + int32_t ret; + uint32_t i, j; + struct timeval start, end; + double elapsed_time; + + uint64_t b128_result[TEST_COUNT_TOTAL][2]; + uint64_t b128_expect[TEST_COUNT_TOTAL][2] = { + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, /* 0 */ + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, /* 8 */ + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, /* 16 */ + { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, + { 0xdddedddedddedddeULL, 0xdddedddedddedddeULL, }, + { 0xddddddddddddddddULL, 0xddddddddddddddddULL, }, + { 0x0000e38daaaa0000ULL, 0xe38daaaa0000e38dULL, }, + { 0xfffde38eaaaafffdULL, 0xe38eaaaafffde38eULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, /* 24 */ + { 0x5555555555555555ULL, 0x5555555555555555ULL, }, + { 0x5555555555555555ULL, 0x5555555555555555ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x2221222122212221ULL, 0x2221222122212221ULL, }, + { 0x2222222222222222ULL, 0x2222222222222222ULL, }, + { 0x1c711c7255551c71ULL, 0x1c7255551c711c72ULL, }, + { 0x00021c7155550002ULL, 0x1c71555500021c71ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, /* 32 */ + { 0xccccccccccccccccULL, 0xccccccccccccccccULL, }, + { 0xccccccccccccccccULL, 0xccccccccccccccccULL, }, + { 0xccccccccccccccccULL, 0xccccccccccccccccULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, + { 0xe93ecccccccce93eULL, 0xcccccccce93eccccULL, }, + { 0xe93dcccccccce93dULL, 0xcccccccce93dccccULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, /* 40 */ + { 0x3333333333333333ULL, 0x3333333333333333ULL, }, + { 0x3333333333333333ULL, 0x3333333333333333ULL, }, + { 0x3333333333333333ULL, 0x3333333333333333ULL, }, + { 0x3333333333333333ULL, 0x3333333333333333ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x16c13333333316c1ULL, 0x3333333316c13333ULL, }, + { 0x16c23333333316c2ULL, 0x3333333316c23333ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, /* 48 */ + { 0xe38e38e38e38e38eULL, 0x38e38e38e38e38e3ULL, }, + { 0xe38e38e3e38ee38eULL, 0x38e3e38ee38e38e3ULL, }, + { 0xe38e38e3e38de38eULL, 0x38e3e38de38e38e3ULL, }, + { 0xe38e05aff4a0e38eULL, 0x05aff4a0e38e05afULL, }, + { 0xe38e05b0f49ee38eULL, 0x05b0f49ee38e05b0ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0xffff38e3ffffffffULL, 0x38e3ffffffff38e3ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, /* 56 */ + { 0x1c71c71c71c71c71ULL, 0xc71c71c71c71c71cULL, }, + { 0x1c71c71c1c711c71ULL, 0xc71c1c711c71c71cULL, }, + { 0x1c71c71c1c721c71ULL, 0xc71c1c721c71c71cULL, }, + { 0x1c71fa500b5f1c71ULL, 0xfa500b5f1c71fa50ULL, }, + { 0x1c71fa4f0b611c71ULL, 0xfa4f0b611c71fa4fULL, }, + { 0x1c71ffff71c71c71ULL, 0xffff71c71c71ffffULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, /* 64 */ + { 0xffa2ffef28621c48ULL, 0x12820b5efe7bb00cULL, }, + { 0xdc10e6cc28625540ULL, 0x238f0b5efe7bfa34ULL, }, + { 0xf8b9fd19286219dcULL, 0x4b670b5efe7beaccULL, }, + { 0xfbbe00632531c708ULL, 0x12f7ff4e017e0308ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0xfbbe00630762c708ULL, 0x12f7f41b153f08d4ULL, }, + { 0xfbbe00634d93e4baULL, 0x12f7bb1a153f183cULL, }, + { 0xac5afa46e231e0c0ULL, 0x27d8ffd5febe2514ULL, }, /* 72 */ + { 0xfd40ffe0b9cffd70ULL, 0x01eac6ffeae82514ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0xac5af191b9cfe496ULL, 0x27d8c6ffab2b07b4ULL, }, + { 0x704f164d0d6de24eULL, 0xd958fa84ffdfe2a0ULL, }, + { 0x019b0042109ee24eULL, 0xffbbcdbefe3ee2a0ULL, }, + { 0x1ca9164d1800e24eULL, 0xdda1fadafe17e2a0ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, +}; + + reset_msa_registers(); + + gettimeofday(&start, NULL); + + for (i = 0; i < PATTERN_INPUTS_SHORT_COUNT; i++) { + for (j = 0; j < PATTERN_INPUTS_SHORT_COUNT; j++) { + do_msa_MOD_S_H(b128_pattern[i], b128_pattern[j], + b128_result[PATTERN_INPUTS_SHORT_COUNT * i + j]); + } + } + + for (i = 0; i < RANDOM_INPUTS_SHORT_COUNT; i++) { + for (j = 0; j < RANDOM_INPUTS_SHORT_COUNT; j++) { + do_msa_MOD_S_H(b128_random[i], b128_random[j], + b128_result[((PATTERN_INPUTS_SHORT_COUNT) * + (PATTERN_INPUTS_SHORT_COUNT)) + + RANDOM_INPUTS_SHORT_COUNT * i + j]); + } + } + + gettimeofday(&end, NULL); + + elapsed_time = (end.tv_sec - start.tv_sec) * 1000.0; + elapsed_time += (end.tv_usec - start.tv_usec) / 1000.0; + + ret = check_results(instruction_name, TEST_COUNT_TOTAL, elapsed_time, + &b128_result[0][0], &b128_expect[0][0]); + + return ret; +} diff --git a/tests/tcg/mips/user/ase/msa/int-modulo/test_msa_mod_s_w.c b/tests/tcg/mips/user/ase/msa/int-modulo/test_msa_mod_s_w.c new file mode 100644 index 0000000000..593e516534 --- /dev/null +++ b/tests/tcg/mips/user/ase/msa/int-modulo/test_msa_mod_s_w.c @@ -0,0 +1,157 @@ +/* + * Test program for MSA instruction MOD_S.W + * + * Copyright (C) 2019 Wave Computing, Inc. + * Copyright (C) 2019 Aleksandar Markovic <amarkovic@wavecomp.com> + * Copyright (C) 2019 RT-RK Computer Based Systems LLC + * Copyright (C) 2019 Mateja Marjanovic <mateja.marjanovic@rt-rk.com> + * + * This program 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, see <https://www.gnu.org/licenses/>. + * + */ + +#include <sys/time.h> +#include <stdint.h> + +#include "../../../../include/wrappers_msa.h" +#include "../../../../include/test_inputs_128.h" +#include "../../../../include/test_utils_128.h" + +#define TEST_COUNT_TOTAL ( \ + (PATTERN_INPUTS_SHORT_COUNT) * (PATTERN_INPUTS_SHORT_COUNT) + \ + (RANDOM_INPUTS_SHORT_COUNT) * (RANDOM_INPUTS_SHORT_COUNT)) + + +int32_t main(void) +{ + char *instruction_name = "MOD_S.W"; + int32_t ret; + uint32_t i, j; + struct timeval start, end; + double elapsed_time; + + uint64_t b128_result[TEST_COUNT_TOTAL][2]; + uint64_t b128_expect[TEST_COUNT_TOTAL][2] = { + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, /* 0 */ + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, /* 8 */ + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, /* 16 */ + { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, + { 0xdddddddedddddddeULL, 0xdddddddedddddddeULL, }, + { 0xddddddddddddddddULL, 0xddddddddddddddddULL, }, + { 0xe38e38e4aaaaaaaaULL, 0xe38e38e2e38e38e4ULL, }, + { 0xfffffffeaaaaaaaaULL, 0xe38e38e3fffffffeULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, /* 24 */ + { 0x5555555555555555ULL, 0x5555555555555555ULL, }, + { 0x5555555555555555ULL, 0x5555555555555555ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x2222222122222221ULL, 0x2222222122222221ULL, }, + { 0x2222222222222222ULL, 0x2222222222222222ULL, }, + { 0x1c71c71b55555555ULL, 0x1c71c71d1c71c71bULL, }, + { 0x0000000155555555ULL, 0x1c71c71c00000001ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, /* 32 */ + { 0xccccccccccccccccULL, 0xccccccccccccccccULL, }, + { 0xccccccccccccccccULL, 0xccccccccccccccccULL, }, + { 0xccccccccccccccccULL, 0xccccccccccccccccULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, + { 0xe93e93e9ccccccccULL, 0xcccccccce93e93e9ULL, }, + { 0xe93e93e8ccccccccULL, 0xcccccccce93e93e8ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, /* 40 */ + { 0x3333333333333333ULL, 0x3333333333333333ULL, }, + { 0x3333333333333333ULL, 0x3333333333333333ULL, }, + { 0x3333333333333333ULL, 0x3333333333333333ULL, }, + { 0x3333333333333333ULL, 0x3333333333333333ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x16c16c1633333333ULL, 0x3333333316c16c16ULL, }, + { 0x16c16c1733333333ULL, 0x3333333316c16c17ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, /* 48 */ + { 0xe38e38e38e38e38eULL, 0x38e38e38e38e38e3ULL, }, + { 0xe38e38e3e38e38e4ULL, 0x38e38e38e38e38e3ULL, }, + { 0xe38e38e3e38e38e3ULL, 0x38e38e38e38e38e3ULL, }, + { 0xe38e38e3f49f49f6ULL, 0x05b05b04e38e38e3ULL, }, + { 0xe38e38e3f49f49f4ULL, 0x05b05b05e38e38e3ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0xffffffffffffffffULL, 0x38e38e38ffffffffULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, /* 56 */ + { 0x1c71c71c71c71c71ULL, 0xc71c71c71c71c71cULL, }, + { 0x1c71c71c1c71c71bULL, 0xc71c71c71c71c71cULL, }, + { 0x1c71c71c1c71c71cULL, 0xc71c71c71c71c71cULL, }, + { 0x1c71c71c0b60b609ULL, 0xfa4fa4fb1c71c71cULL, }, + { 0x1c71c71c0b60b60bULL, 0xfa4fa4fa1c71c71cULL, }, + { 0x1c71c71c71c71c71ULL, 0xffffffff1c71c71cULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, /* 64 */ + { 0xffa2dbf828625540ULL, 0x127fda10fe7bb00cULL, }, + { 0xdc10382228625540ULL, 0x238e445ffe7bb00cULL, }, + { 0xf8b9fd1928625540ULL, 0x4b670b5efe7bb00cULL, }, + { 0xfbbe0063253171c8ULL, 0x12f7bb1a0002f3a4ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0xfbbe006307635288ULL, 0x12f7bb1a153f52fcULL, }, + { 0xfbbe00634d93c708ULL, 0x12f7bb1a153f52fcULL, }, + { 0xac5aaeaae231e0c0ULL, 0x27d8c6fffe985280ULL, }, /* 72 */ + { 0xfd40a751b9cf8b80ULL, 0x01e950cbeae91e08ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0xac5aaeaab9cf8b80ULL, 0x27d8c6ffab2b2514ULL, }, + { 0x704f164d0d6d37ceULL, 0xd9589436ffb8aff4ULL, }, + { 0x019b205b109e1b46ULL, 0xffbfeb74fe402e90ULL, }, + { 0x1ca9c4f718016dceULL, 0xdda316d6fe17bd8cULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, +}; + + reset_msa_registers(); + + gettimeofday(&start, NULL); + + for (i = 0; i < PATTERN_INPUTS_SHORT_COUNT; i++) { + for (j = 0; j < PATTERN_INPUTS_SHORT_COUNT; j++) { + do_msa_MOD_S_W(b128_pattern[i], b128_pattern[j], + b128_result[PATTERN_INPUTS_SHORT_COUNT * i + j]); + } + } + + for (i = 0; i < RANDOM_INPUTS_SHORT_COUNT; i++) { + for (j = 0; j < RANDOM_INPUTS_SHORT_COUNT; j++) { + do_msa_MOD_S_W(b128_random[i], b128_random[j], + b128_result[((PATTERN_INPUTS_SHORT_COUNT) * + (PATTERN_INPUTS_SHORT_COUNT)) + + RANDOM_INPUTS_SHORT_COUNT * i + j]); + } + } + + gettimeofday(&end, NULL); + + elapsed_time = (end.tv_sec - start.tv_sec) * 1000.0; + elapsed_time += (end.tv_usec - start.tv_usec) / 1000.0; + + ret = check_results(instruction_name, TEST_COUNT_TOTAL, elapsed_time, + &b128_result[0][0], &b128_expect[0][0]); + + return ret; +} diff --git a/tests/tcg/mips/user/ase/msa/int-modulo/test_msa_mod_u_b.c b/tests/tcg/mips/user/ase/msa/int-modulo/test_msa_mod_u_b.c new file mode 100644 index 0000000000..1b5e57b96f --- /dev/null +++ b/tests/tcg/mips/user/ase/msa/int-modulo/test_msa_mod_u_b.c @@ -0,0 +1,157 @@ +/* + * Test program for MSA instruction MOD_U.B + * + * Copyright (C) 2019 Wave Computing, Inc. + * Copyright (C) 2019 Aleksandar Markovic <amarkovic@wavecomp.com> + * Copyright (C) 2019 RT-RK Computer Based Systems LLC + * Copyright (C) 2019 Mateja Marjanovic <mateja.marjanovic@rt-rk.com> + * + * This program 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, see <https://www.gnu.org/licenses/>. + * + */ + +#include <sys/time.h> +#include <stdint.h> + +#include "../../../../include/wrappers_msa.h" +#include "../../../../include/test_inputs_128.h" +#include "../../../../include/test_utils_128.h" + +#define TEST_COUNT_TOTAL ( \ + (PATTERN_INPUTS_SHORT_COUNT) * (PATTERN_INPUTS_SHORT_COUNT) + \ + (RANDOM_INPUTS_SHORT_COUNT) * (RANDOM_INPUTS_SHORT_COUNT)) + + +int32_t main(void) +{ + char *instruction_name = "MOD_U.B"; + int32_t ret; + uint32_t i, j; + struct timeval start, end; + double elapsed_time; + + uint64_t b128_result[TEST_COUNT_TOTAL][2]; + uint64_t b128_expect[TEST_COUNT_TOTAL][2] = { + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, /* 0 */ + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, + { 0x5555555555555555ULL, 0x5555555555555555ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x3333333333333333ULL, 0x3333333333333333ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x1c711f1c711f1c71ULL, 0x1f1c711f1c711f1cULL, }, + { 0x031d38031d38031dULL, 0x38031d38031d3803ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, /* 8 */ + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, }, /* 16 */ + { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, }, + { 0x1111111111111111ULL, 0x1111111111111111ULL, }, + { 0xaa1c02aa1c02aa1cULL, 0x02aa1c02aa1c02aaULL, }, + { 0x0239aa0239aa0239ULL, 0xaa0239aa0239aa02ULL, }, + { 0x5555555555555555ULL, 0x5555555555555555ULL, }, /* 24 */ + { 0x5555555555555555ULL, 0x5555555555555555ULL, }, + { 0x5555555555555555ULL, 0x5555555555555555ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x5555555555555555ULL, 0x5555555555555555ULL, }, + { 0x2222222222222222ULL, 0x2222222222222222ULL, }, + { 0x55551d55551d5555ULL, 0x1d55551d55551d55ULL, }, + { 0x0155550155550155ULL, 0x5501555501555501ULL, }, + { 0xccccccccccccccccULL, 0xccccccccccccccccULL, }, /* 32 */ + { 0xccccccccccccccccULL, 0xccccccccccccccccULL, }, + { 0x2222222222222222ULL, 0x2222222222222222ULL, }, + { 0x2222222222222222ULL, 0x2222222222222222ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0xcc3e24cc3e24cc3eULL, 0x24cc3e24cc3e24ccULL, }, + { 0x085b05085b05085bULL, 0x05085b05085b0508ULL, }, + { 0x3333333333333333ULL, 0x3333333333333333ULL, }, /* 40 */ + { 0x3333333333333333ULL, 0x3333333333333333ULL, }, + { 0x3333333333333333ULL, 0x3333333333333333ULL, }, + { 0x3333333333333333ULL, 0x3333333333333333ULL, }, + { 0x3333333333333333ULL, 0x3333333333333333ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x3333333333333333ULL, 0x3333333333333333ULL, }, + { 0x1733331733331733ULL, 0x3317333317333317ULL, }, + { 0xe38e38e38e38e38eULL, 0x38e38e38e38e38e3ULL, }, /* 48 */ + { 0xe38e38e38e38e38eULL, 0x38e38e38e38e38e3ULL, }, + { 0x398e38398e38398eULL, 0x38398e38398e3839ULL, }, + { 0x3939383939383939ULL, 0x3839393839393839ULL, }, + { 0x178e38178e38178eULL, 0x38178e38178e3817ULL, }, + { 0x1728051728051728ULL, 0x0517280517280517ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x031d38031d38031dULL, 0x38031d38031d3803ULL, }, + { 0x1c71c71c71c71c71ULL, 0xc71c71c71c71c71cULL, }, /* 56 */ + { 0x1c71c71c71c71c71ULL, 0xc71c71c71c71c71cULL, }, + { 0x1c711d1c711d1c71ULL, 0x1d1c711d1c711d1cULL, }, + { 0x1c1c1d1c1c1d1c1cULL, 0x1d1c1c1d1c1c1d1cULL, }, + { 0x1c71c71c71c71c71ULL, 0xc71c71c71c71c71cULL, }, + { 0x1c0b2e1c0b2e1c0bULL, 0x2e1c0b2e1c0b2e1cULL, }, + { 0x1c711f1c711f1c71ULL, 0x1f1c711f1c711f1cULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, /* 64 */ + { 0x886ae60628625500ULL, 0x03670b10023c0c0cULL, }, + { 0x8810382228625540ULL, 0x24670b5e53251c0cULL, }, + { 0x181b0a3228005540ULL, 0x4b670b5e5539b00cULL, }, + { 0x7354006325311d08ULL, 0x1229001a153f5200ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x4f0a00634d933c08ULL, 0x121fbb1a1514080cULL, }, + { 0x1b2000164d00c708ULL, 0x1206331a153f525cULL, }, + { 0x245aaeaa190b3600ULL, 0x270a0043ab2b2508ULL, }, /* 72 */ + { 0xac5aae471f3c8b00ULL, 0x03d80b15032b2514ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x3c0b14105b0b8b32ULL, 0x27d83e27022b2514ULL, }, + { 0x704f164d0e31380eULL, 0x4223041ca9423204ULL, }, + { 0x704f164d11311b06ULL, 0x0ff1880801033ea0ULL, }, + { 0x704f164d5e31574eULL, 0x181988d8a9170400ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, +}; + + reset_msa_registers(); + + gettimeofday(&start, NULL); + + for (i = 0; i < PATTERN_INPUTS_SHORT_COUNT; i++) { + for (j = 0; j < PATTERN_INPUTS_SHORT_COUNT; j++) { + do_msa_MOD_U_B(b128_pattern[i], b128_pattern[j], + b128_result[PATTERN_INPUTS_SHORT_COUNT * i + j]); + } + } + + for (i = 0; i < RANDOM_INPUTS_SHORT_COUNT; i++) { + for (j = 0; j < RANDOM_INPUTS_SHORT_COUNT; j++) { + do_msa_MOD_U_B(b128_random[i], b128_random[j], + b128_result[((PATTERN_INPUTS_SHORT_COUNT) * + (PATTERN_INPUTS_SHORT_COUNT)) + + RANDOM_INPUTS_SHORT_COUNT * i + j]); + } + } + + gettimeofday(&end, NULL); + + elapsed_time = (end.tv_sec - start.tv_sec) * 1000.0; + elapsed_time += (end.tv_usec - start.tv_usec) / 1000.0; + + ret = check_results(instruction_name, TEST_COUNT_TOTAL, elapsed_time, + &b128_result[0][0], &b128_expect[0][0]); + + return ret; +} diff --git a/tests/tcg/mips/user/ase/msa/int-modulo/test_msa_mod_u_d.c b/tests/tcg/mips/user/ase/msa/int-modulo/test_msa_mod_u_d.c new file mode 100644 index 0000000000..8aef84325f --- /dev/null +++ b/tests/tcg/mips/user/ase/msa/int-modulo/test_msa_mod_u_d.c @@ -0,0 +1,157 @@ +/* + * Test program for MSA instruction MOD_U.D + * + * Copyright (C) 2019 Wave Computing, Inc. + * Copyright (C) 2019 Aleksandar Markovic <amarkovic@wavecomp.com> + * Copyright (C) 2019 RT-RK Computer Based Systems LLC + * Copyright (C) 2019 Mateja Marjanovic <mateja.marjanovic@rt-rk.com> + * + * This program 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, see <https://www.gnu.org/licenses/>. + * + */ + +#include <sys/time.h> +#include <stdint.h> + +#include "../../../../include/wrappers_msa.h" +#include "../../../../include/test_inputs_128.h" +#include "../../../../include/test_utils_128.h" + +#define TEST_COUNT_TOTAL ( \ + (PATTERN_INPUTS_SHORT_COUNT) * (PATTERN_INPUTS_SHORT_COUNT) + \ + (RANDOM_INPUTS_SHORT_COUNT) * (RANDOM_INPUTS_SHORT_COUNT)) + + +int32_t main(void) +{ + char *instruction_name = "MOD_U.D"; + int32_t ret; + uint32_t i, j; + struct timeval start, end; + double elapsed_time; + + uint64_t b128_result[TEST_COUNT_TOTAL][2]; + uint64_t b128_expect[TEST_COUNT_TOTAL][2] = { + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, /* 0 */ + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, + { 0x5555555555555555ULL, 0x5555555555555555ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x3333333333333333ULL, 0x3333333333333333ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x1c71c71c71c71c71ULL, 0x1c71c71c71c71c73ULL, }, + { 0x0000000000000006ULL, 0x38e38e38e38e38e3ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, /* 8 */ + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, }, /* 16 */ + { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, }, + { 0x1111111111111111ULL, 0x1111111111111111ULL, }, + { 0xaaaaaaaaaaaaaaaaULL, 0x0000000000000001ULL, }, + { 0x0000000000000004ULL, 0xaaaaaaaaaaaaaaaaULL, }, + { 0x5555555555555555ULL, 0x5555555555555555ULL, }, /* 24 */ + { 0x5555555555555555ULL, 0x5555555555555555ULL, }, + { 0x5555555555555555ULL, 0x5555555555555555ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x5555555555555555ULL, 0x5555555555555555ULL, }, + { 0x2222222222222222ULL, 0x2222222222222222ULL, }, + { 0x5555555555555555ULL, 0x1c71c71c71c71c72ULL, }, + { 0x0000000000000002ULL, 0x5555555555555555ULL, }, + { 0xccccccccccccccccULL, 0xccccccccccccccccULL, }, /* 32 */ + { 0xccccccccccccccccULL, 0xccccccccccccccccULL, }, + { 0x2222222222222222ULL, 0x2222222222222222ULL, }, + { 0x2222222222222222ULL, 0x2222222222222222ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0xccccccccccccccccULL, 0x2222222222222223ULL, }, + { 0x05b05b05b05b05b5ULL, 0x05b05b05b05b05b0ULL, }, + { 0x3333333333333333ULL, 0x3333333333333333ULL, }, /* 40 */ + { 0x3333333333333333ULL, 0x3333333333333333ULL, }, + { 0x3333333333333333ULL, 0x3333333333333333ULL, }, + { 0x3333333333333333ULL, 0x3333333333333333ULL, }, + { 0x3333333333333333ULL, 0x3333333333333333ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x3333333333333333ULL, 0x3333333333333333ULL, }, + { 0x16c16c16c16c16c2ULL, 0x3333333333333333ULL, }, + { 0xe38e38e38e38e38eULL, 0x38e38e38e38e38e3ULL, }, /* 48 */ + { 0xe38e38e38e38e38eULL, 0x38e38e38e38e38e3ULL, }, + { 0x38e38e38e38e38e4ULL, 0x38e38e38e38e38e3ULL, }, + { 0x38e38e38e38e38e4ULL, 0x38e38e38e38e38e3ULL, }, + { 0x16c16c16c16c16c2ULL, 0x38e38e38e38e38e3ULL, }, + { 0x16c16c16c16c16c2ULL, 0x05b05b05b05b05b0ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000006ULL, 0x38e38e38e38e38e3ULL, }, + { 0x1c71c71c71c71c71ULL, 0xc71c71c71c71c71cULL, }, /* 56 */ + { 0x1c71c71c71c71c71ULL, 0xc71c71c71c71c71cULL, }, + { 0x1c71c71c71c71c71ULL, 0x1c71c71c71c71c72ULL, }, + { 0x1c71c71c71c71c71ULL, 0x1c71c71c71c71c72ULL, }, + { 0x1c71c71c71c71c71ULL, 0xc71c71c71c71c71cULL, }, + { 0x1c71c71c71c71c71ULL, 0x2d82d82d82d82d83ULL, }, + { 0x1c71c71c71c71c71ULL, 0x1c71c71c71c71c73ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, /* 64 */ + { 0x886ae6cc28625540ULL, 0x127fda10bebdb718ULL, }, + { 0x886ae6cc28625540ULL, 0x238e445f53508af8ULL, }, + { 0x181bd07eca3072f2ULL, 0x4b670b5efe7bb00cULL, }, + { 0x73531997253171c8ULL, 0x12f7bb1a153f52fcULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x4f6351b893c43b88ULL, 0x12f7bb1a153f52fcULL, }, + { 0x1b1fd3c89130026cULL, 0x12f7bb1a153f52fcULL, }, + { 0x23efc7de916d3640ULL, 0x27d8c6ffab2b2514ULL, }, /* 72 */ + { 0xac5aaeaab9cf8b80ULL, 0x01e950cb80ac7f1cULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x3c0b985d5b9da932ULL, 0x27d8c6ffab2b2514ULL, }, + { 0x704f164d5e31e24eULL, 0x428a7d79aac73294ULL, }, + { 0x704f164d5e31e24eULL, 0x092b6b2214879dbcULL, }, + { 0x704f164d5e31e24eULL, 0x166733d9a7c17364ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, +}; + + reset_msa_registers(); + + gettimeofday(&start, NULL); + + for (i = 0; i < PATTERN_INPUTS_SHORT_COUNT; i++) { + for (j = 0; j < PATTERN_INPUTS_SHORT_COUNT; j++) { + do_msa_MOD_U_D(b128_pattern[i], b128_pattern[j], + b128_result[PATTERN_INPUTS_SHORT_COUNT * i + j]); + } + } + + for (i = 0; i < RANDOM_INPUTS_SHORT_COUNT; i++) { + for (j = 0; j < RANDOM_INPUTS_SHORT_COUNT; j++) { + do_msa_MOD_U_D(b128_random[i], b128_random[j], + b128_result[((PATTERN_INPUTS_SHORT_COUNT) * + (PATTERN_INPUTS_SHORT_COUNT)) + + RANDOM_INPUTS_SHORT_COUNT * i + j]); + } + } + + gettimeofday(&end, NULL); + + elapsed_time = (end.tv_sec - start.tv_sec) * 1000.0; + elapsed_time += (end.tv_usec - start.tv_usec) / 1000.0; + + ret = check_results(instruction_name, TEST_COUNT_TOTAL, elapsed_time, + &b128_result[0][0], &b128_expect[0][0]); + + return ret; +} diff --git a/tests/tcg/mips/user/ase/msa/int-modulo/test_msa_mod_u_h.c b/tests/tcg/mips/user/ase/msa/int-modulo/test_msa_mod_u_h.c new file mode 100644 index 0000000000..ae5abb8e44 --- /dev/null +++ b/tests/tcg/mips/user/ase/msa/int-modulo/test_msa_mod_u_h.c @@ -0,0 +1,157 @@ +/* + * Test program for MSA instruction MOD_U.H + * + * Copyright (C) 2019 Wave Computing, Inc. + * Copyright (C) 2019 Aleksandar Markovic <amarkovic@wavecomp.com> + * Copyright (C) 2019 RT-RK Computer Based Systems LLC + * Copyright (C) 2019 Mateja Marjanovic <mateja.marjanovic@rt-rk.com> + * + * This program 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, see <https://www.gnu.org/licenses/>. + * + */ + +#include <sys/time.h> +#include <stdint.h> + +#include "../../../../include/wrappers_msa.h" +#include "../../../../include/test_inputs_128.h" +#include "../../../../include/test_utils_128.h" + +#define TEST_COUNT_TOTAL ( \ + (PATTERN_INPUTS_SHORT_COUNT) * (PATTERN_INPUTS_SHORT_COUNT) + \ + (RANDOM_INPUTS_SHORT_COUNT) * (RANDOM_INPUTS_SHORT_COUNT)) + + +int32_t main(void) +{ + char *instruction_name = "MOD_U.H"; + int32_t ret; + uint32_t i, j; + struct timeval start, end; + double elapsed_time; + + uint64_t b128_result[TEST_COUNT_TOTAL][2]; + uint64_t b128_expect[TEST_COUNT_TOTAL][2] = { + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, /* 0 */ + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, + { 0x5555555555555555ULL, 0x5555555555555555ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x3333333333333333ULL, 0x3333333333333333ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x1c711c7371c71c71ULL, 0x1c7371c71c711c73ULL, }, + { 0x000638e31c710006ULL, 0x38e31c71000638e3ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, /* 8 */ + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, }, /* 16 */ + { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, }, + { 0x1111111111111111ULL, 0x1111111111111111ULL, }, + { 0xaaaa00011c72aaaaULL, 0x00011c72aaaa0001ULL, }, + { 0x0004aaaa38e30004ULL, 0xaaaa38e30004aaaaULL, }, + { 0x5555555555555555ULL, 0x5555555555555555ULL, }, /* 24 */ + { 0x5555555555555555ULL, 0x5555555555555555ULL, }, + { 0x5555555555555555ULL, 0x5555555555555555ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x5555555555555555ULL, 0x5555555555555555ULL, }, + { 0x2222222222222222ULL, 0x2222222222222222ULL, }, + { 0x55551c7255555555ULL, 0x1c72555555551c72ULL, }, + { 0x0002555555550002ULL, 0x5555555500025555ULL, }, + { 0xccccccccccccccccULL, 0xccccccccccccccccULL, }, /* 32 */ + { 0xccccccccccccccccULL, 0xccccccccccccccccULL, }, + { 0x2222222222222222ULL, 0x2222222222222222ULL, }, + { 0x2222222222222222ULL, 0x2222222222222222ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0xcccc22233e94ccccULL, 0x22233e94cccc2223ULL, }, + { 0x05b505b05b0505b5ULL, 0x05b05b0505b505b0ULL, }, + { 0x3333333333333333ULL, 0x3333333333333333ULL, }, /* 40 */ + { 0x3333333333333333ULL, 0x3333333333333333ULL, }, + { 0x3333333333333333ULL, 0x3333333333333333ULL, }, + { 0x3333333333333333ULL, 0x3333333333333333ULL, }, + { 0x3333333333333333ULL, 0x3333333333333333ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x3333333333333333ULL, 0x3333333333333333ULL, }, + { 0x16c23333333316c2ULL, 0x3333333316c23333ULL, }, + { 0xe38e38e38e38e38eULL, 0x38e38e38e38e38e3ULL, }, /* 48 */ + { 0xe38e38e38e38e38eULL, 0x38e38e38e38e38e3ULL, }, + { 0x38e438e38e3838e4ULL, 0x38e38e3838e438e3ULL, }, + { 0x38e438e338e338e4ULL, 0x38e338e338e438e3ULL, }, + { 0x16c238e38e3816c2ULL, 0x38e38e3816c238e3ULL, }, + { 0x16c205b027d216c2ULL, 0x05b027d216c205b0ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x000638e31c710006ULL, 0x38e31c71000638e3ULL, }, + { 0x1c71c71c71c71c71ULL, 0xc71c71c71c71c71cULL, }, /* 56 */ + { 0x1c71c71c71c71c71ULL, 0xc71c71c71c71c71cULL, }, + { 0x1c711c7271c71c71ULL, 0x1c7271c71c711c72ULL, }, + { 0x1c711c721c721c71ULL, 0x1c721c721c711c72ULL, }, + { 0x1c71c71c71c71c71ULL, 0xc71c71c71c71c71cULL, }, + { 0x1c712d830b611c71ULL, 0x2d830b611c712d83ULL, }, + { 0x1c711c7371c71c71ULL, 0x1c7371c71c711c73ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, /* 64 */ + { 0x886a005028625540ULL, 0x12820b5e14c60a14ULL, }, + { 0x886a382228625540ULL, 0x238f0b5e53501bbcULL, }, + { 0x181b07ca28625540ULL, 0x4b670b5e5539b00cULL, }, + { 0x7354006325311c88ULL, 0x12f7053a153f52fcULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x4f6400634d933b88ULL, 0x12f7bb1a153f08d4ULL, }, + { 0x1b2000634d93c708ULL, 0x12f73242153f52fcULL, }, + { 0x23f0aeaa18473640ULL, 0x27d805c1ab2b2514ULL, }, /* 72 */ + { 0xac5a00411ea98b80ULL, 0x01ea0be501332514ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x3c0b128f5b9e8b80ULL, 0x27d83e2701e92514ULL, }, + { 0x704f164d0d6d37ceULL, 0x428a0070a9423294ULL, }, + { 0x704f0042109e1b46ULL, 0x093088d814893ca8ULL, }, + { 0x704f164d5e3156ceULL, 0x166988d8a9420428ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, +}; + + reset_msa_registers(); + + gettimeofday(&start, NULL); + + for (i = 0; i < PATTERN_INPUTS_SHORT_COUNT; i++) { + for (j = 0; j < PATTERN_INPUTS_SHORT_COUNT; j++) { + do_msa_MOD_U_H(b128_pattern[i], b128_pattern[j], + b128_result[PATTERN_INPUTS_SHORT_COUNT * i + j]); + } + } + + for (i = 0; i < RANDOM_INPUTS_SHORT_COUNT; i++) { + for (j = 0; j < RANDOM_INPUTS_SHORT_COUNT; j++) { + do_msa_MOD_U_H(b128_random[i], b128_random[j], + b128_result[((PATTERN_INPUTS_SHORT_COUNT) * + (PATTERN_INPUTS_SHORT_COUNT)) + + RANDOM_INPUTS_SHORT_COUNT * i + j]); + } + } + + gettimeofday(&end, NULL); + + elapsed_time = (end.tv_sec - start.tv_sec) * 1000.0; + elapsed_time += (end.tv_usec - start.tv_usec) / 1000.0; + + ret = check_results(instruction_name, TEST_COUNT_TOTAL, elapsed_time, + &b128_result[0][0], &b128_expect[0][0]); + + return ret; +} diff --git a/tests/tcg/mips/user/ase/msa/int-modulo/test_msa_mod_u_w.c b/tests/tcg/mips/user/ase/msa/int-modulo/test_msa_mod_u_w.c new file mode 100644 index 0000000000..da48929f4f --- /dev/null +++ b/tests/tcg/mips/user/ase/msa/int-modulo/test_msa_mod_u_w.c @@ -0,0 +1,157 @@ +/* + * Test program for MSA instruction MOD_U.W + * + * Copyright (C) 2019 Wave Computing, Inc. + * Copyright (C) 2019 Aleksandar Markovic <amarkovic@wavecomp.com> + * Copyright (C) 2019 RT-RK Computer Based Systems LLC + * Copyright (C) 2019 Mateja Marjanovic <mateja.marjanovic@rt-rk.com> + * + * This program 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, see <https://www.gnu.org/licenses/>. + * + */ + +#include <sys/time.h> +#include <stdint.h> + +#include "../../../../include/wrappers_msa.h" +#include "../../../../include/test_inputs_128.h" +#include "../../../../include/test_utils_128.h" + +#define TEST_COUNT_TOTAL ( \ + (PATTERN_INPUTS_SHORT_COUNT) * (PATTERN_INPUTS_SHORT_COUNT) + \ + (RANDOM_INPUTS_SHORT_COUNT) * (RANDOM_INPUTS_SHORT_COUNT)) + + +int32_t main(void) +{ + char *instruction_name = "MOD_U.W"; + int32_t ret; + uint32_t i, j; + struct timeval start, end; + double elapsed_time; + + uint64_t b128_result[TEST_COUNT_TOTAL][2]; + uint64_t b128_expect[TEST_COUNT_TOTAL][2] = { + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, /* 0 */ + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, + { 0x5555555555555555ULL, 0x5555555555555555ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x3333333333333333ULL, 0x3333333333333333ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x1c71c71c71c71c71ULL, 0x1c71c71f1c71c71cULL, }, + { 0x000000031c71c71dULL, 0x38e38e3800000003ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, /* 8 */ + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, }, /* 16 */ + { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, }, + { 0x1111111111111111ULL, 0x1111111111111111ULL, }, + { 0xaaaaaaaa1c71c71cULL, 0x00000002aaaaaaaaULL, }, + { 0x0000000238e38e39ULL, 0xaaaaaaaa00000002ULL, }, + { 0x5555555555555555ULL, 0x5555555555555555ULL, }, /* 24 */ + { 0x5555555555555555ULL, 0x5555555555555555ULL, }, + { 0x5555555555555555ULL, 0x5555555555555555ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x5555555555555555ULL, 0x5555555555555555ULL, }, + { 0x2222222222222222ULL, 0x2222222222222222ULL, }, + { 0x5555555555555555ULL, 0x1c71c71d55555555ULL, }, + { 0x0000000155555555ULL, 0x5555555500000001ULL, }, + { 0xccccccccccccccccULL, 0xccccccccccccccccULL, }, /* 32 */ + { 0xccccccccccccccccULL, 0xccccccccccccccccULL, }, + { 0x2222222222222222ULL, 0x2222222222222222ULL, }, + { 0x2222222222222222ULL, 0x2222222222222222ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0xcccccccc3e93e93eULL, 0x22222224ccccccccULL, }, + { 0x05b05b085b05b05bULL, 0x05b05b0505b05b08ULL, }, + { 0x3333333333333333ULL, 0x3333333333333333ULL, }, /* 40 */ + { 0x3333333333333333ULL, 0x3333333333333333ULL, }, + { 0x3333333333333333ULL, 0x3333333333333333ULL, }, + { 0x3333333333333333ULL, 0x3333333333333333ULL, }, + { 0x3333333333333333ULL, 0x3333333333333333ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x3333333333333333ULL, 0x3333333333333333ULL, }, + { 0x16c16c1733333333ULL, 0x3333333316c16c17ULL, }, + { 0xe38e38e38e38e38eULL, 0x38e38e38e38e38e3ULL, }, /* 48 */ + { 0xe38e38e38e38e38eULL, 0x38e38e38e38e38e3ULL, }, + { 0x38e38e398e38e38eULL, 0x38e38e3838e38e39ULL, }, + { 0x38e38e3938e38e39ULL, 0x38e38e3838e38e39ULL, }, + { 0x16c16c178e38e38eULL, 0x38e38e3816c16c17ULL, }, + { 0x16c16c1727d27d28ULL, 0x05b05b0516c16c17ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x000000031c71c71dULL, 0x38e38e3800000003ULL, }, + { 0x1c71c71c71c71c71ULL, 0xc71c71c71c71c71cULL, }, /* 56 */ + { 0x1c71c71c71c71c71ULL, 0xc71c71c71c71c71cULL, }, + { 0x1c71c71c71c71c71ULL, 0x1c71c71d1c71c71cULL, }, + { 0x1c71c71c1c71c71cULL, 0x1c71c71d1c71c71cULL, }, + { 0x1c71c71c71c71c71ULL, 0xc71c71c71c71c71cULL, }, + { 0x1c71c71c0b60b60bULL, 0x2d82d82e1c71c71cULL, }, + { 0x1c71c71c71c71c71ULL, 0x1c71c71f1c71c71cULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, /* 64 */ + { 0x886ae6cc28625540ULL, 0x127fda1014c31f38ULL, }, + { 0x886ae6cc28625540ULL, 0x238e445f53508af8ULL, }, + { 0x181bd07f28625540ULL, 0x4b670b5e5538cd6cULL, }, + { 0x73531997253171c8ULL, 0x12f7bb1a153f52fcULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x4f6351b94d93c708ULL, 0x12f7bb1a153f52fcULL, }, + { 0x1b1fd3c94d93c708ULL, 0x12f7bb1a153f52fcULL, }, + { 0x23efc7de18463680ULL, 0x27d8c6ffab2b2514ULL, }, /* 72 */ + { 0xac5aaeaa1ea7fd70ULL, 0x01e950cb01308d34ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x3c0b985d5b9da932ULL, 0x27d8c6ff01e84274ULL, }, + { 0x704f164d0d6d37ceULL, 0x428a7d7aa942e2a0ULL, }, + { 0x704f164d109e1b46ULL, 0x092b6b2214879dbcULL, }, + { 0x704f164d5e31e24eULL, 0x166733dba942e2a0ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, +}; + + reset_msa_registers(); + + gettimeofday(&start, NULL); + + for (i = 0; i < PATTERN_INPUTS_SHORT_COUNT; i++) { + for (j = 0; j < PATTERN_INPUTS_SHORT_COUNT; j++) { + do_msa_MOD_U_W(b128_pattern[i], b128_pattern[j], + b128_result[PATTERN_INPUTS_SHORT_COUNT * i + j]); + } + } + + for (i = 0; i < RANDOM_INPUTS_SHORT_COUNT; i++) { + for (j = 0; j < RANDOM_INPUTS_SHORT_COUNT; j++) { + do_msa_MOD_U_W(b128_random[i], b128_random[j], + b128_result[((PATTERN_INPUTS_SHORT_COUNT) * + (PATTERN_INPUTS_SHORT_COUNT)) + + RANDOM_INPUTS_SHORT_COUNT * i + j]); + } + } + + gettimeofday(&end, NULL); + + elapsed_time = (end.tv_sec - start.tv_sec) * 1000.0; + elapsed_time += (end.tv_usec - start.tv_usec) / 1000.0; + + ret = check_results(instruction_name, TEST_COUNT_TOTAL, elapsed_time, + &b128_result[0][0], &b128_expect[0][0]); + + return ret; +} diff --git a/tests/tcg/mips/user/ase/msa/int-multiply/test_msa_mulv_b.c b/tests/tcg/mips/user/ase/msa/int-multiply/test_msa_mulv_b.c index 6beeda906d..fa9753cc75 100644 --- a/tests/tcg/mips/user/ase/msa/int-multiply/test_msa_mulv_b.c +++ b/tests/tcg/mips/user/ase/msa/int-multiply/test_msa_mulv_b.c @@ -1,8 +1,10 @@ /* * Test program for MSA instruction MULV.B * - * Copyright (C) 2018 Wave Computing, Inc. - * Copyright (C) 2018 Mateja Marjanovic <mateja.marjanovic@rt-rk.com> + * Copyright (C) 2019 Wave Computing, Inc. + * Copyright (C) 2019 Aleksandar Markovic <amarkovic@wavecomp.com> + * Copyright (C) 2019 RT-RK Computer Based Systems LLC + * Copyright (C) 2019 Mateja Marjanovic <mateja.marjanovic@rt-rk.com> * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -23,8 +25,8 @@ #include <stdint.h> #include "../../../../include/wrappers_msa.h" -#include "../../../../include/test_inputs.h" -#include "../../../../include/test_utils.h" +#include "../../../../include/test_inputs_128.h" +#include "../../../../include/test_utils_128.h" #define TEST_COUNT_TOTAL ( \ (PATTERN_INPUTS_SHORT_COUNT) * (PATTERN_INPUTS_SHORT_COUNT) + \ @@ -119,8 +121,12 @@ int32_t main(void) { 0x40c6f422ee9fb600ULL, 0x7b583028e316aa80ULL, }, { 0x80b6c45cb0c20a80ULL, 0x4ff7d850aeb66080ULL, }, { 0xd0a200c74623ae70ULL, 0xea8758f0dd3e6480ULL, }, + { 0x40c6f422ee9fb600ULL, 0x7b583028e316aa80ULL, }, + { 0x0061e429846184c4ULL, 0xa9e1404091048400ULL, }, }; + reset_msa_registers(); + gettimeofday(&start, NULL); for (i = 0; i < PATTERN_INPUTS_SHORT_COUNT; i++) { diff --git a/tests/tcg/mips/user/ase/msa/int-multiply/test_msa_mulv_d.c b/tests/tcg/mips/user/ase/msa/int-multiply/test_msa_mulv_d.c index 3205d4b378..2503467bf2 100644 --- a/tests/tcg/mips/user/ase/msa/int-multiply/test_msa_mulv_d.c +++ b/tests/tcg/mips/user/ase/msa/int-multiply/test_msa_mulv_d.c @@ -1,8 +1,10 @@ /* * Test program for MSA instruction MULV.D * - * Copyright (C) 2018 Wave Computing, Inc. - * Copyright (C) 2018 Mateja Marjanovic <mateja.marjanovic@rt-rk.com> + * Copyright (C) 2019 Wave Computing, Inc. + * Copyright (C) 2019 Aleksandar Markovic <amarkovic@wavecomp.com> + * Copyright (C) 2019 RT-RK Computer Based Systems LLC + * Copyright (C) 2019 Mateja Marjanovic <mateja.marjanovic@rt-rk.com> * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -23,8 +25,8 @@ #include <stdint.h> #include "../../../../include/wrappers_msa.h" -#include "../../../../include/test_inputs.h" -#include "../../../../include/test_utils.h" +#include "../../../../include/test_inputs_128.h" +#include "../../../../include/test_utils_128.h" #define TEST_COUNT_TOTAL ( \ (PATTERN_INPUTS_SHORT_COUNT) * (PATTERN_INPUTS_SHORT_COUNT) + \ @@ -119,8 +121,12 @@ int32_t main(void) { 0x76a5ab8089e38100ULL, 0xa1019a60d4dad480ULL, }, { 0xfbe1883aee787980ULL, 0x821d25438dd09f80ULL, }, { 0xedbf72842143b470ULL, 0x7f8223caefce5580ULL, }, + { 0x76a5ab8089e38100ULL, 0xa1019a60d4dad480ULL, }, + { 0x4bb436d5b1e9cfc4ULL, 0x12d1ceb0e31ee400ULL, }, }; + reset_msa_registers(); + gettimeofday(&start, NULL); for (i = 0; i < PATTERN_INPUTS_SHORT_COUNT; i++) { diff --git a/tests/tcg/mips/user/ase/msa/int-multiply/test_msa_mulv_h.c b/tests/tcg/mips/user/ase/msa/int-multiply/test_msa_mulv_h.c index e7bd985ae1..5162678671 100644 --- a/tests/tcg/mips/user/ase/msa/int-multiply/test_msa_mulv_h.c +++ b/tests/tcg/mips/user/ase/msa/int-multiply/test_msa_mulv_h.c @@ -1,8 +1,10 @@ /* * Test program for MSA instruction MULV.H * - * Copyright (C) 2018 Wave Computing, Inc. - * Copyright (C) 2018 Mateja Marjanovic <mateja.marjanovic@rt-rk.com> + * Copyright (C) 2019 Wave Computing, Inc. + * Copyright (C) 2019 Aleksandar Markovic <amarkovic@wavecomp.com> + * Copyright (C) 2019 RT-RK Computer Based Systems LLC + * Copyright (C) 2019 Mateja Marjanovic <mateja.marjanovic@rt-rk.com> * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -23,8 +25,8 @@ #include <stdint.h> #include "../../../../include/wrappers_msa.h" -#include "../../../../include/test_inputs.h" -#include "../../../../include/test_utils.h" +#include "../../../../include/test_inputs_128.h" +#include "../../../../include/test_utils_128.h" #define TEST_COUNT_TOTAL ( \ (PATTERN_INPUTS_SHORT_COUNT) * (PATTERN_INPUTS_SHORT_COUNT) + \ @@ -119,8 +121,12 @@ int32_t main(void) { 0x8fc62522929f8100ULL, 0x7a585f288416d480ULL, }, { 0x78b6f35cb6c27980ULL, 0xb6f78750ceb69f80ULL, }, { 0xcfa29fc7d323b470ULL, 0xe587adf0113e5580ULL, }, + { 0x8fc62522929f8100ULL, 0x7a585f288416d480ULL, }, + { 0x386153290561cfc4ULL, 0x5ce136403504e400ULL, }, }; + reset_msa_registers(); + gettimeofday(&start, NULL); for (i = 0; i < PATTERN_INPUTS_SHORT_COUNT; i++) { diff --git a/tests/tcg/mips/user/ase/msa/int-multiply/test_msa_mulv_w.c b/tests/tcg/mips/user/ase/msa/int-multiply/test_msa_mulv_w.c index 9c318b3fbb..7e2ff6609f 100644 --- a/tests/tcg/mips/user/ase/msa/int-multiply/test_msa_mulv_w.c +++ b/tests/tcg/mips/user/ase/msa/int-multiply/test_msa_mulv_w.c @@ -1,8 +1,10 @@ /* * Test program for MSA instruction MULV.W * - * Copyright (C) 2018 Wave Computing, Inc. - * Copyright (C) 2018 Mateja Marjanovic <mateja.marjanovic@rt-rk.com> + * Copyright (C) 2019 Wave Computing, Inc. + * Copyright (C) 2019 Aleksandar Markovic <amarkovic@wavecomp.com> + * Copyright (C) 2019 RT-RK Computer Based Systems LLC + * Copyright (C) 2019 Mateja Marjanovic <mateja.marjanovic@rt-rk.com> * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -23,8 +25,8 @@ #include <stdint.h> #include "../../../../include/wrappers_msa.h" -#include "../../../../include/test_inputs.h" -#include "../../../../include/test_utils.h" +#include "../../../../include/test_inputs_128.h" +#include "../../../../include/test_utils_128.h" #define TEST_COUNT_TOTAL ( \ (PATTERN_INPUTS_SHORT_COUNT) * (PATTERN_INPUTS_SHORT_COUNT) + \ @@ -119,8 +121,12 @@ int32_t main(void) { 0xe8bf252289e38100ULL, 0x91ae5f28d4dad480ULL, }, { 0xb0f0f35cee787980ULL, 0xd67987508dd09f80ULL, }, { 0x7abb9fc72143b470ULL, 0x11e5adf0efce5580ULL, }, + { 0xe8bf252289e38100ULL, 0x91ae5f28d4dad480ULL, }, + { 0x25775329b1e9cfc4ULL, 0xdfd63640e31ee400ULL, }, }; + reset_msa_registers(); + gettimeofday(&start, NULL); for (i = 0; i < PATTERN_INPUTS_SHORT_COUNT; i++) { diff --git a/tests/tcg/mips/user/ase/msa/int-subtract/test_msa_asub_s_b.c b/tests/tcg/mips/user/ase/msa/int-subtract/test_msa_asub_s_b.c new file mode 100644 index 0000000000..f583702a6b --- /dev/null +++ b/tests/tcg/mips/user/ase/msa/int-subtract/test_msa_asub_s_b.c @@ -0,0 +1,157 @@ +/* + * Test program for MSA instruction ASUB_S.B + * + * Copyright (C) 2019 Wave Computing, Inc. + * Copyright (C) 2019 Aleksandar Markovic <amarkovic@wavecomp.com> + * Copyright (C) 2019 RT-RK Computer Based Systems LLC + * Copyright (C) 2019 Mateja Marjanovic <mateja.marjanovic@rt-rk.com> + * + * This program 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, see <https://www.gnu.org/licenses/>. + * + */ + +#include <sys/time.h> +#include <stdint.h> + +#include "../../../../include/wrappers_msa.h" +#include "../../../../include/test_inputs_128.h" +#include "../../../../include/test_utils_128.h" + +#define TEST_COUNT_TOTAL ( \ + (PATTERN_INPUTS_SHORT_COUNT) * (PATTERN_INPUTS_SHORT_COUNT) + \ + (RANDOM_INPUTS_SHORT_COUNT) * (RANDOM_INPUTS_SHORT_COUNT)) + + +int32_t main(void) +{ + char *instruction_name = "ASUB_S.B"; + int32_t ret; + uint32_t i, j; + struct timeval start, end; + double elapsed_time; + + uint64_t b128_result[TEST_COUNT_TOTAL][2]; + uint64_t b128_expect[TEST_COUNT_TOTAL][2] = { + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, /* 0 */ + { 0x0101010101010101ULL, 0x0101010101010101ULL, }, + { 0x5555555555555555ULL, 0x5555555555555555ULL, }, + { 0x5656565656565656ULL, 0x5656565656565656ULL, }, + { 0x3333333333333333ULL, 0x3333333333333333ULL, }, + { 0x3434343434343434ULL, 0x3434343434343434ULL, }, + { 0x1c71391c71391c71ULL, 0x391c71391c71391cULL, }, + { 0x1d72381d72381d72ULL, 0x381d72381d72381dULL, }, + { 0x0101010101010101ULL, 0x0101010101010101ULL, }, /* 8 */ + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x5656565656565656ULL, 0x5656565656565656ULL, }, + { 0x5555555555555555ULL, 0x5555555555555555ULL, }, + { 0x3434343434343434ULL, 0x3434343434343434ULL, }, + { 0x3333333333333333ULL, 0x3333333333333333ULL, }, + { 0x1d72381d72381d72ULL, 0x381d72381d72381dULL, }, + { 0x1c71391c71391c71ULL, 0x391c71391c71391cULL, }, + { 0x5555555555555555ULL, 0x5555555555555555ULL, }, /* 16 */ + { 0x5656565656565656ULL, 0x5656565656565656ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0xababababababababULL, 0xababababababababULL, }, + { 0x2222222222222222ULL, 0x2222222222222222ULL, }, + { 0x8989898989898989ULL, 0x8989898989898989ULL, }, + { 0x391c8e391c8e391cULL, 0x8e391c8e391c8e39ULL, }, + { 0x72c71d72c71d72c7ULL, 0x1d72c71d72c71d72ULL, }, + { 0x5656565656565656ULL, 0x5656565656565656ULL, }, /* 24 */ + { 0x5555555555555555ULL, 0x5555555555555555ULL, }, + { 0xababababababababULL, 0xababababababababULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x8989898989898989ULL, 0x8989898989898989ULL, }, + { 0x2222222222222222ULL, 0x2222222222222222ULL, }, + { 0x72c71d72c71d72c7ULL, 0x1d72c71d72c71d72ULL, }, + { 0x391c8e391c8e391cULL, 0x8e391c8e391c8e39ULL, }, + { 0x3333333333333333ULL, 0x3333333333333333ULL, }, /* 32 */ + { 0x3434343434343434ULL, 0x3434343434343434ULL, }, + { 0x2222222222222222ULL, 0x2222222222222222ULL, }, + { 0x8989898989898989ULL, 0x8989898989898989ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x6767676767676767ULL, 0x6767676767676767ULL, }, + { 0x173e6c173e6c173eULL, 0x6c173e6c173e6c17ULL, }, + { 0x50a50550a50550a5ULL, 0x0550a50550a50550ULL, }, + { 0x3434343434343434ULL, 0x3434343434343434ULL, }, /* 40 */ + { 0x3333333333333333ULL, 0x3333333333333333ULL, }, + { 0x8989898989898989ULL, 0x8989898989898989ULL, }, + { 0x2222222222222222ULL, 0x2222222222222222ULL, }, + { 0x6767676767676767ULL, 0x6767676767676767ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x50a50550a50550a5ULL, 0x0550a50550a50550ULL, }, + { 0x173e6c173e6c173eULL, 0x6c173e6c173e6c17ULL, }, + { 0x1c71391c71391c71ULL, 0x391c71391c71391cULL, }, /* 48 */ + { 0x1d72381d72381d72ULL, 0x381d72381d72381dULL, }, + { 0x391c8e391c8e391cULL, 0x8e391c8e391c8e39ULL, }, + { 0x72c71d72c71d72c7ULL, 0x1d72c71d72c71d72ULL, }, + { 0x173e6c173e6c173eULL, 0x6c173e6c173e6c17ULL, }, + { 0x50a50550a50550a5ULL, 0x0550a50550a50550ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x39e37139e37139e3ULL, 0x7139e37139e37139ULL, }, + { 0x1d72381d72381d72ULL, 0x381d72381d72381dULL, }, /* 56 */ + { 0x1c71391c71391c71ULL, 0x391c71391c71391cULL, }, + { 0x72c71d72c71d72c7ULL, 0x1d72c71d72c71d72ULL, }, + { 0x391c8e391c8e391cULL, 0x8e391c8e391c8e39ULL, }, + { 0x50a50550a50550a5ULL, 0x0550a50550a50550ULL, }, + { 0x173e6c173e6c173eULL, 0x6c173e6c173e6c17ULL, }, + { 0x39e37139e37139e3ULL, 0x7139e37139e37139ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, /* 64 */ + { 0x73ac1a9725cf8e38ULL, 0x39705044173ca210ULL, }, + { 0x241038226f93cac0ULL, 0x248f455f53507508ULL, }, + { 0xe81b30813631730eULL, 0xbe7683865539326cULL, }, + { 0x73ac1a9725cf8e38ULL, 0x39705044173ca210ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x4f9c52b9943c3c88ULL, 0x151f0b1b6a142d18ULL, }, + { 0x75911616119e1b46ULL, 0x850633426c03705cULL, }, + { 0x241038226f93cac0ULL, 0x248f455f53507508ULL, }, /* 72 */ + { 0x4f9c52b9943c3c88ULL, 0x151f0b1b6a142d18ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0xc40b68a3a56257ceULL, 0x9a193e2702174374ULL, }, + { 0xe81b30813631730eULL, 0xbe7683865539326cULL, }, + { 0x75911616119e1b46ULL, 0x850633426c03705cULL, }, + { 0xc40b68a3a56257ceULL, 0x9a193e2702174374ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, +}; + + reset_msa_registers(); + + gettimeofday(&start, NULL); + + for (i = 0; i < PATTERN_INPUTS_SHORT_COUNT; i++) { + for (j = 0; j < PATTERN_INPUTS_SHORT_COUNT; j++) { + do_msa_ASUB_S_B(b128_pattern[i], b128_pattern[j], + b128_result[PATTERN_INPUTS_SHORT_COUNT * i + j]); + } + } + + for (i = 0; i < RANDOM_INPUTS_SHORT_COUNT; i++) { + for (j = 0; j < RANDOM_INPUTS_SHORT_COUNT; j++) { + do_msa_ASUB_S_B(b128_random[i], b128_random[j], + b128_result[((PATTERN_INPUTS_SHORT_COUNT) * + (PATTERN_INPUTS_SHORT_COUNT)) + + RANDOM_INPUTS_SHORT_COUNT * i + j]); + } + } + + gettimeofday(&end, NULL); + + elapsed_time = (end.tv_sec - start.tv_sec) * 1000.0; + elapsed_time += (end.tv_usec - start.tv_usec) / 1000.0; + + ret = check_results(instruction_name, TEST_COUNT_TOTAL, elapsed_time, + &b128_result[0][0], &b128_expect[0][0]); + + return ret; +} diff --git a/tests/tcg/mips/user/ase/msa/int-subtract/test_msa_asub_s_d.c b/tests/tcg/mips/user/ase/msa/int-subtract/test_msa_asub_s_d.c new file mode 100644 index 0000000000..a9ae576610 --- /dev/null +++ b/tests/tcg/mips/user/ase/msa/int-subtract/test_msa_asub_s_d.c @@ -0,0 +1,157 @@ +/* + * Test program for MSA instruction ASUB_S.D + * + * Copyright (C) 2019 Wave Computing, Inc. + * Copyright (C) 2019 Aleksandar Markovic <amarkovic@wavecomp.com> + * Copyright (C) 2019 RT-RK Computer Based Systems LLC + * Copyright (C) 2019 Mateja Marjanovic <mateja.marjanovic@rt-rk.com> + * + * This program 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, see <https://www.gnu.org/licenses/>. + * + */ + +#include <sys/time.h> +#include <stdint.h> + +#include "../../../../include/wrappers_msa.h" +#include "../../../../include/test_inputs_128.h" +#include "../../../../include/test_utils_128.h" + +#define TEST_COUNT_TOTAL ( \ + (PATTERN_INPUTS_SHORT_COUNT) * (PATTERN_INPUTS_SHORT_COUNT) + \ + (RANDOM_INPUTS_SHORT_COUNT) * (RANDOM_INPUTS_SHORT_COUNT)) + + +int32_t main(void) +{ + char *instruction_name = "ASUB_S.D"; + int32_t ret; + uint32_t i, j; + struct timeval start, end; + double elapsed_time; + + uint64_t b128_result[TEST_COUNT_TOTAL][2]; + uint64_t b128_expect[TEST_COUNT_TOTAL][2] = { + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, /* 0 */ + { 0x0000000000000001ULL, 0x0000000000000001ULL, }, + { 0x5555555555555555ULL, 0x5555555555555555ULL, }, + { 0x5555555555555556ULL, 0x5555555555555556ULL, }, + { 0x3333333333333333ULL, 0x3333333333333333ULL, }, + { 0x3333333333333334ULL, 0x3333333333333334ULL, }, + { 0x1c71c71c71c71c71ULL, 0x38e38e38e38e38e4ULL, }, + { 0x1c71c71c71c71c72ULL, 0x38e38e38e38e38e3ULL, }, + { 0x0000000000000001ULL, 0x0000000000000001ULL, }, /* 8 */ + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x5555555555555556ULL, 0x5555555555555556ULL, }, + { 0x5555555555555555ULL, 0x5555555555555555ULL, }, + { 0x3333333333333334ULL, 0x3333333333333334ULL, }, + { 0x3333333333333333ULL, 0x3333333333333333ULL, }, + { 0x1c71c71c71c71c72ULL, 0x38e38e38e38e38e3ULL, }, + { 0x1c71c71c71c71c71ULL, 0x38e38e38e38e38e4ULL, }, + { 0x5555555555555555ULL, 0x5555555555555555ULL, }, /* 16 */ + { 0x5555555555555556ULL, 0x5555555555555556ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0xaaaaaaaaaaaaaaabULL, 0xaaaaaaaaaaaaaaabULL, }, + { 0x2222222222222222ULL, 0x2222222222222222ULL, }, + { 0x8888888888888889ULL, 0x8888888888888889ULL, }, + { 0x38e38e38e38e38e4ULL, 0x8e38e38e38e38e39ULL, }, + { 0x71c71c71c71c71c7ULL, 0x1c71c71c71c71c72ULL, }, + { 0x5555555555555556ULL, 0x5555555555555556ULL, }, /* 24 */ + { 0x5555555555555555ULL, 0x5555555555555555ULL, }, + { 0xaaaaaaaaaaaaaaabULL, 0xaaaaaaaaaaaaaaabULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x8888888888888889ULL, 0x8888888888888889ULL, }, + { 0x2222222222222222ULL, 0x2222222222222222ULL, }, + { 0x71c71c71c71c71c7ULL, 0x1c71c71c71c71c72ULL, }, + { 0x38e38e38e38e38e4ULL, 0x8e38e38e38e38e39ULL, }, + { 0x3333333333333333ULL, 0x3333333333333333ULL, }, /* 32 */ + { 0x3333333333333334ULL, 0x3333333333333334ULL, }, + { 0x2222222222222222ULL, 0x2222222222222222ULL, }, + { 0x8888888888888889ULL, 0x8888888888888889ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x6666666666666667ULL, 0x6666666666666667ULL, }, + { 0x16c16c16c16c16c2ULL, 0x6c16c16c16c16c17ULL, }, + { 0x4fa4fa4fa4fa4fa5ULL, 0x05b05b05b05b05b0ULL, }, + { 0x3333333333333334ULL, 0x3333333333333334ULL, }, /* 40 */ + { 0x3333333333333333ULL, 0x3333333333333333ULL, }, + { 0x8888888888888889ULL, 0x8888888888888889ULL, }, + { 0x2222222222222222ULL, 0x2222222222222222ULL, }, + { 0x6666666666666667ULL, 0x6666666666666667ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x4fa4fa4fa4fa4fa5ULL, 0x05b05b05b05b05b0ULL, }, + { 0x16c16c16c16c16c2ULL, 0x6c16c16c16c16c17ULL, }, + { 0x1c71c71c71c71c71ULL, 0x38e38e38e38e38e4ULL, }, /* 48 */ + { 0x1c71c71c71c71c72ULL, 0x38e38e38e38e38e3ULL, }, + { 0x38e38e38e38e38e4ULL, 0x8e38e38e38e38e39ULL, }, + { 0x71c71c71c71c71c7ULL, 0x1c71c71c71c71c72ULL, }, + { 0x16c16c16c16c16c2ULL, 0x6c16c16c16c16c17ULL, }, + { 0x4fa4fa4fa4fa4fa5ULL, 0x05b05b05b05b05b0ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x38e38e38e38e38e3ULL, 0x71c71c71c71c71c7ULL, }, + { 0x1c71c71c71c71c72ULL, 0x38e38e38e38e38e3ULL, }, /* 56 */ + { 0x1c71c71c71c71c71ULL, 0x38e38e38e38e38e4ULL, }, + { 0x71c71c71c71c71c7ULL, 0x1c71c71c71c71c72ULL, }, + { 0x38e38e38e38e38e4ULL, 0x8e38e38e38e38e39ULL, }, + { 0x4fa4fa4fa4fa4fa5ULL, 0x05b05b05b05b05b0ULL, }, + { 0x16c16c16c16c16c2ULL, 0x6c16c16c16c16c17ULL, }, + { 0x38e38e38e38e38e3ULL, 0x71c71c71c71c71c7ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, /* 64 */ + { 0x73531997253171c8ULL, 0x386f5044e93c5d10ULL, }, + { 0x23efc7de916d3640ULL, 0x238e445f53508af8ULL, }, + { 0xe7e42f8135cf8d0eULL, 0xbd7582865538cd6cULL, }, + { 0x73531997253171c8ULL, 0x386f5044e93c5d10ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x4f6351b893c43b88ULL, 0x14e10be595ebd218ULL, }, + { 0x749115ea109e1b46ULL, 0x850632416bfc705cULL, }, + { 0x23efc7de916d3640ULL, 0x238e445f53508af8ULL, }, /* 72 */ + { 0x4f6351b893c43b88ULL, 0x14e10be595ebd218ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0xc3f467a2a46256ceULL, 0x99e73e2701e84274ULL, }, + { 0xe7e42f8135cf8d0eULL, 0xbd7582865538cd6cULL, }, + { 0x749115ea109e1b46ULL, 0x850632416bfc705cULL, }, + { 0xc3f467a2a46256ceULL, 0x99e73e2701e84274ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, +}; + + reset_msa_registers(); + + gettimeofday(&start, NULL); + + for (i = 0; i < PATTERN_INPUTS_SHORT_COUNT; i++) { + for (j = 0; j < PATTERN_INPUTS_SHORT_COUNT; j++) { + do_msa_ASUB_S_D(b128_pattern[i], b128_pattern[j], + b128_result[PATTERN_INPUTS_SHORT_COUNT * i + j]); + } + } + + for (i = 0; i < RANDOM_INPUTS_SHORT_COUNT; i++) { + for (j = 0; j < RANDOM_INPUTS_SHORT_COUNT; j++) { + do_msa_ASUB_S_D(b128_random[i], b128_random[j], + b128_result[((PATTERN_INPUTS_SHORT_COUNT) * + (PATTERN_INPUTS_SHORT_COUNT)) + + RANDOM_INPUTS_SHORT_COUNT * i + j]); + } + } + + gettimeofday(&end, NULL); + + elapsed_time = (end.tv_sec - start.tv_sec) * 1000.0; + elapsed_time += (end.tv_usec - start.tv_usec) / 1000.0; + + ret = check_results(instruction_name, TEST_COUNT_TOTAL, elapsed_time, + &b128_result[0][0], &b128_expect[0][0]); + + return ret; +} diff --git a/tests/tcg/mips/user/ase/msa/int-subtract/test_msa_asub_s_h.c b/tests/tcg/mips/user/ase/msa/int-subtract/test_msa_asub_s_h.c new file mode 100644 index 0000000000..8c193b6705 --- /dev/null +++ b/tests/tcg/mips/user/ase/msa/int-subtract/test_msa_asub_s_h.c @@ -0,0 +1,157 @@ +/* + * Test program for MSA instruction ASUB_S.H + * + * Copyright (C) 2019 Wave Computing, Inc. + * Copyright (C) 2019 Aleksandar Markovic <amarkovic@wavecomp.com> + * Copyright (C) 2019 RT-RK Computer Based Systems LLC + * Copyright (C) 2019 Mateja Marjanovic <mateja.marjanovic@rt-rk.com> + * + * This program 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, see <https://www.gnu.org/licenses/>. + * + */ + +#include <sys/time.h> +#include <stdint.h> + +#include "../../../../include/wrappers_msa.h" +#include "../../../../include/test_inputs_128.h" +#include "../../../../include/test_utils_128.h" + +#define TEST_COUNT_TOTAL ( \ + (PATTERN_INPUTS_SHORT_COUNT) * (PATTERN_INPUTS_SHORT_COUNT) + \ + (RANDOM_INPUTS_SHORT_COUNT) * (RANDOM_INPUTS_SHORT_COUNT)) + + +int32_t main(void) +{ + char *instruction_name = "ASUB_S.H"; + int32_t ret; + uint32_t i, j; + struct timeval start, end; + double elapsed_time; + + uint64_t b128_result[TEST_COUNT_TOTAL][2]; + uint64_t b128_expect[TEST_COUNT_TOTAL][2] = { + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, /* 0 */ + { 0x0001000100010001ULL, 0x0001000100010001ULL, }, + { 0x5555555555555555ULL, 0x5555555555555555ULL, }, + { 0x5556555655565556ULL, 0x5556555655565556ULL, }, + { 0x3333333333333333ULL, 0x3333333333333333ULL, }, + { 0x3334333433343334ULL, 0x3334333433343334ULL, }, + { 0x1c7138e471c71c71ULL, 0x38e471c71c7138e4ULL, }, + { 0x1c7238e371c81c72ULL, 0x38e371c81c7238e3ULL, }, + { 0x0001000100010001ULL, 0x0001000100010001ULL, }, /* 8 */ + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x5556555655565556ULL, 0x5556555655565556ULL, }, + { 0x5555555555555555ULL, 0x5555555555555555ULL, }, + { 0x3334333433343334ULL, 0x3334333433343334ULL, }, + { 0x3333333333333333ULL, 0x3333333333333333ULL, }, + { 0x1c7238e371c81c72ULL, 0x38e371c81c7238e3ULL, }, + { 0x1c7138e471c71c71ULL, 0x38e471c71c7138e4ULL, }, + { 0x5555555555555555ULL, 0x5555555555555555ULL, }, /* 16 */ + { 0x5556555655565556ULL, 0x5556555655565556ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0xaaabaaabaaabaaabULL, 0xaaabaaabaaabaaabULL, }, + { 0x2222222222222222ULL, 0x2222222222222222ULL, }, + { 0x8889888988898889ULL, 0x8889888988898889ULL, }, + { 0x38e48e391c7238e4ULL, 0x8e391c7238e48e39ULL, }, + { 0x71c71c72c71d71c7ULL, 0x1c72c71d71c71c72ULL, }, + { 0x5556555655565556ULL, 0x5556555655565556ULL, }, /* 24 */ + { 0x5555555555555555ULL, 0x5555555555555555ULL, }, + { 0xaaabaaabaaabaaabULL, 0xaaabaaabaaabaaabULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x8889888988898889ULL, 0x8889888988898889ULL, }, + { 0x2222222222222222ULL, 0x2222222222222222ULL, }, + { 0x71c71c72c71d71c7ULL, 0x1c72c71d71c71c72ULL, }, + { 0x38e48e391c7238e4ULL, 0x8e391c7238e48e39ULL, }, + { 0x3333333333333333ULL, 0x3333333333333333ULL, }, /* 32 */ + { 0x3334333433343334ULL, 0x3334333433343334ULL, }, + { 0x2222222222222222ULL, 0x2222222222222222ULL, }, + { 0x8889888988898889ULL, 0x8889888988898889ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x6667666766676667ULL, 0x6667666766676667ULL, }, + { 0x16c26c173e9416c2ULL, 0x6c173e9416c26c17ULL, }, + { 0x4fa505b0a4fb4fa5ULL, 0x05b0a4fb4fa505b0ULL, }, + { 0x3334333433343334ULL, 0x3334333433343334ULL, }, /* 40 */ + { 0x3333333333333333ULL, 0x3333333333333333ULL, }, + { 0x8889888988898889ULL, 0x8889888988898889ULL, }, + { 0x2222222222222222ULL, 0x2222222222222222ULL, }, + { 0x6667666766676667ULL, 0x6667666766676667ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x4fa505b0a4fb4fa5ULL, 0x05b0a4fb4fa505b0ULL, }, + { 0x16c26c173e9416c2ULL, 0x6c173e9416c26c17ULL, }, + { 0x1c7138e471c71c71ULL, 0x38e471c71c7138e4ULL, }, /* 48 */ + { 0x1c7238e371c81c72ULL, 0x38e371c81c7238e3ULL, }, + { 0x38e48e391c7238e4ULL, 0x8e391c7238e48e39ULL, }, + { 0x71c71c72c71d71c7ULL, 0x1c72c71d71c71c72ULL, }, + { 0x16c26c173e9416c2ULL, 0x6c173e9416c26c17ULL, }, + { 0x4fa505b0a4fb4fa5ULL, 0x05b0a4fb4fa505b0ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x38e371c7e38f38e3ULL, 0x71c7e38f38e371c7ULL, }, + { 0x1c7238e371c81c72ULL, 0x38e371c81c7238e3ULL, }, /* 56 */ + { 0x1c7138e471c71c71ULL, 0x38e471c71c7138e4ULL, }, + { 0x71c71c72c71d71c7ULL, 0x1c72c71d71c71c72ULL, }, + { 0x38e48e391c7238e4ULL, 0x8e391c7238e48e39ULL, }, + { 0x4fa505b0a4fb4fa5ULL, 0x05b0a4fb4fa505b0ULL, }, + { 0x16c26c173e9416c2ULL, 0x6c173e9416c26c17ULL, }, + { 0x38e371c7e38f38e3ULL, 0x71c7e38f38e371c7ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, /* 64 */ + { 0x7354199725318e38ULL, 0x3870504416c4a2f0ULL, }, + { 0x23f038226e93c9c0ULL, 0x238f445f53507508ULL, }, + { 0xe7e52f8135cf72f2ULL, 0xbd76828655393294ULL, }, + { 0x7354199725318e38ULL, 0x3870504416c4a2f0ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x4f6451b993c43b88ULL, 0x14e10be56a142de8ULL, }, + { 0x749115ea109e1b46ULL, 0x850632426bfd705cULL, }, + { 0x23f038226e93c9c0ULL, 0x238f445f53507508ULL, }, /* 72 */ + { 0x4f6451b993c43b88ULL, 0x14e10be56a142de8ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0xc3f567a3a46256ceULL, 0x99e73e2701e94274ULL, }, + { 0xe7e52f8135cf72f2ULL, 0xbd76828655393294ULL, }, + { 0x749115ea109e1b46ULL, 0x850632426bfd705cULL, }, + { 0xc3f567a3a46256ceULL, 0x99e73e2701e94274ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, +}; + + reset_msa_registers(); + + gettimeofday(&start, NULL); + + for (i = 0; i < PATTERN_INPUTS_SHORT_COUNT; i++) { + for (j = 0; j < PATTERN_INPUTS_SHORT_COUNT; j++) { + do_msa_ASUB_S_H(b128_pattern[i], b128_pattern[j], + b128_result[PATTERN_INPUTS_SHORT_COUNT * i + j]); + } + } + + for (i = 0; i < RANDOM_INPUTS_SHORT_COUNT; i++) { + for (j = 0; j < RANDOM_INPUTS_SHORT_COUNT; j++) { + do_msa_ASUB_S_H(b128_random[i], b128_random[j], + b128_result[((PATTERN_INPUTS_SHORT_COUNT) * + (PATTERN_INPUTS_SHORT_COUNT)) + + RANDOM_INPUTS_SHORT_COUNT * i + j]); + } + } + + gettimeofday(&end, NULL); + + elapsed_time = (end.tv_sec - start.tv_sec) * 1000.0; + elapsed_time += (end.tv_usec - start.tv_usec) / 1000.0; + + ret = check_results(instruction_name, TEST_COUNT_TOTAL, elapsed_time, + &b128_result[0][0], &b128_expect[0][0]); + + return ret; +} diff --git a/tests/tcg/mips/user/ase/msa/int-subtract/test_msa_asub_s_w.c b/tests/tcg/mips/user/ase/msa/int-subtract/test_msa_asub_s_w.c new file mode 100644 index 0000000000..fb8f3c1a10 --- /dev/null +++ b/tests/tcg/mips/user/ase/msa/int-subtract/test_msa_asub_s_w.c @@ -0,0 +1,157 @@ +/* + * Test program for MSA instruction ASUB_S.W + * + * Copyright (C) 2019 Wave Computing, Inc. + * Copyright (C) 2019 Aleksandar Markovic <amarkovic@wavecomp.com> + * Copyright (C) 2019 RT-RK Computer Based Systems LLC + * Copyright (C) 2019 Mateja Marjanovic <mateja.marjanovic@rt-rk.com> + * + * This program 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, see <https://www.gnu.org/licenses/>. + * + */ + +#include <sys/time.h> +#include <stdint.h> + +#include "../../../../include/wrappers_msa.h" +#include "../../../../include/test_inputs_128.h" +#include "../../../../include/test_utils_128.h" + +#define TEST_COUNT_TOTAL ( \ + (PATTERN_INPUTS_SHORT_COUNT) * (PATTERN_INPUTS_SHORT_COUNT) + \ + (RANDOM_INPUTS_SHORT_COUNT) * (RANDOM_INPUTS_SHORT_COUNT)) + + +int32_t main(void) +{ + char *instruction_name = "ASUB_S.W"; + int32_t ret; + uint32_t i, j; + struct timeval start, end; + double elapsed_time; + + uint64_t b128_result[TEST_COUNT_TOTAL][2]; + uint64_t b128_expect[TEST_COUNT_TOTAL][2] = { + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, /* 0 */ + { 0x0000000100000001ULL, 0x0000000100000001ULL, }, + { 0x5555555555555555ULL, 0x5555555555555555ULL, }, + { 0x5555555655555556ULL, 0x5555555655555556ULL, }, + { 0x3333333333333333ULL, 0x3333333333333333ULL, }, + { 0x3333333433333334ULL, 0x3333333433333334ULL, }, + { 0x1c71c71c71c71c71ULL, 0x38e38e391c71c71cULL, }, + { 0x1c71c71d71c71c72ULL, 0x38e38e381c71c71dULL, }, + { 0x0000000100000001ULL, 0x0000000100000001ULL, }, /* 8 */ + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x5555555655555556ULL, 0x5555555655555556ULL, }, + { 0x5555555555555555ULL, 0x5555555555555555ULL, }, + { 0x3333333433333334ULL, 0x3333333433333334ULL, }, + { 0x3333333333333333ULL, 0x3333333333333333ULL, }, + { 0x1c71c71d71c71c72ULL, 0x38e38e381c71c71dULL, }, + { 0x1c71c71c71c71c71ULL, 0x38e38e391c71c71cULL, }, + { 0x5555555555555555ULL, 0x5555555555555555ULL, }, /* 16 */ + { 0x5555555655555556ULL, 0x5555555655555556ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0xaaaaaaabaaaaaaabULL, 0xaaaaaaabaaaaaaabULL, }, + { 0x2222222222222222ULL, 0x2222222222222222ULL, }, + { 0x8888888988888889ULL, 0x8888888988888889ULL, }, + { 0x38e38e391c71c71cULL, 0x8e38e38e38e38e39ULL, }, + { 0x71c71c72c71c71c7ULL, 0x1c71c71d71c71c72ULL, }, + { 0x5555555655555556ULL, 0x5555555655555556ULL, }, /* 24 */ + { 0x5555555555555555ULL, 0x5555555555555555ULL, }, + { 0xaaaaaaabaaaaaaabULL, 0xaaaaaaabaaaaaaabULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x8888888988888889ULL, 0x8888888988888889ULL, }, + { 0x2222222222222222ULL, 0x2222222222222222ULL, }, + { 0x71c71c72c71c71c7ULL, 0x1c71c71d71c71c72ULL, }, + { 0x38e38e391c71c71cULL, 0x8e38e38e38e38e39ULL, }, + { 0x3333333333333333ULL, 0x3333333333333333ULL, }, /* 32 */ + { 0x3333333433333334ULL, 0x3333333433333334ULL, }, + { 0x2222222222222222ULL, 0x2222222222222222ULL, }, + { 0x8888888988888889ULL, 0x8888888988888889ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x6666666766666667ULL, 0x6666666766666667ULL, }, + { 0x16c16c173e93e93eULL, 0x6c16c16c16c16c17ULL, }, + { 0x4fa4fa50a4fa4fa5ULL, 0x05b05b054fa4fa50ULL, }, + { 0x3333333433333334ULL, 0x3333333433333334ULL, }, /* 40 */ + { 0x3333333333333333ULL, 0x3333333333333333ULL, }, + { 0x8888888988888889ULL, 0x8888888988888889ULL, }, + { 0x2222222222222222ULL, 0x2222222222222222ULL, }, + { 0x6666666766666667ULL, 0x6666666766666667ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x4fa4fa50a4fa4fa5ULL, 0x05b05b054fa4fa50ULL, }, + { 0x16c16c173e93e93eULL, 0x6c16c16c16c16c17ULL, }, + { 0x1c71c71c71c71c71ULL, 0x38e38e391c71c71cULL, }, /* 48 */ + { 0x1c71c71d71c71c72ULL, 0x38e38e381c71c71dULL, }, + { 0x38e38e391c71c71cULL, 0x8e38e38e38e38e39ULL, }, + { 0x71c71c72c71c71c7ULL, 0x1c71c71d71c71c72ULL, }, + { 0x16c16c173e93e93eULL, 0x6c16c16c16c16c17ULL, }, + { 0x4fa4fa50a4fa4fa5ULL, 0x05b05b054fa4fa50ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x38e38e39e38e38e3ULL, 0x71c71c7138e38e39ULL, }, + { 0x1c71c71d71c71c72ULL, 0x38e38e381c71c71dULL, }, /* 56 */ + { 0x1c71c71c71c71c71ULL, 0x38e38e391c71c71cULL, }, + { 0x71c71c72c71c71c7ULL, 0x1c71c71d71c71c72ULL, }, + { 0x38e38e391c71c71cULL, 0x8e38e38e38e38e39ULL, }, + { 0x4fa4fa50a4fa4fa5ULL, 0x05b05b054fa4fa50ULL, }, + { 0x16c16c173e93e93eULL, 0x6c16c16c16c16c17ULL, }, + { 0x38e38e39e38e38e3ULL, 0x71c71c7138e38e39ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, /* 64 */ + { 0x73531997253171c8ULL, 0x386f504416c3a2f0ULL, }, + { 0x23efc7de6e92c9c0ULL, 0x238e445f53508af8ULL, }, + { 0xe7e42f8135cf8d0eULL, 0xbd7582865538cd6cULL, }, + { 0x73531997253171c8ULL, 0x386f504416c3a2f0ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x4f6351b993c43b88ULL, 0x14e10be56a142de8ULL, }, + { 0x749115ea109e1b46ULL, 0x850632426bfc705cULL, }, + { 0x23efc7de6e92c9c0ULL, 0x238e445f53508af8ULL, }, /* 72 */ + { 0x4f6351b993c43b88ULL, 0x14e10be56a142de8ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0xc3f467a3a46256ceULL, 0x99e73e2701e84274ULL, }, + { 0xe7e42f8135cf8d0eULL, 0xbd7582865538cd6cULL, }, + { 0x749115ea109e1b46ULL, 0x850632426bfc705cULL, }, + { 0xc3f467a3a46256ceULL, 0x99e73e2701e84274ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, +}; + + reset_msa_registers(); + + gettimeofday(&start, NULL); + + for (i = 0; i < PATTERN_INPUTS_SHORT_COUNT; i++) { + for (j = 0; j < PATTERN_INPUTS_SHORT_COUNT; j++) { + do_msa_ASUB_S_W(b128_pattern[i], b128_pattern[j], + b128_result[PATTERN_INPUTS_SHORT_COUNT * i + j]); + } + } + + for (i = 0; i < RANDOM_INPUTS_SHORT_COUNT; i++) { + for (j = 0; j < RANDOM_INPUTS_SHORT_COUNT; j++) { + do_msa_ASUB_S_W(b128_random[i], b128_random[j], + b128_result[((PATTERN_INPUTS_SHORT_COUNT) * + (PATTERN_INPUTS_SHORT_COUNT)) + + RANDOM_INPUTS_SHORT_COUNT * i + j]); + } + } + + gettimeofday(&end, NULL); + + elapsed_time = (end.tv_sec - start.tv_sec) * 1000.0; + elapsed_time += (end.tv_usec - start.tv_usec) / 1000.0; + + ret = check_results(instruction_name, TEST_COUNT_TOTAL, elapsed_time, + &b128_result[0][0], &b128_expect[0][0]); + + return ret; +} diff --git a/tests/tcg/mips/user/ase/msa/int-subtract/test_msa_asub_u_b.c b/tests/tcg/mips/user/ase/msa/int-subtract/test_msa_asub_u_b.c new file mode 100644 index 0000000000..506500b993 --- /dev/null +++ b/tests/tcg/mips/user/ase/msa/int-subtract/test_msa_asub_u_b.c @@ -0,0 +1,157 @@ +/* + * Test program for MSA instruction ASUB_U.B + * + * Copyright (C) 2019 Wave Computing, Inc. + * Copyright (C) 2019 Aleksandar Markovic <amarkovic@wavecomp.com> + * Copyright (C) 2019 RT-RK Computer Based Systems LLC + * Copyright (C) 2019 Mateja Marjanovic <mateja.marjanovic@rt-rk.com> + * + * This program 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, see <https://www.gnu.org/licenses/>. + * + */ + +#include <sys/time.h> +#include <stdint.h> + +#include "../../../../include/wrappers_msa.h" +#include "../../../../include/test_inputs_128.h" +#include "../../../../include/test_utils_128.h" + +#define TEST_COUNT_TOTAL ( \ + (PATTERN_INPUTS_SHORT_COUNT) * (PATTERN_INPUTS_SHORT_COUNT) + \ + (RANDOM_INPUTS_SHORT_COUNT) * (RANDOM_INPUTS_SHORT_COUNT)) + + +int32_t main(void) +{ + char *instruction_name = "ASUB_U.B"; + int32_t ret; + uint32_t i, j; + struct timeval start, end; + double elapsed_time; + + uint64_t b128_result[TEST_COUNT_TOTAL][2]; + uint64_t b128_expect[TEST_COUNT_TOTAL][2] = { + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, /* 0 */ + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, + { 0x5555555555555555ULL, 0x5555555555555555ULL, }, + { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, }, + { 0x3333333333333333ULL, 0x3333333333333333ULL, }, + { 0xccccccccccccccccULL, 0xccccccccccccccccULL, }, + { 0x1c71c71c71c71c71ULL, 0xc71c71c71c71c71cULL, }, + { 0xe38e38e38e38e38eULL, 0x38e38e38e38e38e3ULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 8 */ + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, }, + { 0x5555555555555555ULL, 0x5555555555555555ULL, }, + { 0xccccccccccccccccULL, 0xccccccccccccccccULL, }, + { 0x3333333333333333ULL, 0x3333333333333333ULL, }, + { 0xe38e38e38e38e38eULL, 0x38e38e38e38e38e3ULL, }, + { 0x1c71c71c71c71c71ULL, 0xc71c71c71c71c71cULL, }, + { 0x5555555555555555ULL, 0x5555555555555555ULL, }, /* 16 */ + { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x5555555555555555ULL, 0x5555555555555555ULL, }, + { 0x2222222222222222ULL, 0x2222222222222222ULL, }, + { 0x7777777777777777ULL, 0x7777777777777777ULL, }, + { 0x391c72391c72391cULL, 0x72391c72391c7239ULL, }, + { 0x8e391d8e391d8e39ULL, 0x1d8e391d8e391d8eULL, }, + { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, }, /* 24 */ + { 0x5555555555555555ULL, 0x5555555555555555ULL, }, + { 0x5555555555555555ULL, 0x5555555555555555ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x7777777777777777ULL, 0x7777777777777777ULL, }, + { 0x2222222222222222ULL, 0x2222222222222222ULL, }, + { 0x8e391d8e391d8e39ULL, 0x1d8e391d8e391d8eULL, }, + { 0x391c72391c72391cULL, 0x72391c72391c7239ULL, }, + { 0x3333333333333333ULL, 0x3333333333333333ULL, }, /* 32 */ + { 0xccccccccccccccccULL, 0xccccccccccccccccULL, }, + { 0x2222222222222222ULL, 0x2222222222222222ULL, }, + { 0x7777777777777777ULL, 0x7777777777777777ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x9999999999999999ULL, 0x9999999999999999ULL, }, + { 0x173e94173e94173eULL, 0x94173e94173e9417ULL, }, + { 0xb05b05b05b05b05bULL, 0x05b05b05b05b05b0ULL, }, + { 0xccccccccccccccccULL, 0xccccccccccccccccULL, }, /* 40 */ + { 0x3333333333333333ULL, 0x3333333333333333ULL, }, + { 0x7777777777777777ULL, 0x7777777777777777ULL, }, + { 0x2222222222222222ULL, 0x2222222222222222ULL, }, + { 0x9999999999999999ULL, 0x9999999999999999ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0xb05b05b05b05b05bULL, 0x05b05b05b05b05b0ULL, }, + { 0x173e94173e94173eULL, 0x94173e94173e9417ULL, }, + { 0x1c71c71c71c71c71ULL, 0xc71c71c71c71c71cULL, }, /* 48 */ + { 0xe38e38e38e38e38eULL, 0x38e38e38e38e38e3ULL, }, + { 0x391c72391c72391cULL, 0x72391c72391c7239ULL, }, + { 0x8e391d8e391d8e39ULL, 0x1d8e391d8e391d8eULL, }, + { 0x173e94173e94173eULL, 0x94173e94173e9417ULL, }, + { 0xb05b05b05b05b05bULL, 0x05b05b05b05b05b0ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0xc71d8fc71d8fc71dULL, 0x8fc71d8fc71d8fc7ULL, }, + { 0xe38e38e38e38e38eULL, 0x38e38e38e38e38e3ULL, }, /* 56 */ + { 0x1c71c71c71c71c71ULL, 0xc71c71c71c71c71cULL, }, + { 0x8e391d8e391d8e39ULL, 0x1d8e391d8e391d8eULL, }, + { 0x391c72391c72391cULL, 0x72391c72391c7239ULL, }, + { 0xb05b05b05b05b05bULL, 0x05b05b05b05b05b0ULL, }, + { 0x173e94173e94173eULL, 0x94173e94173e9417ULL, }, + { 0xc71d8fc71d8fc71dULL, 0x8fc71d8fc71d8fc7ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, /* 64 */ + { 0x7354e66925317238ULL, 0x3990b044e93c5ef0ULL, }, + { 0x24103822916d3640ULL, 0x2471bba153508b08ULL, }, + { 0x181bd07f36318d0eULL, 0x428a7d7a55393294ULL, }, + { 0x7354e66925317238ULL, 0x3990b044e93c5ef0ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x4f64ae476c3c3c78ULL, 0x151f0be596142de8ULL, }, + { 0x8b6f161611621b46ULL, 0x7b0633be9403905cULL, }, + { 0x24103822916d3640ULL, 0x2471bba153508b08ULL, }, /* 72 */ + { 0x4f64ae476c3c3c78ULL, 0x151f0be596142de8ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x3c0b985d5b9e5732ULL, 0x66193e270217bd8cULL, }, + { 0x181bd07f36318d0eULL, 0x428a7d7a55393294ULL, }, + { 0x8b6f161611621b46ULL, 0x7b0633be9403905cULL, }, + { 0x3c0b985d5b9e5732ULL, 0x66193e270217bd8cULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, +}; + + reset_msa_registers(); + + gettimeofday(&start, NULL); + + for (i = 0; i < PATTERN_INPUTS_SHORT_COUNT; i++) { + for (j = 0; j < PATTERN_INPUTS_SHORT_COUNT; j++) { + do_msa_ASUB_U_B(b128_pattern[i], b128_pattern[j], + b128_result[PATTERN_INPUTS_SHORT_COUNT * i + j]); + } + } + + for (i = 0; i < RANDOM_INPUTS_SHORT_COUNT; i++) { + for (j = 0; j < RANDOM_INPUTS_SHORT_COUNT; j++) { + do_msa_ASUB_U_B(b128_random[i], b128_random[j], + b128_result[((PATTERN_INPUTS_SHORT_COUNT) * + (PATTERN_INPUTS_SHORT_COUNT)) + + RANDOM_INPUTS_SHORT_COUNT * i + j]); + } + } + + gettimeofday(&end, NULL); + + elapsed_time = (end.tv_sec - start.tv_sec) * 1000.0; + elapsed_time += (end.tv_usec - start.tv_usec) / 1000.0; + + ret = check_results(instruction_name, TEST_COUNT_TOTAL, elapsed_time, + &b128_result[0][0], &b128_expect[0][0]); + + return ret; +} diff --git a/tests/tcg/mips/user/ase/msa/int-subtract/test_msa_asub_u_d.c b/tests/tcg/mips/user/ase/msa/int-subtract/test_msa_asub_u_d.c new file mode 100644 index 0000000000..ef7ee3fd15 --- /dev/null +++ b/tests/tcg/mips/user/ase/msa/int-subtract/test_msa_asub_u_d.c @@ -0,0 +1,157 @@ +/* + * Test program for MSA instruction ASUB_U.D + * + * Copyright (C) 2019 Wave Computing, Inc. + * Copyright (C) 2019 Aleksandar Markovic <amarkovic@wavecomp.com> + * Copyright (C) 2019 RT-RK Computer Based Systems LLC + * Copyright (C) 2019 Mateja Marjanovic <mateja.marjanovic@rt-rk.com> + * + * This program 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, see <https://www.gnu.org/licenses/>. + * + */ + +#include <sys/time.h> +#include <stdint.h> + +#include "../../../../include/wrappers_msa.h" +#include "../../../../include/test_inputs_128.h" +#include "../../../../include/test_utils_128.h" + +#define TEST_COUNT_TOTAL ( \ + (PATTERN_INPUTS_SHORT_COUNT) * (PATTERN_INPUTS_SHORT_COUNT) + \ + (RANDOM_INPUTS_SHORT_COUNT) * (RANDOM_INPUTS_SHORT_COUNT)) + + +int32_t main(void) +{ + char *instruction_name = "ASUB_U.D"; + int32_t ret; + uint32_t i, j; + struct timeval start, end; + double elapsed_time; + + uint64_t b128_result[TEST_COUNT_TOTAL][2]; + uint64_t b128_expect[TEST_COUNT_TOTAL][2] = { + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, /* 0 */ + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, + { 0x5555555555555555ULL, 0x5555555555555555ULL, }, + { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, }, + { 0x3333333333333333ULL, 0x3333333333333333ULL, }, + { 0xccccccccccccccccULL, 0xccccccccccccccccULL, }, + { 0x1c71c71c71c71c71ULL, 0xc71c71c71c71c71cULL, }, + { 0xe38e38e38e38e38eULL, 0x38e38e38e38e38e3ULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 8 */ + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, }, + { 0x5555555555555555ULL, 0x5555555555555555ULL, }, + { 0xccccccccccccccccULL, 0xccccccccccccccccULL, }, + { 0x3333333333333333ULL, 0x3333333333333333ULL, }, + { 0xe38e38e38e38e38eULL, 0x38e38e38e38e38e3ULL, }, + { 0x1c71c71c71c71c71ULL, 0xc71c71c71c71c71cULL, }, + { 0x5555555555555555ULL, 0x5555555555555555ULL, }, /* 16 */ + { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x5555555555555555ULL, 0x5555555555555555ULL, }, + { 0x2222222222222222ULL, 0x2222222222222222ULL, }, + { 0x7777777777777777ULL, 0x7777777777777777ULL, }, + { 0x38e38e38e38e38e4ULL, 0x71c71c71c71c71c7ULL, }, + { 0x8e38e38e38e38e39ULL, 0x1c71c71c71c71c72ULL, }, + { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, }, /* 24 */ + { 0x5555555555555555ULL, 0x5555555555555555ULL, }, + { 0x5555555555555555ULL, 0x5555555555555555ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x7777777777777777ULL, 0x7777777777777777ULL, }, + { 0x2222222222222222ULL, 0x2222222222222222ULL, }, + { 0x8e38e38e38e38e39ULL, 0x1c71c71c71c71c72ULL, }, + { 0x38e38e38e38e38e4ULL, 0x71c71c71c71c71c7ULL, }, + { 0x3333333333333333ULL, 0x3333333333333333ULL, }, /* 32 */ + { 0xccccccccccccccccULL, 0xccccccccccccccccULL, }, + { 0x2222222222222222ULL, 0x2222222222222222ULL, }, + { 0x7777777777777777ULL, 0x7777777777777777ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x9999999999999999ULL, 0x9999999999999999ULL, }, + { 0x16c16c16c16c16c2ULL, 0x93e93e93e93e93e9ULL, }, + { 0xb05b05b05b05b05bULL, 0x05b05b05b05b05b0ULL, }, + { 0xccccccccccccccccULL, 0xccccccccccccccccULL, }, /* 40 */ + { 0x3333333333333333ULL, 0x3333333333333333ULL, }, + { 0x7777777777777777ULL, 0x7777777777777777ULL, }, + { 0x2222222222222222ULL, 0x2222222222222222ULL, }, + { 0x9999999999999999ULL, 0x9999999999999999ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0xb05b05b05b05b05bULL, 0x05b05b05b05b05b0ULL, }, + { 0x16c16c16c16c16c2ULL, 0x93e93e93e93e93e9ULL, }, + { 0x1c71c71c71c71c71ULL, 0xc71c71c71c71c71cULL, }, /* 48 */ + { 0xe38e38e38e38e38eULL, 0x38e38e38e38e38e3ULL, }, + { 0x38e38e38e38e38e4ULL, 0x71c71c71c71c71c7ULL, }, + { 0x8e38e38e38e38e39ULL, 0x1c71c71c71c71c72ULL, }, + { 0x16c16c16c16c16c2ULL, 0x93e93e93e93e93e9ULL, }, + { 0xb05b05b05b05b05bULL, 0x05b05b05b05b05b0ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0xc71c71c71c71c71dULL, 0x8e38e38e38e38e39ULL, }, + { 0xe38e38e38e38e38eULL, 0x38e38e38e38e38e3ULL, }, /* 56 */ + { 0x1c71c71c71c71c71ULL, 0xc71c71c71c71c71cULL, }, + { 0x8e38e38e38e38e39ULL, 0x1c71c71c71c71c72ULL, }, + { 0x38e38e38e38e38e4ULL, 0x71c71c71c71c71c7ULL, }, + { 0xb05b05b05b05b05bULL, 0x05b05b05b05b05b0ULL, }, + { 0x16c16c16c16c16c2ULL, 0x93e93e93e93e93e9ULL, }, + { 0xc71c71c71c71c71dULL, 0x8e38e38e38e38e39ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, /* 64 */ + { 0x73531997253171c8ULL, 0x386f5044e93c5d10ULL, }, + { 0x23efc7de916d3640ULL, 0x238e445f53508af8ULL, }, + { 0x181bd07eca3072f2ULL, 0x428a7d79aac73294ULL, }, + { 0x73531997253171c8ULL, 0x386f5044e93c5d10ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x4f6351b893c43b88ULL, 0x14e10be595ebd218ULL, }, + { 0x8b6eea15ef61e4baULL, 0x7af9cdbe94038fa4ULL, }, + { 0x23efc7de916d3640ULL, 0x238e445f53508af8ULL, }, /* 72 */ + { 0x4f6351b893c43b88ULL, 0x14e10be595ebd218ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x3c0b985d5b9da932ULL, 0x6618c1d8fe17bd8cULL, }, + { 0x181bd07eca3072f2ULL, 0x428a7d79aac73294ULL, }, + { 0x8b6eea15ef61e4baULL, 0x7af9cdbe94038fa4ULL, }, + { 0x3c0b985d5b9da932ULL, 0x6618c1d8fe17bd8cULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, +}; + + reset_msa_registers(); + + gettimeofday(&start, NULL); + + for (i = 0; i < PATTERN_INPUTS_SHORT_COUNT; i++) { + for (j = 0; j < PATTERN_INPUTS_SHORT_COUNT; j++) { + do_msa_ASUB_U_D(b128_pattern[i], b128_pattern[j], + b128_result[PATTERN_INPUTS_SHORT_COUNT * i + j]); + } + } + + for (i = 0; i < RANDOM_INPUTS_SHORT_COUNT; i++) { + for (j = 0; j < RANDOM_INPUTS_SHORT_COUNT; j++) { + do_msa_ASUB_U_D(b128_random[i], b128_random[j], + b128_result[((PATTERN_INPUTS_SHORT_COUNT) * + (PATTERN_INPUTS_SHORT_COUNT)) + + RANDOM_INPUTS_SHORT_COUNT * i + j]); + } + } + + gettimeofday(&end, NULL); + + elapsed_time = (end.tv_sec - start.tv_sec) * 1000.0; + elapsed_time += (end.tv_usec - start.tv_usec) / 1000.0; + + ret = check_results(instruction_name, TEST_COUNT_TOTAL, elapsed_time, + &b128_result[0][0], &b128_expect[0][0]); + + return ret; +} diff --git a/tests/tcg/mips/user/ase/msa/int-subtract/test_msa_asub_u_h.c b/tests/tcg/mips/user/ase/msa/int-subtract/test_msa_asub_u_h.c new file mode 100644 index 0000000000..17dab15761 --- /dev/null +++ b/tests/tcg/mips/user/ase/msa/int-subtract/test_msa_asub_u_h.c @@ -0,0 +1,157 @@ +/* + * Test program for MSA instruction ASUB_U.H + * + * Copyright (C) 2019 Wave Computing, Inc. + * Copyright (C) 2019 Aleksandar Markovic <amarkovic@wavecomp.com> + * Copyright (C) 2019 RT-RK Computer Based Systems LLC + * Copyright (C) 2019 Mateja Marjanovic <mateja.marjanovic@rt-rk.com> + * + * This program 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, see <https://www.gnu.org/licenses/>. + * + */ + +#include <sys/time.h> +#include <stdint.h> + +#include "../../../../include/wrappers_msa.h" +#include "../../../../include/test_inputs_128.h" +#include "../../../../include/test_utils_128.h" + +#define TEST_COUNT_TOTAL ( \ + (PATTERN_INPUTS_SHORT_COUNT) * (PATTERN_INPUTS_SHORT_COUNT) + \ + (RANDOM_INPUTS_SHORT_COUNT) * (RANDOM_INPUTS_SHORT_COUNT)) + + +int32_t main(void) +{ + char *instruction_name = "ASUB_U.H"; + int32_t ret; + uint32_t i, j; + struct timeval start, end; + double elapsed_time; + + uint64_t b128_result[TEST_COUNT_TOTAL][2]; + uint64_t b128_expect[TEST_COUNT_TOTAL][2] = { + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, /* 0 */ + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, + { 0x5555555555555555ULL, 0x5555555555555555ULL, }, + { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, }, + { 0x3333333333333333ULL, 0x3333333333333333ULL, }, + { 0xccccccccccccccccULL, 0xccccccccccccccccULL, }, + { 0x1c71c71c71c71c71ULL, 0xc71c71c71c71c71cULL, }, + { 0xe38e38e38e38e38eULL, 0x38e38e38e38e38e3ULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 8 */ + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, }, + { 0x5555555555555555ULL, 0x5555555555555555ULL, }, + { 0xccccccccccccccccULL, 0xccccccccccccccccULL, }, + { 0x3333333333333333ULL, 0x3333333333333333ULL, }, + { 0xe38e38e38e38e38eULL, 0x38e38e38e38e38e3ULL, }, + { 0x1c71c71c71c71c71ULL, 0xc71c71c71c71c71cULL, }, + { 0x5555555555555555ULL, 0x5555555555555555ULL, }, /* 16 */ + { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x5555555555555555ULL, 0x5555555555555555ULL, }, + { 0x2222222222222222ULL, 0x2222222222222222ULL, }, + { 0x7777777777777777ULL, 0x7777777777777777ULL, }, + { 0x38e471c71c7238e4ULL, 0x71c71c7238e471c7ULL, }, + { 0x8e391c7238e38e39ULL, 0x1c7238e38e391c72ULL, }, + { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, }, /* 24 */ + { 0x5555555555555555ULL, 0x5555555555555555ULL, }, + { 0x5555555555555555ULL, 0x5555555555555555ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x7777777777777777ULL, 0x7777777777777777ULL, }, + { 0x2222222222222222ULL, 0x2222222222222222ULL, }, + { 0x8e391c7238e38e39ULL, 0x1c7238e38e391c72ULL, }, + { 0x38e471c71c7238e4ULL, 0x71c71c7238e471c7ULL, }, + { 0x3333333333333333ULL, 0x3333333333333333ULL, }, /* 32 */ + { 0xccccccccccccccccULL, 0xccccccccccccccccULL, }, + { 0x2222222222222222ULL, 0x2222222222222222ULL, }, + { 0x7777777777777777ULL, 0x7777777777777777ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x9999999999999999ULL, 0x9999999999999999ULL, }, + { 0x16c293e93e9416c2ULL, 0x93e93e9416c293e9ULL, }, + { 0xb05b05b05b05b05bULL, 0x05b05b05b05b05b0ULL, }, + { 0xccccccccccccccccULL, 0xccccccccccccccccULL, }, /* 40 */ + { 0x3333333333333333ULL, 0x3333333333333333ULL, }, + { 0x7777777777777777ULL, 0x7777777777777777ULL, }, + { 0x2222222222222222ULL, 0x2222222222222222ULL, }, + { 0x9999999999999999ULL, 0x9999999999999999ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0xb05b05b05b05b05bULL, 0x05b05b05b05b05b0ULL, }, + { 0x16c293e93e9416c2ULL, 0x93e93e9416c293e9ULL, }, + { 0x1c71c71c71c71c71ULL, 0xc71c71c71c71c71cULL, }, /* 48 */ + { 0xe38e38e38e38e38eULL, 0x38e38e38e38e38e3ULL, }, + { 0x38e471c71c7238e4ULL, 0x71c71c7238e471c7ULL, }, + { 0x8e391c7238e38e39ULL, 0x1c7238e38e391c72ULL, }, + { 0x16c293e93e9416c2ULL, 0x93e93e9416c293e9ULL, }, + { 0xb05b05b05b05b05bULL, 0x05b05b05b05b05b0ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0xc71d8e391c71c71dULL, 0x8e391c71c71d8e39ULL, }, + { 0xe38e38e38e38e38eULL, 0x38e38e38e38e38e3ULL, }, /* 56 */ + { 0x1c71c71c71c71c71ULL, 0xc71c71c71c71c71cULL, }, + { 0x8e391c7238e38e39ULL, 0x1c7238e38e391c72ULL, }, + { 0x38e471c71c7238e4ULL, 0x71c71c7238e471c7ULL, }, + { 0xb05b05b05b05b05bULL, 0x05b05b05b05b05b0ULL, }, + { 0x16c293e93e9416c2ULL, 0x93e93e9416c293e9ULL, }, + { 0xc71d8e391c71c71dULL, 0x8e391c71c71d8e39ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, /* 64 */ + { 0x7354e669253171c8ULL, 0x3870afbce93c5d10ULL, }, + { 0x23f03822916d3640ULL, 0x238fbba153508af8ULL, }, + { 0x181bd07f35cf8d0eULL, 0x428a7d7a55393294ULL, }, + { 0x7354e669253171c8ULL, 0x3870afbce93c5d10ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x4f64ae476c3c3b88ULL, 0x14e10be595ec2de8ULL, }, + { 0x8b6f15ea109e1b46ULL, 0x7afa324294038fa4ULL, }, + { 0x23f03822916d3640ULL, 0x238fbba153508af8ULL, }, /* 72 */ + { 0x4f64ae476c3c3b88ULL, 0x14e10be595ec2de8ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x3c0b985d5b9e56ceULL, 0x66193e2701e9bd8cULL, }, + { 0x181bd07f35cf8d0eULL, 0x428a7d7a55393294ULL, }, + { 0x8b6f15ea109e1b46ULL, 0x7afa324294038fa4ULL, }, + { 0x3c0b985d5b9e56ceULL, 0x66193e2701e9bd8cULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, +}; + + reset_msa_registers(); + + gettimeofday(&start, NULL); + + for (i = 0; i < PATTERN_INPUTS_SHORT_COUNT; i++) { + for (j = 0; j < PATTERN_INPUTS_SHORT_COUNT; j++) { + do_msa_ASUB_U_H(b128_pattern[i], b128_pattern[j], + b128_result[PATTERN_INPUTS_SHORT_COUNT * i + j]); + } + } + + for (i = 0; i < RANDOM_INPUTS_SHORT_COUNT; i++) { + for (j = 0; j < RANDOM_INPUTS_SHORT_COUNT; j++) { + do_msa_ASUB_U_H(b128_random[i], b128_random[j], + b128_result[((PATTERN_INPUTS_SHORT_COUNT) * + (PATTERN_INPUTS_SHORT_COUNT)) + + RANDOM_INPUTS_SHORT_COUNT * i + j]); + } + } + + gettimeofday(&end, NULL); + + elapsed_time = (end.tv_sec - start.tv_sec) * 1000.0; + elapsed_time += (end.tv_usec - start.tv_usec) / 1000.0; + + ret = check_results(instruction_name, TEST_COUNT_TOTAL, elapsed_time, + &b128_result[0][0], &b128_expect[0][0]); + + return ret; +} diff --git a/tests/tcg/mips/user/ase/msa/int-subtract/test_msa_asub_u_w.c b/tests/tcg/mips/user/ase/msa/int-subtract/test_msa_asub_u_w.c new file mode 100644 index 0000000000..38a6395e2d --- /dev/null +++ b/tests/tcg/mips/user/ase/msa/int-subtract/test_msa_asub_u_w.c @@ -0,0 +1,157 @@ +/* + * Test program for MSA instruction ASUB_U.W + * + * Copyright (C) 2019 Wave Computing, Inc. + * Copyright (C) 2019 Aleksandar Markovic <amarkovic@wavecomp.com> + * Copyright (C) 2019 RT-RK Computer Based Systems LLC + * Copyright (C) 2019 Mateja Marjanovic <mateja.marjanovic@rt-rk.com> + * + * This program 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, see <https://www.gnu.org/licenses/>. + * + */ + +#include <sys/time.h> +#include <stdint.h> + +#include "../../../../include/wrappers_msa.h" +#include "../../../../include/test_inputs_128.h" +#include "../../../../include/test_utils_128.h" + +#define TEST_COUNT_TOTAL ( \ + (PATTERN_INPUTS_SHORT_COUNT) * (PATTERN_INPUTS_SHORT_COUNT) + \ + (RANDOM_INPUTS_SHORT_COUNT) * (RANDOM_INPUTS_SHORT_COUNT)) + + +int32_t main(void) +{ + char *instruction_name = "ASUB_U.W"; + int32_t ret; + uint32_t i, j; + struct timeval start, end; + double elapsed_time; + + uint64_t b128_result[TEST_COUNT_TOTAL][2]; + uint64_t b128_expect[TEST_COUNT_TOTAL][2] = { + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, /* 0 */ + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, + { 0x5555555555555555ULL, 0x5555555555555555ULL, }, + { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, }, + { 0x3333333333333333ULL, 0x3333333333333333ULL, }, + { 0xccccccccccccccccULL, 0xccccccccccccccccULL, }, + { 0x1c71c71c71c71c71ULL, 0xc71c71c71c71c71cULL, }, + { 0xe38e38e38e38e38eULL, 0x38e38e38e38e38e3ULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 8 */ + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, }, + { 0x5555555555555555ULL, 0x5555555555555555ULL, }, + { 0xccccccccccccccccULL, 0xccccccccccccccccULL, }, + { 0x3333333333333333ULL, 0x3333333333333333ULL, }, + { 0xe38e38e38e38e38eULL, 0x38e38e38e38e38e3ULL, }, + { 0x1c71c71c71c71c71ULL, 0xc71c71c71c71c71cULL, }, + { 0x5555555555555555ULL, 0x5555555555555555ULL, }, /* 16 */ + { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x5555555555555555ULL, 0x5555555555555555ULL, }, + { 0x2222222222222222ULL, 0x2222222222222222ULL, }, + { 0x7777777777777777ULL, 0x7777777777777777ULL, }, + { 0x38e38e391c71c71cULL, 0x71c71c7238e38e39ULL, }, + { 0x8e38e38e38e38e39ULL, 0x1c71c71d8e38e38eULL, }, + { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, }, /* 24 */ + { 0x5555555555555555ULL, 0x5555555555555555ULL, }, + { 0x5555555555555555ULL, 0x5555555555555555ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x7777777777777777ULL, 0x7777777777777777ULL, }, + { 0x2222222222222222ULL, 0x2222222222222222ULL, }, + { 0x8e38e38e38e38e39ULL, 0x1c71c71d8e38e38eULL, }, + { 0x38e38e391c71c71cULL, 0x71c71c7238e38e39ULL, }, + { 0x3333333333333333ULL, 0x3333333333333333ULL, }, /* 32 */ + { 0xccccccccccccccccULL, 0xccccccccccccccccULL, }, + { 0x2222222222222222ULL, 0x2222222222222222ULL, }, + { 0x7777777777777777ULL, 0x7777777777777777ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x9999999999999999ULL, 0x9999999999999999ULL, }, + { 0x16c16c173e93e93eULL, 0x93e93e9416c16c17ULL, }, + { 0xb05b05b05b05b05bULL, 0x05b05b05b05b05b0ULL, }, + { 0xccccccccccccccccULL, 0xccccccccccccccccULL, }, /* 40 */ + { 0x3333333333333333ULL, 0x3333333333333333ULL, }, + { 0x7777777777777777ULL, 0x7777777777777777ULL, }, + { 0x2222222222222222ULL, 0x2222222222222222ULL, }, + { 0x9999999999999999ULL, 0x9999999999999999ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0xb05b05b05b05b05bULL, 0x05b05b05b05b05b0ULL, }, + { 0x16c16c173e93e93eULL, 0x93e93e9416c16c17ULL, }, + { 0x1c71c71c71c71c71ULL, 0xc71c71c71c71c71cULL, }, /* 48 */ + { 0xe38e38e38e38e38eULL, 0x38e38e38e38e38e3ULL, }, + { 0x38e38e391c71c71cULL, 0x71c71c7238e38e39ULL, }, + { 0x8e38e38e38e38e39ULL, 0x1c71c71d8e38e38eULL, }, + { 0x16c16c173e93e93eULL, 0x93e93e9416c16c17ULL, }, + { 0xb05b05b05b05b05bULL, 0x05b05b05b05b05b0ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0xc71c71c71c71c71dULL, 0x8e38e38fc71c71c7ULL, }, + { 0xe38e38e38e38e38eULL, 0x38e38e38e38e38e3ULL, }, /* 56 */ + { 0x1c71c71c71c71c71ULL, 0xc71c71c71c71c71cULL, }, + { 0x8e38e38e38e38e39ULL, 0x1c71c71d8e38e38eULL, }, + { 0x38e38e391c71c71cULL, 0x71c71c7238e38e39ULL, }, + { 0xb05b05b05b05b05bULL, 0x05b05b05b05b05b0ULL, }, + { 0x16c16c173e93e93eULL, 0x93e93e9416c16c17ULL, }, + { 0xc71c71c71c71c71dULL, 0x8e38e38fc71c71c7ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, /* 64 */ + { 0x73531997253171c8ULL, 0x386f5044e93c5d10ULL, }, + { 0x23efc7de916d3640ULL, 0x238e445f53508af8ULL, }, + { 0x181bd07f35cf8d0eULL, 0x428a7d7a5538cd6cULL, }, + { 0x73531997253171c8ULL, 0x386f5044e93c5d10ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x4f6351b96c3bc478ULL, 0x14e10be595ebd218ULL, }, + { 0x8b6eea16109e1b46ULL, 0x7af9cdbe94038fa4ULL, }, + { 0x23efc7de916d3640ULL, 0x238e445f53508af8ULL, }, /* 72 */ + { 0x4f6351b96c3bc478ULL, 0x14e10be595ebd218ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x3c0b985d5b9da932ULL, 0x6618c1d901e84274ULL, }, + { 0x181bd07f35cf8d0eULL, 0x428a7d7a5538cd6cULL, }, + { 0x8b6eea16109e1b46ULL, 0x7af9cdbe94038fa4ULL, }, + { 0x3c0b985d5b9da932ULL, 0x6618c1d901e84274ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, +}; + + reset_msa_registers(); + + gettimeofday(&start, NULL); + + for (i = 0; i < PATTERN_INPUTS_SHORT_COUNT; i++) { + for (j = 0; j < PATTERN_INPUTS_SHORT_COUNT; j++) { + do_msa_ASUB_U_W(b128_pattern[i], b128_pattern[j], + b128_result[PATTERN_INPUTS_SHORT_COUNT * i + j]); + } + } + + for (i = 0; i < RANDOM_INPUTS_SHORT_COUNT; i++) { + for (j = 0; j < RANDOM_INPUTS_SHORT_COUNT; j++) { + do_msa_ASUB_U_W(b128_random[i], b128_random[j], + b128_result[((PATTERN_INPUTS_SHORT_COUNT) * + (PATTERN_INPUTS_SHORT_COUNT)) + + RANDOM_INPUTS_SHORT_COUNT * i + j]); + } + } + + gettimeofday(&end, NULL); + + elapsed_time = (end.tv_sec - start.tv_sec) * 1000.0; + elapsed_time += (end.tv_usec - start.tv_usec) / 1000.0; + + ret = check_results(instruction_name, TEST_COUNT_TOTAL, elapsed_time, + &b128_result[0][0], &b128_expect[0][0]); + + return ret; +} diff --git a/tests/tcg/mips/user/ase/msa/int-subtract/test_msa_hsub_s_d.c b/tests/tcg/mips/user/ase/msa/int-subtract/test_msa_hsub_s_d.c new file mode 100644 index 0000000000..dd1dd37af2 --- /dev/null +++ b/tests/tcg/mips/user/ase/msa/int-subtract/test_msa_hsub_s_d.c @@ -0,0 +1,157 @@ +/* + * Test program for MSA instruction HSUB_S.D + * + * Copyright (C) 2019 Wave Computing, Inc. + * Copyright (C) 2019 Aleksandar Markovic <amarkovic@wavecomp.com> + * Copyright (C) 2019 RT-RK Computer Based Systems LLC + * Copyright (C) 2019 Mateja Marjanovic <mateja.marjanovic@rt-rk.com> + * + * This program 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, see <https://www.gnu.org/licenses/>. + * + */ + +#include <sys/time.h> +#include <stdint.h> + +#include "../../../../include/wrappers_msa.h" +#include "../../../../include/test_inputs_128.h" +#include "../../../../include/test_utils_128.h" + +#define TEST_COUNT_TOTAL ( \ + (PATTERN_INPUTS_SHORT_COUNT) * (PATTERN_INPUTS_SHORT_COUNT) + \ + (RANDOM_INPUTS_SHORT_COUNT) * (RANDOM_INPUTS_SHORT_COUNT)) + + +int32_t main(void) +{ + char *instruction_name = "HSUB_S.D"; + int32_t ret; + uint32_t i, j; + struct timeval start, end; + double elapsed_time; + + uint64_t b128_result[TEST_COUNT_TOTAL][2]; + uint64_t b128_expect[TEST_COUNT_TOTAL][2] = { + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, /* 0 */ + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, + { 0x0000000055555555ULL, 0x0000000055555555ULL, }, + { 0xffffffffaaaaaaaaULL, 0xffffffffaaaaaaaaULL, }, + { 0x0000000033333333ULL, 0x0000000033333333ULL, }, + { 0xffffffffccccccccULL, 0xffffffffccccccccULL, }, + { 0x0000000071c71c71ULL, 0x000000001c71c71cULL, }, + { 0xffffffff8e38e38eULL, 0xffffffffe38e38e3ULL, }, + { 0x0000000000000001ULL, 0x0000000000000001ULL, }, /* 8 */ + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000055555556ULL, 0x0000000055555556ULL, }, + { 0xffffffffaaaaaaabULL, 0xffffffffaaaaaaabULL, }, + { 0x0000000033333334ULL, 0x0000000033333334ULL, }, + { 0xffffffffcccccccdULL, 0xffffffffcccccccdULL, }, + { 0x0000000071c71c72ULL, 0x000000001c71c71dULL, }, + { 0xffffffff8e38e38fULL, 0xffffffffe38e38e4ULL, }, + { 0xffffffffaaaaaaabULL, 0xffffffffaaaaaaabULL, }, /* 16 */ + { 0xffffffffaaaaaaaaULL, 0xffffffffaaaaaaaaULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0xffffffff55555555ULL, 0xffffffff55555555ULL, }, + { 0xffffffffdddddddeULL, 0xffffffffdddddddeULL, }, + { 0xffffffff77777777ULL, 0xffffffff77777777ULL, }, + { 0x000000001c71c71cULL, 0xffffffffc71c71c7ULL, }, + { 0xffffffff38e38e39ULL, 0xffffffff8e38e38eULL, }, + { 0x0000000055555556ULL, 0x0000000055555556ULL, }, /* 24 */ + { 0x0000000055555555ULL, 0x0000000055555555ULL, }, + { 0x00000000aaaaaaabULL, 0x00000000aaaaaaabULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000088888889ULL, 0x0000000088888889ULL, }, + { 0x0000000022222222ULL, 0x0000000022222222ULL, }, + { 0x00000000c71c71c7ULL, 0x0000000071c71c72ULL, }, + { 0xffffffffe38e38e4ULL, 0x0000000038e38e39ULL, }, + { 0xffffffffcccccccdULL, 0xffffffffcccccccdULL, }, /* 32 */ + { 0xffffffffccccccccULL, 0xffffffffccccccccULL, }, + { 0x0000000022222222ULL, 0x0000000022222222ULL, }, + { 0xffffffff77777777ULL, 0xffffffff77777777ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0xffffffff99999999ULL, 0xffffffff99999999ULL, }, + { 0x000000003e93e93eULL, 0xffffffffe93e93e9ULL, }, + { 0xffffffff5b05b05bULL, 0xffffffffb05b05b0ULL, }, + { 0x0000000033333334ULL, 0x0000000033333334ULL, }, /* 40 */ + { 0x0000000033333333ULL, 0x0000000033333333ULL, }, + { 0x0000000088888889ULL, 0x0000000088888889ULL, }, + { 0xffffffffdddddddeULL, 0xffffffffdddddddeULL, }, + { 0x0000000066666667ULL, 0x0000000066666667ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x00000000a4fa4fa5ULL, 0x000000004fa4fa50ULL, }, + { 0xffffffffc16c16c2ULL, 0x0000000016c16c17ULL, }, + { 0xffffffffe38e38e4ULL, 0x0000000038e38e39ULL, }, /* 48 */ + { 0xffffffffe38e38e3ULL, 0x0000000038e38e38ULL, }, + { 0x0000000038e38e39ULL, 0x000000008e38e38eULL, }, + { 0xffffffff8e38e38eULL, 0xffffffffe38e38e3ULL, }, + { 0x0000000016c16c17ULL, 0x000000006c16c16cULL, }, + { 0xffffffffb05b05b0ULL, 0x0000000005b05b05ULL, }, + { 0x0000000055555555ULL, 0x0000000055555555ULL, }, + { 0xffffffff71c71c72ULL, 0x000000001c71c71cULL, }, + { 0x000000001c71c71dULL, 0xffffffffc71c71c8ULL, }, /* 56 */ + { 0x000000001c71c71cULL, 0xffffffffc71c71c7ULL, }, + { 0x0000000071c71c72ULL, 0x000000001c71c71dULL, }, + { 0xffffffffc71c71c7ULL, 0xffffffff71c71c72ULL, }, + { 0x000000004fa4fa50ULL, 0xfffffffffa4fa4fbULL, }, + { 0xffffffffe93e93e9ULL, 0xffffffff93e93e94ULL, }, + { 0x000000008e38e38eULL, 0xffffffffe38e38e4ULL, }, + { 0xffffffffaaaaaaabULL, 0xffffffffaaaaaaabULL, }, + { 0xffffffff6008918cULL, 0x000000004ceb5b52ULL, }, /* 64 */ + { 0xffffffff3ad71fc4ULL, 0x000000003627b862ULL, }, + { 0xffffffffce9b5b4cULL, 0x00000000a03be64aULL, }, + { 0xffffffff2a39047eULL, 0x00000000a22428beULL, }, + { 0xffffffffd35bab23ULL, 0x00000000147c0b0eULL, }, + { 0xffffffffae2a395bULL, 0xfffffffffdb8681eULL, }, + { 0x0000000041ee74e3ULL, 0x0000000067cc9606ULL, }, + { 0xffffffff9d8c1e15ULL, 0x0000000069b4d87aULL, }, + { 0xffffffff83f8596aULL, 0x00000000295d16f3ULL, }, /* 72 */ + { 0xffffffff5ec6e7a2ULL, 0x0000000012997403ULL, }, + { 0xfffffffff28b232aULL, 0x000000007cada1ebULL, }, + { 0xffffffff4e28cc5cULL, 0x000000007e95e45fULL, }, + { 0x0000000047ecc10dULL, 0xffffffff8f75d8ccULL, }, + { 0x0000000022bb4f45ULL, 0xffffffff78b235dcULL, }, + { 0x00000000b67f8acdULL, 0xffffffffe2c663c4ULL, }, + { 0x00000000121d33ffULL, 0xffffffffe4aea638ULL, }, +}; + + reset_msa_registers(); + + gettimeofday(&start, NULL); + + for (i = 0; i < PATTERN_INPUTS_SHORT_COUNT; i++) { + for (j = 0; j < PATTERN_INPUTS_SHORT_COUNT; j++) { + do_msa_HSUB_S_D(b128_pattern[i], b128_pattern[j], + b128_result[PATTERN_INPUTS_SHORT_COUNT * i + j]); + } + } + + for (i = 0; i < RANDOM_INPUTS_SHORT_COUNT; i++) { + for (j = 0; j < RANDOM_INPUTS_SHORT_COUNT; j++) { + do_msa_HSUB_S_D(b128_random[i], b128_random[j], + b128_result[((PATTERN_INPUTS_SHORT_COUNT) * + (PATTERN_INPUTS_SHORT_COUNT)) + + RANDOM_INPUTS_SHORT_COUNT * i + j]); + } + } + + gettimeofday(&end, NULL); + + elapsed_time = (end.tv_sec - start.tv_sec) * 1000.0; + elapsed_time += (end.tv_usec - start.tv_usec) / 1000.0; + + ret = check_results(instruction_name, TEST_COUNT_TOTAL, elapsed_time, + &b128_result[0][0], &b128_expect[0][0]); + + return ret; +} diff --git a/tests/tcg/mips/user/ase/msa/int-subtract/test_msa_hsub_s_h.c b/tests/tcg/mips/user/ase/msa/int-subtract/test_msa_hsub_s_h.c new file mode 100644 index 0000000000..d725d1957a --- /dev/null +++ b/tests/tcg/mips/user/ase/msa/int-subtract/test_msa_hsub_s_h.c @@ -0,0 +1,157 @@ +/* + * Test program for MSA instruction HSUB_S.H + * + * Copyright (C) 2019 Wave Computing, Inc. + * Copyright (C) 2019 Aleksandar Markovic <amarkovic@wavecomp.com> + * Copyright (C) 2019 RT-RK Computer Based Systems LLC + * Copyright (C) 2019 Mateja Marjanovic <mateja.marjanovic@rt-rk.com> + * + * This program 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, see <https://www.gnu.org/licenses/>. + * + */ + +#include <sys/time.h> +#include <stdint.h> + +#include "../../../../include/wrappers_msa.h" +#include "../../../../include/test_inputs_128.h" +#include "../../../../include/test_utils_128.h" + +#define TEST_COUNT_TOTAL ( \ + (PATTERN_INPUTS_SHORT_COUNT) * (PATTERN_INPUTS_SHORT_COUNT) + \ + (RANDOM_INPUTS_SHORT_COUNT) * (RANDOM_INPUTS_SHORT_COUNT)) + + +int32_t main(void) +{ + char *instruction_name = "HSUB_S.H"; + int32_t ret; + uint32_t i, j; + struct timeval start, end; + double elapsed_time; + + uint64_t b128_result[TEST_COUNT_TOTAL][2]; + uint64_t b128_expect[TEST_COUNT_TOTAL][2] = { + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, /* 0 */ + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, + { 0x0055005500550055ULL, 0x0055005500550055ULL, }, + { 0xffaaffaaffaaffaaULL, 0xffaaffaaffaaffaaULL, }, + { 0x0033003300330033ULL, 0x0033003300330033ULL, }, + { 0xffccffccffccffccULL, 0xffccffccffccffccULL, }, + { 0x0071001cffc70071ULL, 0x001cffc70071001cULL, }, + { 0xff8effe30038ff8eULL, 0xffe30038ff8effe3ULL, }, + { 0x0001000100010001ULL, 0x0001000100010001ULL, }, /* 8 */ + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0056005600560056ULL, 0x0056005600560056ULL, }, + { 0xffabffabffabffabULL, 0xffabffabffabffabULL, }, + { 0x0034003400340034ULL, 0x0034003400340034ULL, }, + { 0xffcdffcdffcdffcdULL, 0xffcdffcdffcdffcdULL, }, + { 0x0072001dffc80072ULL, 0x001dffc80072001dULL, }, + { 0xff8fffe40039ff8fULL, 0xffe40039ff8fffe4ULL, }, + { 0xffabffabffabffabULL, 0xffabffabffabffabULL, }, /* 16 */ + { 0xffaaffaaffaaffaaULL, 0xffaaffaaffaaffaaULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0xff55ff55ff55ff55ULL, 0xff55ff55ff55ff55ULL, }, + { 0xffdeffdeffdeffdeULL, 0xffdeffdeffdeffdeULL, }, + { 0xff77ff77ff77ff77ULL, 0xff77ff77ff77ff77ULL, }, + { 0x001cffc7ff72001cULL, 0xffc7ff72001cffc7ULL, }, + { 0xff39ff8effe3ff39ULL, 0xff8effe3ff39ff8eULL, }, + { 0x0056005600560056ULL, 0x0056005600560056ULL, }, /* 24 */ + { 0x0055005500550055ULL, 0x0055005500550055ULL, }, + { 0x00ab00ab00ab00abULL, 0x00ab00ab00ab00abULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0089008900890089ULL, 0x0089008900890089ULL, }, + { 0x0022002200220022ULL, 0x0022002200220022ULL, }, + { 0x00c70072001d00c7ULL, 0x0072001d00c70072ULL, }, + { 0xffe40039008effe4ULL, 0x0039008effe40039ULL, }, + { 0xffcdffcdffcdffcdULL, 0xffcdffcdffcdffcdULL, }, /* 32 */ + { 0xffccffccffccffccULL, 0xffccffccffccffccULL, }, + { 0x0022002200220022ULL, 0x0022002200220022ULL, }, + { 0xff77ff77ff77ff77ULL, 0xff77ff77ff77ff77ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0xff99ff99ff99ff99ULL, 0xff99ff99ff99ff99ULL, }, + { 0x003effe9ff94003eULL, 0xffe9ff94003effe9ULL, }, + { 0xff5bffb00005ff5bULL, 0xffb00005ff5bffb0ULL, }, + { 0x0034003400340034ULL, 0x0034003400340034ULL, }, /* 40 */ + { 0x0033003300330033ULL, 0x0033003300330033ULL, }, + { 0x0089008900890089ULL, 0x0089008900890089ULL, }, + { 0xffdeffdeffdeffdeULL, 0xffdeffdeffdeffdeULL, }, + { 0x0067006700670067ULL, 0x0067006700670067ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x00a50050fffb00a5ULL, 0x0050fffb00a50050ULL, }, + { 0xffc20017006cffc2ULL, 0x0017006cffc20017ULL, }, + { 0xffe40039ff8fffe4ULL, 0x0039ff8fffe40039ULL, }, /* 48 */ + { 0xffe30038ff8effe3ULL, 0x0038ff8effe30038ULL, }, + { 0x0039008effe40039ULL, 0x008effe40039008eULL, }, + { 0xff8effe3ff39ff8eULL, 0xffe3ff39ff8effe3ULL, }, + { 0x0017006cffc20017ULL, 0x006cffc20017006cULL, }, + { 0xffb00005ff5bffb0ULL, 0x0005ff5bffb00005ULL, }, + { 0x00550055ff560055ULL, 0x0055ff5600550055ULL, }, + { 0xff72001cffc7ff72ULL, 0x001cffc7ff72001cULL, }, + { 0x001dffc80072001dULL, 0xffc80072001dffc8ULL, }, /* 56 */ + { 0x001cffc70071001cULL, 0xffc70071001cffc7ULL, }, + { 0x0072001d00c70072ULL, 0x001d00c70072001dULL, }, + { 0xffc7ff72001cffc7ULL, 0xff72001cffc7ff72ULL, }, + { 0x0050fffb00a50050ULL, 0xfffb00a50050fffbULL, }, + { 0xffe9ff94003effe9ULL, 0xff94003effe9ff94ULL, }, + { 0x008effe40039008eULL, 0xffe40039008effe4ULL, }, + { 0xffabffab00aaffabULL, 0xffab00aaffabffabULL, }, + { 0xff1e001affc60015ULL, 0xffe4ffadff83ffa4ULL, }, /* 64 */ + { 0xffcaff830095004dULL, 0x0054fff1ffbfffb4ULL, }, + { 0xff2e003c005900d5ULL, 0x0073000cffd3ff9cULL, }, + { 0xff39ff99fff70007ULL, 0x005a0033ffbc0010ULL, }, + { 0xff910034ffebff87ULL, 0xffabff5dff9a0046ULL, }, + { 0x003dff9d00baffbfULL, 0x001bffa1ffd60056ULL, }, + { 0xffa10056007e0047ULL, 0x003affbcffea003eULL, }, + { 0xffacffb3001cff79ULL, 0x0021ffe3ffd300b2ULL, }, + { 0xff42ffe2ff57ff4bULL, 0xffc0ff68ff300019ULL, }, /* 72 */ + { 0xffeeff4b0026ff83ULL, 0x0030ffacff6c0029ULL, }, + { 0xff520004ffea000bULL, 0x004fffc7ff800011ULL, }, + { 0xff5dff61ff88ff3dULL, 0x0036ffeeff690085ULL, }, + { 0x0006004afffcffa2ULL, 0xff26ff2aff2effd6ULL, }, + { 0x00b2ffb300cbffdaULL, 0xff96ff6eff6affe6ULL, }, + { 0x0016006c008f0062ULL, 0xffb5ff89ff7effceULL, }, + { 0x0021ffc9002dff94ULL, 0xff9cffb0ff670042ULL, }, +}; + + reset_msa_registers(); + + gettimeofday(&start, NULL); + + for (i = 0; i < PATTERN_INPUTS_SHORT_COUNT; i++) { + for (j = 0; j < PATTERN_INPUTS_SHORT_COUNT; j++) { + do_msa_HSUB_S_H(b128_pattern[i], b128_pattern[j], + b128_result[PATTERN_INPUTS_SHORT_COUNT * i + j]); + } + } + + for (i = 0; i < RANDOM_INPUTS_SHORT_COUNT; i++) { + for (j = 0; j < RANDOM_INPUTS_SHORT_COUNT; j++) { + do_msa_HSUB_S_H(b128_random[i], b128_random[j], + b128_result[((PATTERN_INPUTS_SHORT_COUNT) * + (PATTERN_INPUTS_SHORT_COUNT)) + + RANDOM_INPUTS_SHORT_COUNT * i + j]); + } + } + + gettimeofday(&end, NULL); + + elapsed_time = (end.tv_sec - start.tv_sec) * 1000.0; + elapsed_time += (end.tv_usec - start.tv_usec) / 1000.0; + + ret = check_results(instruction_name, TEST_COUNT_TOTAL, elapsed_time, + &b128_result[0][0], &b128_expect[0][0]); + + return ret; +} diff --git a/tests/tcg/mips/user/ase/msa/int-subtract/test_msa_hsub_s_w.c b/tests/tcg/mips/user/ase/msa/int-subtract/test_msa_hsub_s_w.c new file mode 100644 index 0000000000..af13d99c0f --- /dev/null +++ b/tests/tcg/mips/user/ase/msa/int-subtract/test_msa_hsub_s_w.c @@ -0,0 +1,157 @@ +/* + * Test program for MSA instruction HSUB_S.W + * + * Copyright (C) 2019 Wave Computing, Inc. + * Copyright (C) 2019 Aleksandar Markovic <amarkovic@wavecomp.com> + * Copyright (C) 2019 RT-RK Computer Based Systems LLC + * Copyright (C) 2019 Mateja Marjanovic <mateja.marjanovic@rt-rk.com> + * + * This program 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, see <https://www.gnu.org/licenses/>. + * + */ + +#include <sys/time.h> +#include <stdint.h> + +#include "../../../../include/wrappers_msa.h" +#include "../../../../include/test_inputs_128.h" +#include "../../../../include/test_utils_128.h" + +#define TEST_COUNT_TOTAL ( \ + (PATTERN_INPUTS_SHORT_COUNT) * (PATTERN_INPUTS_SHORT_COUNT) + \ + (RANDOM_INPUTS_SHORT_COUNT) * (RANDOM_INPUTS_SHORT_COUNT)) + + +int32_t main(void) +{ + char *instruction_name = "HSUB_S.W"; + int32_t ret; + uint32_t i, j; + struct timeval start, end; + double elapsed_time; + + uint64_t b128_result[TEST_COUNT_TOTAL][2]; + uint64_t b128_expect[TEST_COUNT_TOTAL][2] = { + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, /* 0 */ + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, + { 0x0000555500005555ULL, 0x0000555500005555ULL, }, + { 0xffffaaaaffffaaaaULL, 0xffffaaaaffffaaaaULL, }, + { 0x0000333300003333ULL, 0x0000333300003333ULL, }, + { 0xffffccccffffccccULL, 0xffffccccffffccccULL, }, + { 0xffffc71c00001c71ULL, 0x000071c7ffffc71cULL, }, + { 0x000038e3ffffe38eULL, 0xffff8e38000038e3ULL, }, + { 0x0000000100000001ULL, 0x0000000100000001ULL, }, /* 8 */ + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000555600005556ULL, 0x0000555600005556ULL, }, + { 0xffffaaabffffaaabULL, 0xffffaaabffffaaabULL, }, + { 0x0000333400003334ULL, 0x0000333400003334ULL, }, + { 0xffffcccdffffcccdULL, 0xffffcccdffffcccdULL, }, + { 0xffffc71d00001c72ULL, 0x000071c8ffffc71dULL, }, + { 0x000038e4ffffe38fULL, 0xffff8e39000038e4ULL, }, + { 0xffffaaabffffaaabULL, 0xffffaaabffffaaabULL, }, /* 16 */ + { 0xffffaaaaffffaaaaULL, 0xffffaaaaffffaaaaULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0xffff5555ffff5555ULL, 0xffff5555ffff5555ULL, }, + { 0xffffdddeffffdddeULL, 0xffffdddeffffdddeULL, }, + { 0xffff7777ffff7777ULL, 0xffff7777ffff7777ULL, }, + { 0xffff71c7ffffc71cULL, 0x00001c72ffff71c7ULL, }, + { 0xffffe38effff8e39ULL, 0xffff38e3ffffe38eULL, }, + { 0x0000555600005556ULL, 0x0000555600005556ULL, }, /* 24 */ + { 0x0000555500005555ULL, 0x0000555500005555ULL, }, + { 0x0000aaab0000aaabULL, 0x0000aaab0000aaabULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000888900008889ULL, 0x0000888900008889ULL, }, + { 0x0000222200002222ULL, 0x0000222200002222ULL, }, + { 0x00001c72000071c7ULL, 0x0000c71d00001c72ULL, }, + { 0x00008e39000038e4ULL, 0xffffe38e00008e39ULL, }, + { 0xffffcccdffffcccdULL, 0xffffcccdffffcccdULL, }, /* 32 */ + { 0xffffccccffffccccULL, 0xffffccccffffccccULL, }, + { 0x0000222200002222ULL, 0x0000222200002222ULL, }, + { 0xffff7777ffff7777ULL, 0xffff7777ffff7777ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0xffff9999ffff9999ULL, 0xffff9999ffff9999ULL, }, + { 0xffff93e9ffffe93eULL, 0x00003e94ffff93e9ULL, }, + { 0x000005b0ffffb05bULL, 0xffff5b05000005b0ULL, }, + { 0x0000333400003334ULL, 0x0000333400003334ULL, }, /* 40 */ + { 0x0000333300003333ULL, 0x0000333300003333ULL, }, + { 0x0000888900008889ULL, 0x0000888900008889ULL, }, + { 0xffffdddeffffdddeULL, 0xffffdddeffffdddeULL, }, + { 0x0000666700006667ULL, 0x0000666700006667ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0xfffffa5000004fa5ULL, 0x0000a4fbfffffa50ULL, }, + { 0x00006c17000016c2ULL, 0xffffc16c00006c17ULL, }, + { 0xffffe38fffff8e39ULL, 0x000038e4ffffe38fULL, }, /* 48 */ + { 0xffffe38effff8e38ULL, 0x000038e3ffffe38eULL, }, + { 0x000038e4ffffe38eULL, 0x00008e39000038e4ULL, }, + { 0xffff8e39ffff38e3ULL, 0xffffe38effff8e39ULL, }, + { 0x000016c2ffffc16cULL, 0x00006c17000016c2ULL, }, + { 0xffffb05bffff5b05ULL, 0x000005b0ffffb05bULL, }, + { 0xffffaaabffffaaaaULL, 0x0000aaabffffaaabULL, }, + { 0x00001c72ffff71c7ULL, 0xffffc71c00001c72ULL, }, + { 0x00001c72000071c8ULL, 0xffffc71d00001c72ULL, }, /* 56 */ + { 0x00001c71000071c7ULL, 0xffffc71c00001c71ULL, }, + { 0x000071c70000c71dULL, 0x00001c72000071c7ULL, }, + { 0xffffc71c00001c72ULL, 0xffff71c7ffffc71cULL, }, + { 0x00004fa50000a4fbULL, 0xfffffa5000004fa5ULL, }, + { 0xffffe93e00003e94ULL, 0xffff93e9ffffe93eULL, }, + { 0xffffe38e00008e39ULL, 0x000038e4ffffe38eULL, }, + { 0x0000555500005556ULL, 0xffff555500005555ULL, }, + { 0xffffa19effffd322ULL, 0x0000400900004e6fULL, }, /* 64 */ + { 0xffff88070000615aULL, 0x0000904dffffab7fULL, }, + { 0xffffd9c000009ce2ULL, 0x00008468ffffd967ULL, }, + { 0xffff721d00004614ULL, 0x0000c28f00001bdbULL, }, + { 0x000014f2fffff853ULL, 0x0000079900006533ULL, }, + { 0xfffffb5b0000868bULL, 0x000057ddffffc243ULL, }, + { 0x00004d140000c213ULL, 0x00004bf8fffff02bULL, }, + { 0xffffe57100006b45ULL, 0x00008a1f0000329fULL, }, + { 0xffffc58effff648fULL, 0x00001c7afffffb1fULL, }, /* 72 */ + { 0xffffabf7fffff2c7ULL, 0x00006cbeffff582fULL, }, + { 0xfffffdb000002e4fULL, 0x000060d9ffff8617ULL, }, + { 0xffff960dffffd781ULL, 0x00009f00ffffc88bULL, }, + { 0x00008983000008f1ULL, 0xffff8293fffff936ULL, }, + { 0x00006fec00009729ULL, 0xffffd2d7ffff5646ULL, }, + { 0x0000c1a50000d2b1ULL, 0xffffc6f2ffff842eULL, }, + { 0x00005a0200007be3ULL, 0x00000519ffffc6a2ULL, }, +}; + + reset_msa_registers(); + + gettimeofday(&start, NULL); + + for (i = 0; i < PATTERN_INPUTS_SHORT_COUNT; i++) { + for (j = 0; j < PATTERN_INPUTS_SHORT_COUNT; j++) { + do_msa_HSUB_S_W(b128_pattern[i], b128_pattern[j], + b128_result[PATTERN_INPUTS_SHORT_COUNT * i + j]); + } + } + + for (i = 0; i < RANDOM_INPUTS_SHORT_COUNT; i++) { + for (j = 0; j < RANDOM_INPUTS_SHORT_COUNT; j++) { + do_msa_HSUB_S_W(b128_random[i], b128_random[j], + b128_result[((PATTERN_INPUTS_SHORT_COUNT) * + (PATTERN_INPUTS_SHORT_COUNT)) + + RANDOM_INPUTS_SHORT_COUNT * i + j]); + } + } + + gettimeofday(&end, NULL); + + elapsed_time = (end.tv_sec - start.tv_sec) * 1000.0; + elapsed_time += (end.tv_usec - start.tv_usec) / 1000.0; + + ret = check_results(instruction_name, TEST_COUNT_TOTAL, elapsed_time, + &b128_result[0][0], &b128_expect[0][0]); + + return ret; +} diff --git a/tests/tcg/mips/user/ase/msa/int-subtract/test_msa_hsub_u_d.c b/tests/tcg/mips/user/ase/msa/int-subtract/test_msa_hsub_u_d.c new file mode 100644 index 0000000000..bd71abfc4f --- /dev/null +++ b/tests/tcg/mips/user/ase/msa/int-subtract/test_msa_hsub_u_d.c @@ -0,0 +1,157 @@ +/* + * Test program for MSA instruction HSUB_U.D + * + * Copyright (C) 2019 Wave Computing, Inc. + * Copyright (C) 2019 Aleksandar Markovic <amarkovic@wavecomp.com> + * Copyright (C) 2019 RT-RK Computer Based Systems LLC + * Copyright (C) 2019 Mateja Marjanovic <mateja.marjanovic@rt-rk.com> + * + * This program 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, see <https://www.gnu.org/licenses/>. + * + */ + +#include <sys/time.h> +#include <stdint.h> + +#include "../../../../include/wrappers_msa.h" +#include "../../../../include/test_inputs_128.h" +#include "../../../../include/test_utils_128.h" + +#define TEST_COUNT_TOTAL ( \ + (PATTERN_INPUTS_SHORT_COUNT) * (PATTERN_INPUTS_SHORT_COUNT) + \ + (RANDOM_INPUTS_SHORT_COUNT) * (RANDOM_INPUTS_SHORT_COUNT)) + + +int32_t main(void) +{ + char *instruction_name = "HSUB_U.D"; + int32_t ret; + uint32_t i, j; + struct timeval start, end; + double elapsed_time; + + uint64_t b128_result[TEST_COUNT_TOTAL][2]; + uint64_t b128_expect[TEST_COUNT_TOTAL][2] = { + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, /* 0 */ + { 0x00000000ffffffffULL, 0x00000000ffffffffULL, }, + { 0x0000000055555555ULL, 0x0000000055555555ULL, }, + { 0x00000000aaaaaaaaULL, 0x00000000aaaaaaaaULL, }, + { 0x0000000033333333ULL, 0x0000000033333333ULL, }, + { 0x00000000ccccccccULL, 0x00000000ccccccccULL, }, + { 0x0000000071c71c71ULL, 0x000000001c71c71cULL, }, + { 0x000000008e38e38eULL, 0x00000000e38e38e3ULL, }, + { 0xffffffff00000001ULL, 0xffffffff00000001ULL, }, /* 8 */ + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0xffffffff55555556ULL, 0xffffffff55555556ULL, }, + { 0xffffffffaaaaaaabULL, 0xffffffffaaaaaaabULL, }, + { 0xffffffff33333334ULL, 0xffffffff33333334ULL, }, + { 0xffffffffcccccccdULL, 0xffffffffcccccccdULL, }, + { 0xffffffff71c71c72ULL, 0xffffffff1c71c71dULL, }, + { 0xffffffff8e38e38fULL, 0xffffffffe38e38e4ULL, }, + { 0xffffffffaaaaaaabULL, 0xffffffffaaaaaaabULL, }, /* 16 */ + { 0x00000000aaaaaaaaULL, 0x00000000aaaaaaaaULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000055555555ULL, 0x0000000055555555ULL, }, + { 0xffffffffdddddddeULL, 0xffffffffdddddddeULL, }, + { 0x0000000077777777ULL, 0x0000000077777777ULL, }, + { 0x000000001c71c71cULL, 0xffffffffc71c71c7ULL, }, + { 0x0000000038e38e39ULL, 0x000000008e38e38eULL, }, + { 0xffffffff55555556ULL, 0xffffffff55555556ULL, }, /* 24 */ + { 0x0000000055555555ULL, 0x0000000055555555ULL, }, + { 0xffffffffaaaaaaabULL, 0xffffffffaaaaaaabULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0xffffffff88888889ULL, 0xffffffff88888889ULL, }, + { 0x0000000022222222ULL, 0x0000000022222222ULL, }, + { 0xffffffffc71c71c7ULL, 0xffffffff71c71c72ULL, }, + { 0xffffffffe38e38e4ULL, 0x0000000038e38e39ULL, }, + { 0xffffffffcccccccdULL, 0xffffffffcccccccdULL, }, /* 32 */ + { 0x00000000ccccccccULL, 0x00000000ccccccccULL, }, + { 0x0000000022222222ULL, 0x0000000022222222ULL, }, + { 0x0000000077777777ULL, 0x0000000077777777ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000099999999ULL, 0x0000000099999999ULL, }, + { 0x000000003e93e93eULL, 0xffffffffe93e93e9ULL, }, + { 0x000000005b05b05bULL, 0x00000000b05b05b0ULL, }, + { 0xffffffff33333334ULL, 0xffffffff33333334ULL, }, /* 40 */ + { 0x0000000033333333ULL, 0x0000000033333333ULL, }, + { 0xffffffff88888889ULL, 0xffffffff88888889ULL, }, + { 0xffffffffdddddddeULL, 0xffffffffdddddddeULL, }, + { 0xffffffff66666667ULL, 0xffffffff66666667ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0xffffffffa4fa4fa5ULL, 0xffffffff4fa4fa50ULL, }, + { 0xffffffffc16c16c2ULL, 0x0000000016c16c17ULL, }, + { 0xffffffffe38e38e4ULL, 0xffffffff38e38e39ULL, }, /* 48 */ + { 0x00000000e38e38e3ULL, 0x0000000038e38e38ULL, }, + { 0x0000000038e38e39ULL, 0xffffffff8e38e38eULL, }, + { 0x000000008e38e38eULL, 0xffffffffe38e38e3ULL, }, + { 0x0000000016c16c17ULL, 0xffffffff6c16c16cULL, }, + { 0x00000000b05b05b0ULL, 0x0000000005b05b05ULL, }, + { 0x0000000055555555ULL, 0xffffffff55555555ULL, }, + { 0x0000000071c71c72ULL, 0x000000001c71c71cULL, }, + { 0xffffffff1c71c71dULL, 0xffffffffc71c71c8ULL, }, /* 56 */ + { 0x000000001c71c71cULL, 0x00000000c71c71c7ULL, }, + { 0xffffffff71c71c72ULL, 0x000000001c71c71dULL, }, + { 0xffffffffc71c71c7ULL, 0x0000000071c71c72ULL, }, + { 0xffffffff4fa4fa50ULL, 0xfffffffffa4fa4fbULL, }, + { 0xffffffffe93e93e9ULL, 0x0000000093e93e94ULL, }, + { 0xffffffff8e38e38eULL, 0xffffffffe38e38e4ULL, }, + { 0xffffffffaaaaaaabULL, 0x00000000aaaaaaabULL, }, + { 0x000000006008918cULL, 0xffffffff4ceb5b52ULL, }, /* 64 */ + { 0x000000003ad71fc4ULL, 0x000000003627b862ULL, }, + { 0xffffffffce9b5b4cULL, 0xffffffffa03be64aULL, }, + { 0x000000002a39047eULL, 0xffffffffa22428beULL, }, + { 0x00000000d35bab23ULL, 0xffffffff147c0b0eULL, }, + { 0x00000000ae2a395bULL, 0xfffffffffdb8681eULL, }, + { 0x0000000041ee74e3ULL, 0xffffffff67cc9606ULL, }, + { 0x000000009d8c1e15ULL, 0xffffffff69b4d87aULL, }, + { 0x0000000083f8596aULL, 0xffffffff295d16f3ULL, }, /* 72 */ + { 0x000000005ec6e7a2ULL, 0x0000000012997403ULL, }, + { 0xfffffffff28b232aULL, 0xffffffff7cada1ebULL, }, + { 0x000000004e28cc5cULL, 0xffffffff7e95e45fULL, }, + { 0x0000000047ecc10dULL, 0xffffffff8f75d8ccULL, }, + { 0x0000000022bb4f45ULL, 0x0000000078b235dcULL, }, + { 0xffffffffb67f8acdULL, 0xffffffffe2c663c4ULL, }, + { 0x00000000121d33ffULL, 0xffffffffe4aea638ULL, }, +}; + + reset_msa_registers(); + + gettimeofday(&start, NULL); + + for (i = 0; i < PATTERN_INPUTS_SHORT_COUNT; i++) { + for (j = 0; j < PATTERN_INPUTS_SHORT_COUNT; j++) { + do_msa_HSUB_U_D(b128_pattern[i], b128_pattern[j], + b128_result[PATTERN_INPUTS_SHORT_COUNT * i + j]); + } + } + + for (i = 0; i < RANDOM_INPUTS_SHORT_COUNT; i++) { + for (j = 0; j < RANDOM_INPUTS_SHORT_COUNT; j++) { + do_msa_HSUB_U_D(b128_random[i], b128_random[j], + b128_result[((PATTERN_INPUTS_SHORT_COUNT) * + (PATTERN_INPUTS_SHORT_COUNT)) + + RANDOM_INPUTS_SHORT_COUNT * i + j]); + } + } + + gettimeofday(&end, NULL); + + elapsed_time = (end.tv_sec - start.tv_sec) * 1000.0; + elapsed_time += (end.tv_usec - start.tv_usec) / 1000.0; + + ret = check_results(instruction_name, TEST_COUNT_TOTAL, elapsed_time, + &b128_result[0][0], &b128_expect[0][0]); + + return ret; +} diff --git a/tests/tcg/mips/user/ase/msa/int-subtract/test_msa_hsub_u_h.c b/tests/tcg/mips/user/ase/msa/int-subtract/test_msa_hsub_u_h.c new file mode 100644 index 0000000000..fbf0b6c45c --- /dev/null +++ b/tests/tcg/mips/user/ase/msa/int-subtract/test_msa_hsub_u_h.c @@ -0,0 +1,157 @@ +/* + * Test program for MSA instruction HSUB_U.H + * + * Copyright (C) 2019 Wave Computing, Inc. + * Copyright (C) 2019 Aleksandar Markovic <amarkovic@wavecomp.com> + * Copyright (C) 2019 RT-RK Computer Based Systems LLC + * Copyright (C) 2019 Mateja Marjanovic <mateja.marjanovic@rt-rk.com> + * + * This program 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, see <https://www.gnu.org/licenses/>. + * + */ + +#include <sys/time.h> +#include <stdint.h> + +#include "../../../../include/wrappers_msa.h" +#include "../../../../include/test_inputs_128.h" +#include "../../../../include/test_utils_128.h" + +#define TEST_COUNT_TOTAL ( \ + (PATTERN_INPUTS_SHORT_COUNT) * (PATTERN_INPUTS_SHORT_COUNT) + \ + (RANDOM_INPUTS_SHORT_COUNT) * (RANDOM_INPUTS_SHORT_COUNT)) + + +int32_t main(void) +{ + char *instruction_name = "HSUB_U.H"; + int32_t ret; + uint32_t i, j; + struct timeval start, end; + double elapsed_time; + + uint64_t b128_result[TEST_COUNT_TOTAL][2]; + uint64_t b128_expect[TEST_COUNT_TOTAL][2] = { + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, /* 0 */ + { 0x00ff00ff00ff00ffULL, 0x00ff00ff00ff00ffULL, }, + { 0x0055005500550055ULL, 0x0055005500550055ULL, }, + { 0x00aa00aa00aa00aaULL, 0x00aa00aa00aa00aaULL, }, + { 0x0033003300330033ULL, 0x0033003300330033ULL, }, + { 0x00cc00cc00cc00ccULL, 0x00cc00cc00cc00ccULL, }, + { 0x0071001c00c70071ULL, 0x001c00c70071001cULL, }, + { 0x008e00e30038008eULL, 0x00e30038008e00e3ULL, }, + { 0xff01ff01ff01ff01ULL, 0xff01ff01ff01ff01ULL, }, /* 8 */ + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0xff56ff56ff56ff56ULL, 0xff56ff56ff56ff56ULL, }, + { 0xffabffabffabffabULL, 0xffabffabffabffabULL, }, + { 0xff34ff34ff34ff34ULL, 0xff34ff34ff34ff34ULL, }, + { 0xffcdffcdffcdffcdULL, 0xffcdffcdffcdffcdULL, }, + { 0xff72ff1dffc8ff72ULL, 0xff1dffc8ff72ff1dULL, }, + { 0xff8fffe4ff39ff8fULL, 0xffe4ff39ff8fffe4ULL, }, + { 0xffabffabffabffabULL, 0xffabffabffabffabULL, }, /* 16 */ + { 0x00aa00aa00aa00aaULL, 0x00aa00aa00aa00aaULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0055005500550055ULL, 0x0055005500550055ULL, }, + { 0xffdeffdeffdeffdeULL, 0xffdeffdeffdeffdeULL, }, + { 0x0077007700770077ULL, 0x0077007700770077ULL, }, + { 0x001cffc70072001cULL, 0xffc70072001cffc7ULL, }, + { 0x0039008effe30039ULL, 0x008effe30039008eULL, }, + { 0xff56ff56ff56ff56ULL, 0xff56ff56ff56ff56ULL, }, /* 24 */ + { 0x0055005500550055ULL, 0x0055005500550055ULL, }, + { 0xffabffabffabffabULL, 0xffabffabffabffabULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0xff89ff89ff89ff89ULL, 0xff89ff89ff89ff89ULL, }, + { 0x0022002200220022ULL, 0x0022002200220022ULL, }, + { 0xffc7ff72001dffc7ULL, 0xff72001dffc7ff72ULL, }, + { 0xffe40039ff8effe4ULL, 0x0039ff8effe40039ULL, }, + { 0xffcdffcdffcdffcdULL, 0xffcdffcdffcdffcdULL, }, /* 32 */ + { 0x00cc00cc00cc00ccULL, 0x00cc00cc00cc00ccULL, }, + { 0x0022002200220022ULL, 0x0022002200220022ULL, }, + { 0x0077007700770077ULL, 0x0077007700770077ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0099009900990099ULL, 0x0099009900990099ULL, }, + { 0x003effe90094003eULL, 0xffe90094003effe9ULL, }, + { 0x005b00b00005005bULL, 0x00b00005005b00b0ULL, }, + { 0xff34ff34ff34ff34ULL, 0xff34ff34ff34ff34ULL, }, /* 40 */ + { 0x0033003300330033ULL, 0x0033003300330033ULL, }, + { 0xff89ff89ff89ff89ULL, 0xff89ff89ff89ff89ULL, }, + { 0xffdeffdeffdeffdeULL, 0xffdeffdeffdeffdeULL, }, + { 0xff67ff67ff67ff67ULL, 0xff67ff67ff67ff67ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0xffa5ff50fffbffa5ULL, 0xff50fffbffa5ff50ULL, }, + { 0xffc20017ff6cffc2ULL, 0x0017ff6cffc20017ULL, }, + { 0xffe4ff39ff8fffe4ULL, 0xff39ff8fffe4ff39ULL, }, /* 48 */ + { 0x00e30038008e00e3ULL, 0x0038008e00e30038ULL, }, + { 0x0039ff8effe40039ULL, 0xff8effe40039ff8eULL, }, + { 0x008effe30039008eULL, 0xffe30039008effe3ULL, }, + { 0x0017ff6cffc20017ULL, 0xff6cffc20017ff6cULL, }, + { 0x00b00005005b00b0ULL, 0x0005005b00b00005ULL, }, + { 0x0055ff5500560055ULL, 0xff5500560055ff55ULL, }, + { 0x0072001cffc70072ULL, 0x001cffc70072001cULL, }, + { 0xff1dffc8ff72ff1dULL, 0xffc8ff72ff1dffc8ULL, }, /* 56 */ + { 0x001c00c70071001cULL, 0x00c70071001c00c7ULL, }, + { 0xff72001dffc7ff72ULL, 0x001dffc7ff72001dULL, }, + { 0xffc70072001cffc7ULL, 0x0072001cffc70072ULL, }, + { 0xff50fffbffa5ff50ULL, 0xfffbffa5ff50fffbULL, }, + { 0xffe90094003effe9ULL, 0x0094003effe90094ULL, }, + { 0xff8effe40039ff8eULL, 0xffe40039ff8effe4ULL, }, + { 0xffab00abffaaffabULL, 0x00abffaaffab00abULL, }, + { 0x001e001affc60015ULL, 0xffe4ffad008300a4ULL, }, /* 64 */ + { 0xffca0083ff95004dULL, 0xff54fff100bfffb4ULL, }, + { 0x002e003cff59ffd5ULL, 0xff73ff0c00d3009cULL, }, + { 0x00390099fff70007ULL, 0xff5aff3300bc0010ULL, }, + { 0x0091ff34ffeb0087ULL, 0xffab005dff9a0046ULL, }, + { 0x003dff9dffba00bfULL, 0xff1b00a1ffd6ff56ULL, }, + { 0x00a1ff56ff7e0047ULL, 0xff3affbcffea003eULL, }, + { 0x00acffb3001c0079ULL, 0xff21ffe3ffd3ffb2ULL, }, + { 0x0042ffe20057004bULL, 0xffc0006800300019ULL, }, /* 72 */ + { 0xffee004b00260083ULL, 0xff3000ac006cff29ULL, }, + { 0x00520004ffea000bULL, 0xff4fffc700800011ULL, }, + { 0x005d00610088003dULL, 0xff36ffee0069ff85ULL, }, + { 0x0006ff4afffc00a2ULL, 0x0026002a002e00d6ULL, }, + { 0xffb2ffb3ffcb00daULL, 0xff96006e006affe6ULL, }, + { 0x0016ff6cff8f0062ULL, 0xffb5ff89007e00ceULL, }, + { 0x0021ffc9002d0094ULL, 0xff9cffb000670042ULL, }, +}; + + reset_msa_registers(); + + gettimeofday(&start, NULL); + + for (i = 0; i < PATTERN_INPUTS_SHORT_COUNT; i++) { + for (j = 0; j < PATTERN_INPUTS_SHORT_COUNT; j++) { + do_msa_HSUB_U_H(b128_pattern[i], b128_pattern[j], + b128_result[PATTERN_INPUTS_SHORT_COUNT * i + j]); + } + } + + for (i = 0; i < RANDOM_INPUTS_SHORT_COUNT; i++) { + for (j = 0; j < RANDOM_INPUTS_SHORT_COUNT; j++) { + do_msa_HSUB_U_H(b128_random[i], b128_random[j], + b128_result[((PATTERN_INPUTS_SHORT_COUNT) * + (PATTERN_INPUTS_SHORT_COUNT)) + + RANDOM_INPUTS_SHORT_COUNT * i + j]); + } + } + + gettimeofday(&end, NULL); + + elapsed_time = (end.tv_sec - start.tv_sec) * 1000.0; + elapsed_time += (end.tv_usec - start.tv_usec) / 1000.0; + + ret = check_results(instruction_name, TEST_COUNT_TOTAL, elapsed_time, + &b128_result[0][0], &b128_expect[0][0]); + + return ret; +} diff --git a/tests/tcg/mips/user/ase/msa/int-subtract/test_msa_hsub_u_w.c b/tests/tcg/mips/user/ase/msa/int-subtract/test_msa_hsub_u_w.c new file mode 100644 index 0000000000..fb6b91a3a2 --- /dev/null +++ b/tests/tcg/mips/user/ase/msa/int-subtract/test_msa_hsub_u_w.c @@ -0,0 +1,157 @@ +/* + * Test program for MSA instruction HSUB_U.W + * + * Copyright (C) 2019 Wave Computing, Inc. + * Copyright (C) 2019 Aleksandar Markovic <amarkovic@wavecomp.com> + * Copyright (C) 2019 RT-RK Computer Based Systems LLC + * Copyright (C) 2019 Mateja Marjanovic <mateja.marjanovic@rt-rk.com> + * + * This program 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, see <https://www.gnu.org/licenses/>. + * + */ + +#include <sys/time.h> +#include <stdint.h> + +#include "../../../../include/wrappers_msa.h" +#include "../../../../include/test_inputs_128.h" +#include "../../../../include/test_utils_128.h" + +#define TEST_COUNT_TOTAL ( \ + (PATTERN_INPUTS_SHORT_COUNT) * (PATTERN_INPUTS_SHORT_COUNT) + \ + (RANDOM_INPUTS_SHORT_COUNT) * (RANDOM_INPUTS_SHORT_COUNT)) + + +int32_t main(void) +{ + char *instruction_name = "HSUB_U.W"; + int32_t ret; + uint32_t i, j; + struct timeval start, end; + double elapsed_time; + + uint64_t b128_result[TEST_COUNT_TOTAL][2]; + uint64_t b128_expect[TEST_COUNT_TOTAL][2] = { + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, /* 0 */ + { 0x0000ffff0000ffffULL, 0x0000ffff0000ffffULL, }, + { 0x0000555500005555ULL, 0x0000555500005555ULL, }, + { 0x0000aaaa0000aaaaULL, 0x0000aaaa0000aaaaULL, }, + { 0x0000333300003333ULL, 0x0000333300003333ULL, }, + { 0x0000cccc0000ccccULL, 0x0000cccc0000ccccULL, }, + { 0x0000c71c00001c71ULL, 0x000071c70000c71cULL, }, + { 0x000038e30000e38eULL, 0x00008e38000038e3ULL, }, + { 0xffff0001ffff0001ULL, 0xffff0001ffff0001ULL, }, /* 8 */ + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0xffff5556ffff5556ULL, 0xffff5556ffff5556ULL, }, + { 0xffffaaabffffaaabULL, 0xffffaaabffffaaabULL, }, + { 0xffff3334ffff3334ULL, 0xffff3334ffff3334ULL, }, + { 0xffffcccdffffcccdULL, 0xffffcccdffffcccdULL, }, + { 0xffffc71dffff1c72ULL, 0xffff71c8ffffc71dULL, }, + { 0xffff38e4ffffe38fULL, 0xffff8e39ffff38e4ULL, }, + { 0xffffaaabffffaaabULL, 0xffffaaabffffaaabULL, }, /* 16 */ + { 0x0000aaaa0000aaaaULL, 0x0000aaaa0000aaaaULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000555500005555ULL, 0x0000555500005555ULL, }, + { 0xffffdddeffffdddeULL, 0xffffdddeffffdddeULL, }, + { 0x0000777700007777ULL, 0x0000777700007777ULL, }, + { 0x000071c7ffffc71cULL, 0x00001c72000071c7ULL, }, + { 0xffffe38e00008e39ULL, 0x000038e3ffffe38eULL, }, + { 0xffff5556ffff5556ULL, 0xffff5556ffff5556ULL, }, /* 24 */ + { 0x0000555500005555ULL, 0x0000555500005555ULL, }, + { 0xffffaaabffffaaabULL, 0xffffaaabffffaaabULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0xffff8889ffff8889ULL, 0xffff8889ffff8889ULL, }, + { 0x0000222200002222ULL, 0x0000222200002222ULL, }, + { 0x00001c72ffff71c7ULL, 0xffffc71d00001c72ULL, }, + { 0xffff8e39000038e4ULL, 0xffffe38effff8e39ULL, }, + { 0xffffcccdffffcccdULL, 0xffffcccdffffcccdULL, }, /* 32 */ + { 0x0000cccc0000ccccULL, 0x0000cccc0000ccccULL, }, + { 0x0000222200002222ULL, 0x0000222200002222ULL, }, + { 0x0000777700007777ULL, 0x0000777700007777ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000999900009999ULL, 0x0000999900009999ULL, }, + { 0x000093e9ffffe93eULL, 0x00003e94000093e9ULL, }, + { 0x000005b00000b05bULL, 0x00005b05000005b0ULL, }, + { 0xffff3334ffff3334ULL, 0xffff3334ffff3334ULL, }, /* 40 */ + { 0x0000333300003333ULL, 0x0000333300003333ULL, }, + { 0xffff8889ffff8889ULL, 0xffff8889ffff8889ULL, }, + { 0xffffdddeffffdddeULL, 0xffffdddeffffdddeULL, }, + { 0xffff6667ffff6667ULL, 0xffff6667ffff6667ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0xfffffa50ffff4fa5ULL, 0xffffa4fbfffffa50ULL, }, + { 0xffff6c17000016c2ULL, 0xffffc16cffff6c17ULL, }, + { 0xffffe38fffff8e39ULL, 0xffff38e4ffffe38fULL, }, /* 48 */ + { 0x0000e38e00008e38ULL, 0x000038e30000e38eULL, }, + { 0x000038e4ffffe38eULL, 0xffff8e39000038e4ULL, }, + { 0x00008e39000038e3ULL, 0xffffe38e00008e39ULL, }, + { 0x000016c2ffffc16cULL, 0xffff6c17000016c2ULL, }, + { 0x0000b05b00005b05ULL, 0x000005b00000b05bULL, }, + { 0x0000aaabffffaaaaULL, 0xffffaaab0000aaabULL, }, + { 0x00001c72000071c7ULL, 0xffffc71c00001c72ULL, }, + { 0xffff1c72ffff71c8ULL, 0xffffc71dffff1c72ULL, }, /* 56 */ + { 0x00001c71000071c7ULL, 0x0000c71c00001c71ULL, }, + { 0xffff71c7ffffc71dULL, 0x00001c72ffff71c7ULL, }, + { 0xffffc71c00001c72ULL, 0x000071c7ffffc71cULL, }, + { 0xffff4fa5ffffa4fbULL, 0xfffffa50ffff4fa5ULL, }, + { 0xffffe93e00003e94ULL, 0x000093e9ffffe93eULL, }, + { 0xffffe38effff8e39ULL, 0x000038e4ffffe38eULL, }, + { 0xffff555500005556ULL, 0x00005555ffff5555ULL, }, + { 0xffffa19effffd322ULL, 0x0000400900004e6fULL, }, /* 64 */ + { 0x00008807ffff615aULL, 0xffff904d0000ab7fULL, }, + { 0xffffd9c0ffff9ce2ULL, 0xffff84680000d967ULL, }, + { 0x0000721dffff4614ULL, 0xffffc28f00001bdbULL, }, + { 0x000014f2fffff853ULL, 0x00000799ffff6533ULL, }, + { 0x0000fb5bffff868bULL, 0xffff57ddffffc243ULL, }, + { 0x00004d14ffffc213ULL, 0xffff4bf8fffff02bULL, }, + { 0x0000e571ffff6b45ULL, 0xffff8a1fffff329fULL, }, + { 0xffffc58e0000648fULL, 0x00001c7afffffb1fULL, }, /* 72 */ + { 0x0000abf7fffff2c7ULL, 0xffff6cbe0000582fULL, }, + { 0xfffffdb000002e4fULL, 0xffff60d900008617ULL, }, + { 0x0000960dffffd781ULL, 0xffff9f00ffffc88bULL, }, + { 0xffff8983000008f1ULL, 0x00008293fffff936ULL, }, + { 0x00006fecffff9729ULL, 0xffffd2d700005646ULL, }, + { 0xffffc1a5ffffd2b1ULL, 0xffffc6f20000842eULL, }, + { 0x00005a02ffff7be3ULL, 0x00000519ffffc6a2ULL, }, +}; + + reset_msa_registers(); + + gettimeofday(&start, NULL); + + for (i = 0; i < PATTERN_INPUTS_SHORT_COUNT; i++) { + for (j = 0; j < PATTERN_INPUTS_SHORT_COUNT; j++) { + do_msa_HSUB_U_W(b128_pattern[i], b128_pattern[j], + b128_result[PATTERN_INPUTS_SHORT_COUNT * i + j]); + } + } + + for (i = 0; i < RANDOM_INPUTS_SHORT_COUNT; i++) { + for (j = 0; j < RANDOM_INPUTS_SHORT_COUNT; j++) { + do_msa_HSUB_U_W(b128_random[i], b128_random[j], + b128_result[((PATTERN_INPUTS_SHORT_COUNT) * + (PATTERN_INPUTS_SHORT_COUNT)) + + RANDOM_INPUTS_SHORT_COUNT * i + j]); + } + } + + gettimeofday(&end, NULL); + + elapsed_time = (end.tv_sec - start.tv_sec) * 1000.0; + elapsed_time += (end.tv_usec - start.tv_usec) / 1000.0; + + ret = check_results(instruction_name, TEST_COUNT_TOTAL, elapsed_time, + &b128_result[0][0], &b128_expect[0][0]); + + return ret; +} diff --git a/tests/tcg/mips/user/ase/msa/int-subtract/test_msa_subs_s_b.c b/tests/tcg/mips/user/ase/msa/int-subtract/test_msa_subs_s_b.c index 04e6159fc7..38a6f402fd 100644 --- a/tests/tcg/mips/user/ase/msa/int-subtract/test_msa_subs_s_b.c +++ b/tests/tcg/mips/user/ase/msa/int-subtract/test_msa_subs_s_b.c @@ -1,8 +1,10 @@ /* * Test program for MSA instruction SUBS_S.B * - * Copyright (C) 2018 Wave Computing, Inc. - * Copyright (C) 2018 Mateja Marjanovic <mateja.marjanovic@rt-rk.com> + * Copyright (C) 2019 Wave Computing, Inc. + * Copyright (C) 2019 Aleksandar Markovic <amarkovic@wavecomp.com> + * Copyright (C) 2019 RT-RK Computer Based Systems LLC + * Copyright (C) 2019 Mateja Marjanovic <mateja.marjanovic@rt-rk.com> * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -23,8 +25,8 @@ #include <stdint.h> #include "../../../../include/wrappers_msa.h" -#include "../../../../include/test_inputs.h" -#include "../../../../include/test_utils.h" +#include "../../../../include/test_inputs_128.h" +#include "../../../../include/test_utils_128.h" #define TEST_COUNT_TOTAL ( \ (PATTERN_INPUTS_SHORT_COUNT) * (PATTERN_INPUTS_SHORT_COUNT) + \ @@ -119,8 +121,12 @@ int32_t main(void) { 0x800b9880809ea980ULL, 0x7fe73e2702e94374ULL, }, { 0x7fe5307f36cf8d0eULL, 0x808a8080abc73294ULL, }, { 0x757f16ea117f1b46ULL, 0x80facdbe940390a4ULL, }, + { 0x7ff5687f7f62577fULL, 0x8019c2d9fe17bd8cULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, }; + reset_msa_registers(); + gettimeofday(&start, NULL); for (i = 0; i < PATTERN_INPUTS_SHORT_COUNT; i++) { diff --git a/tests/tcg/mips/user/ase/msa/int-subtract/test_msa_subs_s_d.c b/tests/tcg/mips/user/ase/msa/int-subtract/test_msa_subs_s_d.c index 195137f41f..989d27cb4e 100644 --- a/tests/tcg/mips/user/ase/msa/int-subtract/test_msa_subs_s_d.c +++ b/tests/tcg/mips/user/ase/msa/int-subtract/test_msa_subs_s_d.c @@ -1,8 +1,10 @@ /* * Test program for MSA instruction SUBS_S.D * - * Copyright (C) 2018 Wave Computing, Inc. - * Copyright (C) 2018 Mateja Marjanovic <mateja.marjanovic@rt-rk.com> + * Copyright (C) 2019 Wave Computing, Inc. + * Copyright (C) 2019 Aleksandar Markovic <amarkovic@wavecomp.com> + * Copyright (C) 2019 RT-RK Computer Based Systems LLC + * Copyright (C) 2019 Mateja Marjanovic <mateja.marjanovic@rt-rk.com> * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -23,8 +25,8 @@ #include <stdint.h> #include "../../../../include/wrappers_msa.h" -#include "../../../../include/test_inputs.h" -#include "../../../../include/test_utils.h" +#include "../../../../include/test_inputs_128.h" +#include "../../../../include/test_utils_128.h" #define TEST_COUNT_TOTAL ( \ (PATTERN_INPUTS_SHORT_COUNT) * (PATTERN_INPUTS_SHORT_COUNT) + \ @@ -119,8 +121,12 @@ int32_t main(void) { 0x8000000000000000ULL, 0x7fffffffffffffffULL, }, { 0x7fffffffffffffffULL, 0x8000000000000000ULL, }, { 0x749115ea109e1b46ULL, 0x8000000000000000ULL, }, + { 0x7fffffffffffffffULL, 0x8000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, }; + reset_msa_registers(); + gettimeofday(&start, NULL); for (i = 0; i < PATTERN_INPUTS_SHORT_COUNT; i++) { diff --git a/tests/tcg/mips/user/ase/msa/int-subtract/test_msa_subs_s_h.c b/tests/tcg/mips/user/ase/msa/int-subtract/test_msa_subs_s_h.c index c57238d31a..c847a6e6d2 100644 --- a/tests/tcg/mips/user/ase/msa/int-subtract/test_msa_subs_s_h.c +++ b/tests/tcg/mips/user/ase/msa/int-subtract/test_msa_subs_s_h.c @@ -1,8 +1,10 @@ /* * Test program for MSA instruction SUBS_S.H * - * Copyright (C) 2018 Wave Computing, Inc. - * Copyright (C) 2018 Mateja Marjanovic <mateja.marjanovic@rt-rk.com> + * Copyright (C) 2019 Wave Computing, Inc. + * Copyright (C) 2019 Aleksandar Markovic <amarkovic@wavecomp.com> + * Copyright (C) 2019 RT-RK Computer Based Systems LLC + * Copyright (C) 2019 Mateja Marjanovic <mateja.marjanovic@rt-rk.com> * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -23,8 +25,8 @@ #include <stdint.h> #include "../../../../include/wrappers_msa.h" -#include "../../../../include/test_inputs.h" -#include "../../../../include/test_utils.h" +#include "../../../../include/test_inputs_128.h" +#include "../../../../include/test_utils_128.h" #define TEST_COUNT_TOTAL ( \ (PATTERN_INPUTS_SHORT_COUNT) * (PATTERN_INPUTS_SHORT_COUNT) + \ @@ -119,8 +121,12 @@ int32_t main(void) { 0x8000985d8000a932ULL, 0x7fff3e2701e94274ULL, }, { 0x7fff2f8135cf8d0eULL, 0x80008000aac73294ULL, }, { 0x749115ea109e1b46ULL, 0x8000cdbe94038fa4ULL, }, + { 0x7fff67a37fff56ceULL, 0x8000c1d9fe17bd8cULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, }; + reset_msa_registers(); + gettimeofday(&start, NULL); for (i = 0; i < PATTERN_INPUTS_SHORT_COUNT; i++) { diff --git a/tests/tcg/mips/user/ase/msa/int-subtract/test_msa_subs_s_w.c b/tests/tcg/mips/user/ase/msa/int-subtract/test_msa_subs_s_w.c index 1cded65a7e..0459a4e1af 100644 --- a/tests/tcg/mips/user/ase/msa/int-subtract/test_msa_subs_s_w.c +++ b/tests/tcg/mips/user/ase/msa/int-subtract/test_msa_subs_s_w.c @@ -1,8 +1,10 @@ /* * Test program for MSA instruction SUBS_S.W * - * Copyright (C) 2018 Wave Computing, Inc. - * Copyright (C) 2018 Mateja Marjanovic <mateja.marjanovic@rt-rk.com> + * Copyright (C) 2019 Wave Computing, Inc. + * Copyright (C) 2019 Aleksandar Markovic <amarkovic@wavecomp.com> + * Copyright (C) 2019 RT-RK Computer Based Systems LLC + * Copyright (C) 2019 Mateja Marjanovic <mateja.marjanovic@rt-rk.com> * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -23,8 +25,8 @@ #include <stdint.h> #include "../../../../include/wrappers_msa.h" -#include "../../../../include/test_inputs.h" -#include "../../../../include/test_utils.h" +#include "../../../../include/test_inputs_128.h" +#include "../../../../include/test_utils_128.h" #define TEST_COUNT_TOTAL ( \ (PATTERN_INPUTS_SHORT_COUNT) * (PATTERN_INPUTS_SHORT_COUNT) + \ @@ -119,8 +121,12 @@ int32_t main(void) { 0x8000000080000000ULL, 0x7fffffff01e84274ULL, }, { 0x7fffffff35cf8d0eULL, 0x80000000aac73294ULL, }, { 0x749115ea109e1b46ULL, 0x8000000094038fa4ULL, }, + { 0x7fffffff7fffffffULL, 0x80000000fe17bd8cULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, }; + reset_msa_registers(); + gettimeofday(&start, NULL); for (i = 0; i < PATTERN_INPUTS_SHORT_COUNT; i++) { diff --git a/tests/tcg/mips/user/ase/msa/int-subtract/test_msa_subs_u_b.c b/tests/tcg/mips/user/ase/msa/int-subtract/test_msa_subs_u_b.c index cb38f033a6..3533c0c3ae 100644 --- a/tests/tcg/mips/user/ase/msa/int-subtract/test_msa_subs_u_b.c +++ b/tests/tcg/mips/user/ase/msa/int-subtract/test_msa_subs_u_b.c @@ -1,8 +1,10 @@ /* * Test program for MSA instruction SUBS_U.B * - * Copyright (C) 2018 Wave Computing, Inc. - * Copyright (C) 2018 Mateja Marjanovic <mateja.marjanovic@rt-rk.com> + * Copyright (C) 2019 Wave Computing, Inc. + * Copyright (C) 2019 Aleksandar Markovic <amarkovic@wavecomp.com> + * Copyright (C) 2019 RT-RK Computer Based Systems LLC + * Copyright (C) 2019 Mateja Marjanovic <mateja.marjanovic@rt-rk.com> * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -23,8 +25,8 @@ #include <stdint.h> #include "../../../../include/wrappers_msa.h" -#include "../../../../include/test_inputs.h" -#include "../../../../include/test_utils.h" +#include "../../../../include/test_inputs_128.h" +#include "../../../../include/test_utils_128.h" #define TEST_COUNT_TOTAL ( \ (PATTERN_INPUTS_SHORT_COUNT) * (PATTERN_INPUTS_SHORT_COUNT) + \ @@ -119,8 +121,12 @@ int32_t main(void) { 0x3c0b985d5b9e0032ULL, 0x00003e2702000000ULL, }, { 0x0000000036008d0eULL, 0x428a7d7a00003294ULL, }, { 0x0000160011001b46ULL, 0x7b0000be94039000ULL, }, + { 0x0000000000005700ULL, 0x661900000017bd8cULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, }; + reset_msa_registers(); + gettimeofday(&start, NULL); for (i = 0; i < PATTERN_INPUTS_SHORT_COUNT; i++) { diff --git a/tests/tcg/mips/user/ase/msa/int-subtract/test_msa_subs_u_d.c b/tests/tcg/mips/user/ase/msa/int-subtract/test_msa_subs_u_d.c index 2685b2fe7e..894f984f5f 100644 --- a/tests/tcg/mips/user/ase/msa/int-subtract/test_msa_subs_u_d.c +++ b/tests/tcg/mips/user/ase/msa/int-subtract/test_msa_subs_u_d.c @@ -1,8 +1,10 @@ /* * Test program for MSA instruction SUBS_U.D * - * Copyright (C) 2018 Wave Computing, Inc. - * Copyright (C) 2018 Mateja Marjanovic <mateja.marjanovic@rt-rk.com> + * Copyright (C) 2019 Wave Computing, Inc. + * Copyright (C) 2019 Aleksandar Markovic <amarkovic@wavecomp.com> + * Copyright (C) 2019 RT-RK Computer Based Systems LLC + * Copyright (C) 2019 Mateja Marjanovic <mateja.marjanovic@rt-rk.com> * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -23,8 +25,8 @@ #include <stdint.h> #include "../../../../include/wrappers_msa.h" -#include "../../../../include/test_inputs.h" -#include "../../../../include/test_utils.h" +#include "../../../../include/test_inputs_128.h" +#include "../../../../include/test_utils_128.h" #define TEST_COUNT_TOTAL ( \ (PATTERN_INPUTS_SHORT_COUNT) * (PATTERN_INPUTS_SHORT_COUNT) + \ @@ -119,8 +121,12 @@ int32_t main(void) { 0x3c0b985d5b9da932ULL, 0x0000000000000000ULL, }, { 0x0000000000000000ULL, 0x428a7d79aac73294ULL, }, { 0x0000000000000000ULL, 0x7af9cdbe94038fa4ULL, }, + { 0x0000000000000000ULL, 0x6618c1d8fe17bd8cULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, }; + reset_msa_registers(); + gettimeofday(&start, NULL); for (i = 0; i < PATTERN_INPUTS_SHORT_COUNT; i++) { diff --git a/tests/tcg/mips/user/ase/msa/int-subtract/test_msa_subs_u_h.c b/tests/tcg/mips/user/ase/msa/int-subtract/test_msa_subs_u_h.c index ca6dd38b69..29eea521fd 100644 --- a/tests/tcg/mips/user/ase/msa/int-subtract/test_msa_subs_u_h.c +++ b/tests/tcg/mips/user/ase/msa/int-subtract/test_msa_subs_u_h.c @@ -1,8 +1,10 @@ /* * Test program for MSA instruction SUBS_U.H * - * Copyright (C) 2018 Wave Computing, Inc. - * Copyright (C) 2018 Mateja Marjanovic <mateja.marjanovic@rt-rk.com> + * Copyright (C) 2019 Wave Computing, Inc. + * Copyright (C) 2019 Aleksandar Markovic <amarkovic@wavecomp.com> + * Copyright (C) 2019 RT-RK Computer Based Systems LLC + * Copyright (C) 2019 Mateja Marjanovic <mateja.marjanovic@rt-rk.com> * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -23,8 +25,8 @@ #include <stdint.h> #include "../../../../include/wrappers_msa.h" -#include "../../../../include/test_inputs.h" -#include "../../../../include/test_utils.h" +#include "../../../../include/test_inputs_128.h" +#include "../../../../include/test_utils_128.h" #define TEST_COUNT_TOTAL ( \ (PATTERN_INPUTS_SHORT_COUNT) * (PATTERN_INPUTS_SHORT_COUNT) + \ @@ -119,8 +121,12 @@ int32_t main(void) { 0x3c0b985d5b9e0000ULL, 0x00003e2701e90000ULL, }, { 0x0000000035cf8d0eULL, 0x428a7d7a00003294ULL, }, { 0x000015ea109e1b46ULL, 0x7afa000094038fa4ULL, }, + { 0x00000000000056ceULL, 0x661900000000bd8cULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, }; + reset_msa_registers(); + gettimeofday(&start, NULL); for (i = 0; i < PATTERN_INPUTS_SHORT_COUNT; i++) { diff --git a/tests/tcg/mips/user/ase/msa/int-subtract/test_msa_subs_u_w.c b/tests/tcg/mips/user/ase/msa/int-subtract/test_msa_subs_u_w.c index 42ebddb408..2bae876f11 100644 --- a/tests/tcg/mips/user/ase/msa/int-subtract/test_msa_subs_u_w.c +++ b/tests/tcg/mips/user/ase/msa/int-subtract/test_msa_subs_u_w.c @@ -1,8 +1,10 @@ /* * Test program for MSA instruction SUBS_U.W * - * Copyright (C) 2018 Wave Computing, Inc. - * Copyright (C) 2018 Mateja Marjanovic <mateja.marjanovic@rt-rk.com> + * Copyright (C) 2019 Wave Computing, Inc. + * Copyright (C) 2019 Aleksandar Markovic <amarkovic@wavecomp.com> + * Copyright (C) 2019 RT-RK Computer Based Systems LLC + * Copyright (C) 2019 Mateja Marjanovic <mateja.marjanovic@rt-rk.com> * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -23,8 +25,8 @@ #include <stdint.h> #include "../../../../include/wrappers_msa.h" -#include "../../../../include/test_inputs.h" -#include "../../../../include/test_utils.h" +#include "../../../../include/test_inputs_128.h" +#include "../../../../include/test_utils_128.h" #define TEST_COUNT_TOTAL ( \ (PATTERN_INPUTS_SHORT_COUNT) * (PATTERN_INPUTS_SHORT_COUNT) + \ @@ -119,8 +121,12 @@ int32_t main(void) { 0x3c0b985d5b9da932ULL, 0x0000000001e84274ULL, }, { 0x0000000035cf8d0eULL, 0x428a7d7a00000000ULL, }, { 0x00000000109e1b46ULL, 0x7af9cdbe94038fa4ULL, }, + { 0x0000000000000000ULL, 0x6618c1d900000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, }; + reset_msa_registers(); + gettimeofday(&start, NULL); for (i = 0; i < PATTERN_INPUTS_SHORT_COUNT; i++) { diff --git a/tests/tcg/mips/user/ase/msa/int-subtract/test_msa_subsus_u_b.c b/tests/tcg/mips/user/ase/msa/int-subtract/test_msa_subsus_u_b.c index dac20cc769..9cb798c405 100644 --- a/tests/tcg/mips/user/ase/msa/int-subtract/test_msa_subsus_u_b.c +++ b/tests/tcg/mips/user/ase/msa/int-subtract/test_msa_subsus_u_b.c @@ -1,8 +1,10 @@ /* * Test program for MSA instruction SUBSUS_U.B * - * Copyright (C) 2018 Wave Computing, Inc. - * Copyright (C) 2018 Mateja Marjanovic <mateja.marjanovic@rt-rk.com> + * Copyright (C) 2019 Wave Computing, Inc. + * Copyright (C) 2019 Aleksandar Markovic <amarkovic@wavecomp.com> + * Copyright (C) 2019 RT-RK Computer Based Systems LLC + * Copyright (C) 2019 Mateja Marjanovic <mateja.marjanovic@rt-rk.com> * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -23,8 +25,8 @@ #include <stdint.h> #include "../../../../include/wrappers_msa.h" -#include "../../../../include/test_inputs.h" -#include "../../../../include/test_utils.h" +#include "../../../../include/test_inputs_128.h" +#include "../../../../include/test_utils_128.h" #define TEST_COUNT_TOTAL ( \ (PATTERN_INPUTS_SHORT_COUNT) * (PATTERN_INPUTS_SHORT_COUNT) + \ @@ -119,8 +121,12 @@ int32_t main(void) { 0x3c0b985d5b9ea932ULL, 0x9ae7ffffff004374ULL, }, { 0xe800308136008d0eULL, 0x428a7d7aab00ff94ULL, }, { 0x75911600119eff46ULL, 0x7bfacdbe940390a4ULL, }, + { 0xc40068a3a562ffceULL, 0x66ffc2d9fe17bd8cULL, }, + { 0x000000000000ff00ULL, 0xffffffffff00ffffULL, }, }; + reset_msa_registers(); + gettimeofday(&start, NULL); for (i = 0; i < PATTERN_INPUTS_SHORT_COUNT; i++) { diff --git a/tests/tcg/mips/user/ase/msa/int-subtract/test_msa_subsus_u_d.c b/tests/tcg/mips/user/ase/msa/int-subtract/test_msa_subsus_u_d.c index 4485502c1c..4915d598fd 100644 --- a/tests/tcg/mips/user/ase/msa/int-subtract/test_msa_subsus_u_d.c +++ b/tests/tcg/mips/user/ase/msa/int-subtract/test_msa_subsus_u_d.c @@ -1,8 +1,10 @@ /* * Test program for MSA instruction SUBSUS_U.D * - * Copyright (C) 2018 Wave Computing, Inc. - * Copyright (C) 2018 Mateja Marjanovic <mateja.marjanovic@rt-rk.com> + * Copyright (C) 2019 Wave Computing, Inc. + * Copyright (C) 2019 Aleksandar Markovic <amarkovic@wavecomp.com> + * Copyright (C) 2019 RT-RK Computer Based Systems LLC + * Copyright (C) 2019 Mateja Marjanovic <mateja.marjanovic@rt-rk.com> * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -23,8 +25,8 @@ #include <stdint.h> #include "../../../../include/wrappers_msa.h" -#include "../../../../include/test_inputs.h" -#include "../../../../include/test_utils.h" +#include "../../../../include/test_inputs_128.h" +#include "../../../../include/test_utils_128.h" #define TEST_COUNT_TOTAL ( \ (PATTERN_INPUTS_SHORT_COUNT) * (PATTERN_INPUTS_SHORT_COUNT) + \ @@ -119,8 +121,12 @@ int32_t main(void) { 0x3c0b985d5b9da932ULL, 0x99e73e2701e84274ULL, }, { 0xe7e42f8135cf8d0eULL, 0x428a7d79aac73294ULL, }, { 0x749115ea109e1b46ULL, 0x7af9cdbe94038fa4ULL, }, + { 0xc3f467a2a46256ceULL, 0x6618c1d8fe17bd8cULL, }, + { 0x0000000000000000ULL, 0xffffffffffffffffULL, }, }; + reset_msa_registers(); + gettimeofday(&start, NULL); for (i = 0; i < PATTERN_INPUTS_SHORT_COUNT; i++) { diff --git a/tests/tcg/mips/user/ase/msa/int-subtract/test_msa_subsus_u_h.c b/tests/tcg/mips/user/ase/msa/int-subtract/test_msa_subsus_u_h.c index 9e99aeefc5..19d8538942 100644 --- a/tests/tcg/mips/user/ase/msa/int-subtract/test_msa_subsus_u_h.c +++ b/tests/tcg/mips/user/ase/msa/int-subtract/test_msa_subsus_u_h.c @@ -1,8 +1,10 @@ /* * Test program for MSA instruction SUBSUS_U.H * - * Copyright (C) 2018 Wave Computing, Inc. - * Copyright (C) 2018 Mateja Marjanovic <mateja.marjanovic@rt-rk.com> + * Copyright (C) 2019 Wave Computing, Inc. + * Copyright (C) 2019 Aleksandar Markovic <amarkovic@wavecomp.com> + * Copyright (C) 2019 RT-RK Computer Based Systems LLC + * Copyright (C) 2019 Mateja Marjanovic <mateja.marjanovic@rt-rk.com> * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -23,8 +25,8 @@ #include <stdint.h> #include "../../../../include/wrappers_msa.h" -#include "../../../../include/test_inputs.h" -#include "../../../../include/test_utils.h" +#include "../../../../include/test_inputs_128.h" +#include "../../../../include/test_utils_128.h" #define TEST_COUNT_TOTAL ( \ (PATTERN_INPUTS_SHORT_COUNT) * (PATTERN_INPUTS_SHORT_COUNT) + \ @@ -119,8 +121,12 @@ int32_t main(void) { 0x3c0b985d5b9ea932ULL, 0x99e7ffffffff4274ULL, }, { 0xe7e52f8135cf8d0eULL, 0x428a7d7aaac7ffffULL, }, { 0x749115ea109effffULL, 0x7afacdbe94038fa4ULL, }, + { 0xc3f567a3a462ffffULL, 0x6619c1d9fe17bd8cULL, }, + { 0x000000000000ffffULL, 0xffffffffffffffffULL, }, }; + reset_msa_registers(); + gettimeofday(&start, NULL); for (i = 0; i < PATTERN_INPUTS_SHORT_COUNT; i++) { diff --git a/tests/tcg/mips/user/ase/msa/int-subtract/test_msa_subsus_u_w.c b/tests/tcg/mips/user/ase/msa/int-subtract/test_msa_subsus_u_w.c index 53a9acac1b..278488bcea 100644 --- a/tests/tcg/mips/user/ase/msa/int-subtract/test_msa_subsus_u_w.c +++ b/tests/tcg/mips/user/ase/msa/int-subtract/test_msa_subsus_u_w.c @@ -1,8 +1,10 @@ /* * Test program for MSA instruction SUBSUS_U.W * - * Copyright (C) 2018 Wave Computing, Inc. - * Copyright (C) 2018 Mateja Marjanovic <mateja.marjanovic@rt-rk.com> + * Copyright (C) 2019 Wave Computing, Inc. + * Copyright (C) 2019 Aleksandar Markovic <amarkovic@wavecomp.com> + * Copyright (C) 2019 RT-RK Computer Based Systems LLC + * Copyright (C) 2019 Mateja Marjanovic <mateja.marjanovic@rt-rk.com> * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -23,8 +25,8 @@ #include <stdint.h> #include "../../../../include/wrappers_msa.h" -#include "../../../../include/test_inputs.h" -#include "../../../../include/test_utils.h" +#include "../../../../include/test_inputs_128.h" +#include "../../../../include/test_utils_128.h" #define TEST_COUNT_TOTAL ( \ (PATTERN_INPUTS_SHORT_COUNT) * (PATTERN_INPUTS_SHORT_COUNT) + \ @@ -119,8 +121,12 @@ int32_t main(void) { 0x3c0b985d5b9da932ULL, 0x99e73e27ffffffffULL, }, { 0xe7e42f8135cf8d0eULL, 0x428a7d7aaac73294ULL, }, { 0x749115ea109e1b46ULL, 0x7af9cdbe94038fa4ULL, }, + { 0xc3f467a3a46256ceULL, 0x6618c1d9fe17bd8cULL, }, + { 0x0000000000000000ULL, 0xffffffffffffffffULL, }, }; + reset_msa_registers(); + gettimeofday(&start, NULL); for (i = 0; i < PATTERN_INPUTS_SHORT_COUNT; i++) { diff --git a/tests/tcg/mips/user/ase/msa/int-subtract/test_msa_subsuu_s_b.c b/tests/tcg/mips/user/ase/msa/int-subtract/test_msa_subsuu_s_b.c index 86fb4f3e26..a0d7616246 100644 --- a/tests/tcg/mips/user/ase/msa/int-subtract/test_msa_subsuu_s_b.c +++ b/tests/tcg/mips/user/ase/msa/int-subtract/test_msa_subsuu_s_b.c @@ -1,8 +1,10 @@ /* * Test program for MSA instruction SUBSUU_S.B * - * Copyright (C) 2018 Wave Computing, Inc. - * Copyright (C) 2018 Mateja Marjanovic <mateja.marjanovic@rt-rk.com> + * Copyright (C) 2019 Wave Computing, Inc. + * Copyright (C) 2019 Aleksandar Markovic <amarkovic@wavecomp.com> + * Copyright (C) 2019 RT-RK Computer Based Systems LLC + * Copyright (C) 2019 Mateja Marjanovic <mateja.marjanovic@rt-rk.com> * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -23,8 +25,8 @@ #include <stdint.h> #include "../../../../include/wrappers_msa.h" -#include "../../../../include/test_inputs.h" -#include "../../../../include/test_utils.h" +#include "../../../../include/test_inputs_128.h" +#include "../../../../include/test_utils_128.h" #define TEST_COUNT_TOTAL ( \ (PATTERN_INPUTS_SHORT_COUNT) * (PATTERN_INPUTS_SHORT_COUNT) + \ @@ -119,8 +121,12 @@ int32_t main(void) { 0x3c0b7f5d5b7fa932ULL, 0x9ae73e2702e98080ULL, }, { 0xe8e5808136cf7f0eULL, 0x427f7d7aabc7327fULL, }, { 0x809116ea119e1b46ULL, 0x7bfacd7f7f037fa4ULL, }, + { 0xc4f580a3a58057ceULL, 0x6619c2d9fe177f7fULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, }; + reset_msa_registers(); + gettimeofday(&start, NULL); for (i = 0; i < PATTERN_INPUTS_SHORT_COUNT; i++) { diff --git a/tests/tcg/mips/user/ase/msa/int-subtract/test_msa_subsuu_s_d.c b/tests/tcg/mips/user/ase/msa/int-subtract/test_msa_subsuu_s_d.c index 45a1eb3094..26cf9c5578 100644 --- a/tests/tcg/mips/user/ase/msa/int-subtract/test_msa_subsuu_s_d.c +++ b/tests/tcg/mips/user/ase/msa/int-subtract/test_msa_subsuu_s_d.c @@ -1,8 +1,10 @@ /* * Test program for MSA instruction SUBSUU_S.D * - * Copyright (C) 2018 Wave Computing, Inc. - * Copyright (C) 2018 Mateja Marjanovic <mateja.marjanovic@rt-rk.com> + * Copyright (C) 2019 Wave Computing, Inc. + * Copyright (C) 2019 Aleksandar Markovic <amarkovic@wavecomp.com> + * Copyright (C) 2019 RT-RK Computer Based Systems LLC + * Copyright (C) 2019 Mateja Marjanovic <mateja.marjanovic@rt-rk.com> * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -23,8 +25,8 @@ #include <stdint.h> #include "../../../../include/wrappers_msa.h" -#include "../../../../include/test_inputs.h" -#include "../../../../include/test_utils.h" +#include "../../../../include/test_inputs_128.h" +#include "../../../../include/test_utils_128.h" #define TEST_COUNT_TOTAL ( \ (PATTERN_INPUTS_SHORT_COUNT) * (PATTERN_INPUTS_SHORT_COUNT) + \ @@ -119,8 +121,12 @@ int32_t main(void) { 0x3c0b985d5b9da932ULL, 0x99e73e2701e84274ULL, }, { 0xe7e42f8135cf8d0eULL, 0x428a7d79aac73294ULL, }, { 0x8000000000000000ULL, 0x7af9cdbe94038fa4ULL, }, + { 0xc3f467a2a46256ceULL, 0x6618c1d8fe17bd8cULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, }; + reset_msa_registers(); + gettimeofday(&start, NULL); for (i = 0; i < PATTERN_INPUTS_SHORT_COUNT; i++) { diff --git a/tests/tcg/mips/user/ase/msa/int-subtract/test_msa_subsuu_s_h.c b/tests/tcg/mips/user/ase/msa/int-subtract/test_msa_subsuu_s_h.c index 14ac7def29..cbba316c68 100644 --- a/tests/tcg/mips/user/ase/msa/int-subtract/test_msa_subsuu_s_h.c +++ b/tests/tcg/mips/user/ase/msa/int-subtract/test_msa_subsuu_s_h.c @@ -1,8 +1,10 @@ /* * Test program for MSA instruction SUBSUU_S.H * - * Copyright (C) 2018 Wave Computing, Inc. - * Copyright (C) 2018 Mateja Marjanovic <mateja.marjanovic@rt-rk.com> + * Copyright (C) 2019 Wave Computing, Inc. + * Copyright (C) 2019 Aleksandar Markovic <amarkovic@wavecomp.com> + * Copyright (C) 2019 RT-RK Computer Based Systems LLC + * Copyright (C) 2019 Mateja Marjanovic <mateja.marjanovic@rt-rk.com> * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -23,8 +25,8 @@ #include <stdint.h> #include "../../../../include/wrappers_msa.h" -#include "../../../../include/test_inputs.h" -#include "../../../../include/test_utils.h" +#include "../../../../include/test_inputs_128.h" +#include "../../../../include/test_utils_128.h" #define TEST_COUNT_TOTAL ( \ (PATTERN_INPUTS_SHORT_COUNT) * (PATTERN_INPUTS_SHORT_COUNT) + \ @@ -119,8 +121,12 @@ int32_t main(void) { 0x3c0b7fff5b9ea932ULL, 0x99e73e2701e98000ULL, }, { 0xe7e5800035cf7fffULL, 0x428a7d7aaac73294ULL, }, { 0x800015ea109e1b46ULL, 0x7afacdbe7fff7fffULL, }, + { 0xc3f58000a46256ceULL, 0x6619c1d9fe177fffULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, }; + reset_msa_registers(); + gettimeofday(&start, NULL); for (i = 0; i < PATTERN_INPUTS_SHORT_COUNT; i++) { diff --git a/tests/tcg/mips/user/ase/msa/int-subtract/test_msa_subsuu_s_w.c b/tests/tcg/mips/user/ase/msa/int-subtract/test_msa_subsuu_s_w.c index 688f469cd0..156d62cd65 100644 --- a/tests/tcg/mips/user/ase/msa/int-subtract/test_msa_subsuu_s_w.c +++ b/tests/tcg/mips/user/ase/msa/int-subtract/test_msa_subsuu_s_w.c @@ -1,8 +1,10 @@ /* * Test program for MSA instruction SUBSUU_S.W * - * Copyright (C) 2018 Wave Computing, Inc. - * Copyright (C) 2018 Mateja Marjanovic <mateja.marjanovic@rt-rk.com> + * Copyright (C) 2019 Wave Computing, Inc. + * Copyright (C) 2019 Aleksandar Markovic <amarkovic@wavecomp.com> + * Copyright (C) 2019 RT-RK Computer Based Systems LLC + * Copyright (C) 2019 Mateja Marjanovic <mateja.marjanovic@rt-rk.com> * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -23,8 +25,8 @@ #include <stdint.h> #include "../../../../include/wrappers_msa.h" -#include "../../../../include/test_inputs.h" -#include "../../../../include/test_utils.h" +#include "../../../../include/test_inputs_128.h" +#include "../../../../include/test_utils_128.h" #define TEST_COUNT_TOTAL ( \ (PATTERN_INPUTS_SHORT_COUNT) * (PATTERN_INPUTS_SHORT_COUNT) + \ @@ -119,8 +121,12 @@ int32_t main(void) { 0x3c0b985d5b9da932ULL, 0x99e73e2701e84274ULL, }, { 0xe7e42f8135cf8d0eULL, 0x428a7d7aaac73294ULL, }, { 0x80000000109e1b46ULL, 0x7af9cdbe7fffffffULL, }, + { 0xc3f467a3a46256ceULL, 0x6618c1d9fe17bd8cULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, }; + reset_msa_registers(); + gettimeofday(&start, NULL); for (i = 0; i < PATTERN_INPUTS_SHORT_COUNT; i++) { diff --git a/tests/tcg/mips/user/ase/msa/int-subtract/test_msa_subv_b.c b/tests/tcg/mips/user/ase/msa/int-subtract/test_msa_subv_b.c index d0964dcd59..dbec0466ef 100644 --- a/tests/tcg/mips/user/ase/msa/int-subtract/test_msa_subv_b.c +++ b/tests/tcg/mips/user/ase/msa/int-subtract/test_msa_subv_b.c @@ -1,8 +1,10 @@ /* * Test program for MSA instruction SUBV.B * - * Copyright (C) 2018 Wave Computing, Inc. - * Copyright (C) 2018 Mateja Marjanovic <mateja.marjanovic@rt-rk.com> + * Copyright (C) 2019 Wave Computing, Inc. + * Copyright (C) 2019 Aleksandar Markovic <amarkovic@wavecomp.com> + * Copyright (C) 2019 RT-RK Computer Based Systems LLC + * Copyright (C) 2019 Mateja Marjanovic <mateja.marjanovic@rt-rk.com> * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -23,8 +25,8 @@ #include <stdint.h> #include "../../../../include/wrappers_msa.h" -#include "../../../../include/test_inputs.h" -#include "../../../../include/test_utils.h" +#include "../../../../include/test_inputs_128.h" +#include "../../../../include/test_utils_128.h" #define TEST_COUNT_TOTAL ( \ (PATTERN_INPUTS_SHORT_COUNT) * (PATTERN_INPUTS_SHORT_COUNT) + \ @@ -119,8 +121,12 @@ int32_t main(void) { 0x3c0b985d5b9ea932ULL, 0x9ae73e2702e94374ULL, }, { 0xe8e5308136cf8d0eULL, 0x428a7d7aabc73294ULL, }, { 0x759116ea119e1b46ULL, 0x7bfacdbe940390a4ULL, }, + { 0xc4f568a3a56257ceULL, 0x6619c2d9fe17bd8cULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, }; + reset_msa_registers(); + gettimeofday(&start, NULL); for (i = 0; i < PATTERN_INPUTS_SHORT_COUNT; i++) { diff --git a/tests/tcg/mips/user/ase/msa/int-subtract/test_msa_subv_d.c b/tests/tcg/mips/user/ase/msa/int-subtract/test_msa_subv_d.c index ec26a8e0c6..8b097899ce 100644 --- a/tests/tcg/mips/user/ase/msa/int-subtract/test_msa_subv_d.c +++ b/tests/tcg/mips/user/ase/msa/int-subtract/test_msa_subv_d.c @@ -1,8 +1,10 @@ /* * Test program for MSA instruction SUBV.D * - * Copyright (C) 2018 Wave Computing, Inc. - * Copyright (C) 2018 Mateja Marjanovic <mateja.marjanovic@rt-rk.com> + * Copyright (C) 2019 Wave Computing, Inc. + * Copyright (C) 2019 Aleksandar Markovic <amarkovic@wavecomp.com> + * Copyright (C) 2019 RT-RK Computer Based Systems LLC + * Copyright (C) 2019 Mateja Marjanovic <mateja.marjanovic@rt-rk.com> * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -23,8 +25,8 @@ #include <stdint.h> #include "../../../../include/wrappers_msa.h" -#include "../../../../include/test_inputs.h" -#include "../../../../include/test_utils.h" +#include "../../../../include/test_inputs_128.h" +#include "../../../../include/test_utils_128.h" #define TEST_COUNT_TOTAL ( \ (PATTERN_INPUTS_SHORT_COUNT) * (PATTERN_INPUTS_SHORT_COUNT) + \ @@ -119,8 +121,12 @@ int32_t main(void) { 0x3c0b985d5b9da932ULL, 0x99e73e2701e84274ULL, }, { 0xe7e42f8135cf8d0eULL, 0x428a7d79aac73294ULL, }, { 0x749115ea109e1b46ULL, 0x7af9cdbe94038fa4ULL, }, + { 0xc3f467a2a46256ceULL, 0x6618c1d8fe17bd8cULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, }; + reset_msa_registers(); + gettimeofday(&start, NULL); for (i = 0; i < PATTERN_INPUTS_SHORT_COUNT; i++) { diff --git a/tests/tcg/mips/user/ase/msa/int-subtract/test_msa_subv_h.c b/tests/tcg/mips/user/ase/msa/int-subtract/test_msa_subv_h.c index 420422ecf1..69bf9ec7b8 100644 --- a/tests/tcg/mips/user/ase/msa/int-subtract/test_msa_subv_h.c +++ b/tests/tcg/mips/user/ase/msa/int-subtract/test_msa_subv_h.c @@ -1,8 +1,10 @@ /* * Test program for MSA instruction SUBV.H * - * Copyright (C) 2018 Wave Computing, Inc. - * Copyright (C) 2018 Mateja Marjanovic <mateja.marjanovic@rt-rk.com> + * Copyright (C) 2019 Wave Computing, Inc. + * Copyright (C) 2019 Aleksandar Markovic <amarkovic@wavecomp.com> + * Copyright (C) 2019 RT-RK Computer Based Systems LLC + * Copyright (C) 2019 Mateja Marjanovic <mateja.marjanovic@rt-rk.com> * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -23,8 +25,8 @@ #include <stdint.h> #include "../../../../include/wrappers_msa.h" -#include "../../../../include/test_inputs.h" -#include "../../../../include/test_utils.h" +#include "../../../../include/test_inputs_128.h" +#include "../../../../include/test_utils_128.h" #define TEST_COUNT_TOTAL ( \ (PATTERN_INPUTS_SHORT_COUNT) * (PATTERN_INPUTS_SHORT_COUNT) + \ @@ -119,8 +121,12 @@ int32_t main(void) { 0x3c0b985d5b9ea932ULL, 0x99e73e2701e94274ULL, }, { 0xe7e52f8135cf8d0eULL, 0x428a7d7aaac73294ULL, }, { 0x749115ea109e1b46ULL, 0x7afacdbe94038fa4ULL, }, + { 0xc3f567a3a46256ceULL, 0x6619c1d9fe17bd8cULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, }; + reset_msa_registers(); + gettimeofday(&start, NULL); for (i = 0; i < PATTERN_INPUTS_SHORT_COUNT; i++) { diff --git a/tests/tcg/mips/user/ase/msa/int-subtract/test_msa_subv_w.c b/tests/tcg/mips/user/ase/msa/int-subtract/test_msa_subv_w.c index 3e97005815..365dc0ed83 100644 --- a/tests/tcg/mips/user/ase/msa/int-subtract/test_msa_subv_w.c +++ b/tests/tcg/mips/user/ase/msa/int-subtract/test_msa_subv_w.c @@ -1,8 +1,10 @@ /* * Test program for MSA instruction SUBV.W * - * Copyright (C) 2018 Wave Computing, Inc. - * Copyright (C) 2018 Mateja Marjanovic <mateja.marjanovic@rt-rk.com> + * Copyright (C) 2019 Wave Computing, Inc. + * Copyright (C) 2019 Aleksandar Markovic <amarkovic@wavecomp.com> + * Copyright (C) 2019 RT-RK Computer Based Systems LLC + * Copyright (C) 2019 Mateja Marjanovic <mateja.marjanovic@rt-rk.com> * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -23,8 +25,8 @@ #include <stdint.h> #include "../../../../include/wrappers_msa.h" -#include "../../../../include/test_inputs.h" -#include "../../../../include/test_utils.h" +#include "../../../../include/test_inputs_128.h" +#include "../../../../include/test_utils_128.h" #define TEST_COUNT_TOTAL ( \ (PATTERN_INPUTS_SHORT_COUNT) * (PATTERN_INPUTS_SHORT_COUNT) + \ @@ -123,6 +125,8 @@ int32_t main(void) { 0x0000000000000000ULL, 0x0000000000000000ULL, }, }; + reset_msa_registers(); + gettimeofday(&start, NULL); for (i = 0; i < PATTERN_INPUTS_SHORT_COUNT; i++) { diff --git a/tests/tcg/mips/user/ase/msa/interleave/test_msa_ilvev_b.c b/tests/tcg/mips/user/ase/msa/interleave/test_msa_ilvev_b.c index d720dc30a5..00b78f7ed4 100644 --- a/tests/tcg/mips/user/ase/msa/interleave/test_msa_ilvev_b.c +++ b/tests/tcg/mips/user/ase/msa/interleave/test_msa_ilvev_b.c @@ -33,7 +33,7 @@ int32_t main(void) { - char *instruction_name = "*ILVEV.B"; + char *instruction_name = "ILVEV.B"; int32_t ret; uint32_t i, j; struct timeval start, end; @@ -123,6 +123,8 @@ int32_t main(void) { 0x4f4f4d4d31314e4eULL, 0xf1f1d8d84242a0a0ULL, }, }; + reset_msa_registers(); + gettimeofday(&start, NULL); for (i = 0; i < PATTERN_INPUTS_SHORT_COUNT; i++) { diff --git a/tests/tcg/mips/user/ase/msa/interleave/test_msa_ilvev_d.c b/tests/tcg/mips/user/ase/msa/interleave/test_msa_ilvev_d.c index 83239949af..a33acfa382 100644 --- a/tests/tcg/mips/user/ase/msa/interleave/test_msa_ilvev_d.c +++ b/tests/tcg/mips/user/ase/msa/interleave/test_msa_ilvev_d.c @@ -33,7 +33,7 @@ int32_t main(void) { - char *instruction_name = "*ILVEV.D"; + char *instruction_name = "ILVEV.D"; int32_t ret; uint32_t i, j; struct timeval start, end; @@ -123,6 +123,8 @@ int32_t main(void) { 0x704f164d5e31e24eULL, 0x704f164d5e31e24eULL, }, }; + reset_msa_registers(); + gettimeofday(&start, NULL); for (i = 0; i < PATTERN_INPUTS_SHORT_COUNT; i++) { diff --git a/tests/tcg/mips/user/ase/msa/interleave/test_msa_ilvev_h.c b/tests/tcg/mips/user/ase/msa/interleave/test_msa_ilvev_h.c index 3f6fc265d2..51866330dc 100644 --- a/tests/tcg/mips/user/ase/msa/interleave/test_msa_ilvev_h.c +++ b/tests/tcg/mips/user/ase/msa/interleave/test_msa_ilvev_h.c @@ -33,7 +33,7 @@ int32_t main(void) { - char *instruction_name = "*ILVEV.H"; + char *instruction_name = "ILVEV.H"; int32_t ret; uint32_t i, j; struct timeval start, end; @@ -123,6 +123,8 @@ int32_t main(void) { 0x164d164de24ee24eULL, 0x88d888d8e2a0e2a0ULL, }, }; + reset_msa_registers(); + gettimeofday(&start, NULL); for (i = 0; i < PATTERN_INPUTS_SHORT_COUNT; i++) { diff --git a/tests/tcg/mips/user/ase/msa/interleave/test_msa_ilvev_w.c b/tests/tcg/mips/user/ase/msa/interleave/test_msa_ilvev_w.c index 30d2e3802d..0e82f2199b 100644 --- a/tests/tcg/mips/user/ase/msa/interleave/test_msa_ilvev_w.c +++ b/tests/tcg/mips/user/ase/msa/interleave/test_msa_ilvev_w.c @@ -123,6 +123,8 @@ int32_t main(void) { 0x5e31e24e5e31e24eULL, 0xa942e2a0a942e2a0ULL, }, }; + reset_msa_registers(); + gettimeofday(&start, NULL); for (i = 0; i < PATTERN_INPUTS_SHORT_COUNT; i++) { diff --git a/tests/tcg/mips/user/ase/msa/interleave/test_msa_ilvl_b.c b/tests/tcg/mips/user/ase/msa/interleave/test_msa_ilvl_b.c index c771287a71..6dc06c597e 100644 --- a/tests/tcg/mips/user/ase/msa/interleave/test_msa_ilvl_b.c +++ b/tests/tcg/mips/user/ase/msa/interleave/test_msa_ilvl_b.c @@ -123,6 +123,8 @@ int32_t main(void) { 0xa9a94242e2e2a0a0ULL, 0x8d8df1f18888d8d8ULL, }, }; + reset_msa_registers(); + gettimeofday(&start, NULL); for (i = 0; i < PATTERN_INPUTS_SHORT_COUNT; i++) { diff --git a/tests/tcg/mips/user/ase/msa/interleave/test_msa_ilvl_d.c b/tests/tcg/mips/user/ase/msa/interleave/test_msa_ilvl_d.c index b7d5fcdc18..a8679723aa 100644 --- a/tests/tcg/mips/user/ase/msa/interleave/test_msa_ilvl_d.c +++ b/tests/tcg/mips/user/ase/msa/interleave/test_msa_ilvl_d.c @@ -123,6 +123,8 @@ int32_t main(void) { 0x8df188d8a942e2a0ULL, 0x8df188d8a942e2a0ULL, }, }; + reset_msa_registers(); + gettimeofday(&start, NULL); for (i = 0; i < PATTERN_INPUTS_SHORT_COUNT; i++) { diff --git a/tests/tcg/mips/user/ase/msa/interleave/test_msa_ilvl_h.c b/tests/tcg/mips/user/ase/msa/interleave/test_msa_ilvl_h.c index af72876236..22f6ba600a 100644 --- a/tests/tcg/mips/user/ase/msa/interleave/test_msa_ilvl_h.c +++ b/tests/tcg/mips/user/ase/msa/interleave/test_msa_ilvl_h.c @@ -123,6 +123,8 @@ int32_t main(void) { 0xa942a942e2a0e2a0ULL, 0x8df18df188d888d8ULL, }, }; + reset_msa_registers(); + gettimeofday(&start, NULL); for (i = 0; i < PATTERN_INPUTS_SHORT_COUNT; i++) { diff --git a/tests/tcg/mips/user/ase/msa/interleave/test_msa_ilvl_w.c b/tests/tcg/mips/user/ase/msa/interleave/test_msa_ilvl_w.c index e06c9d94ca..f07689e0c8 100644 --- a/tests/tcg/mips/user/ase/msa/interleave/test_msa_ilvl_w.c +++ b/tests/tcg/mips/user/ase/msa/interleave/test_msa_ilvl_w.c @@ -123,6 +123,8 @@ int32_t main(void) { 0xa942e2a0a942e2a0ULL, 0x8df188d88df188d8ULL, }, }; + reset_msa_registers(); + gettimeofday(&start, NULL); for (i = 0; i < PATTERN_INPUTS_SHORT_COUNT; i++) { diff --git a/tests/tcg/mips/user/ase/msa/interleave/test_msa_ilvod_b.c b/tests/tcg/mips/user/ase/msa/interleave/test_msa_ilvod_b.c index 8e7f1c4706..2316f388ec 100644 --- a/tests/tcg/mips/user/ase/msa/interleave/test_msa_ilvod_b.c +++ b/tests/tcg/mips/user/ase/msa/interleave/test_msa_ilvod_b.c @@ -123,6 +123,8 @@ int32_t main(void) { 0x707016165e5ee2e2ULL, 0x8d8d8888a9a9e2e2ULL, }, }; + reset_msa_registers(); + gettimeofday(&start, NULL); for (i = 0; i < PATTERN_INPUTS_SHORT_COUNT; i++) { diff --git a/tests/tcg/mips/user/ase/msa/interleave/test_msa_ilvod_d.c b/tests/tcg/mips/user/ase/msa/interleave/test_msa_ilvod_d.c index acbd94a68d..2feb2eb2ed 100644 --- a/tests/tcg/mips/user/ase/msa/interleave/test_msa_ilvod_d.c +++ b/tests/tcg/mips/user/ase/msa/interleave/test_msa_ilvod_d.c @@ -123,6 +123,8 @@ int32_t main(void) { 0x8df188d8a942e2a0ULL, 0x8df188d8a942e2a0ULL, }, }; + reset_msa_registers(); + gettimeofday(&start, NULL); for (i = 0; i < PATTERN_INPUTS_SHORT_COUNT; i++) { diff --git a/tests/tcg/mips/user/ase/msa/interleave/test_msa_ilvod_h.c b/tests/tcg/mips/user/ase/msa/interleave/test_msa_ilvod_h.c index 8a82def407..93abfadfdd 100644 --- a/tests/tcg/mips/user/ase/msa/interleave/test_msa_ilvod_h.c +++ b/tests/tcg/mips/user/ase/msa/interleave/test_msa_ilvod_h.c @@ -123,6 +123,8 @@ int32_t main(void) { 0x704f704f5e315e31ULL, 0x8df18df1a942a942ULL, }, }; + reset_msa_registers(); + gettimeofday(&start, NULL); for (i = 0; i < PATTERN_INPUTS_SHORT_COUNT; i++) { diff --git a/tests/tcg/mips/user/ase/msa/interleave/test_msa_ilvod_w.c b/tests/tcg/mips/user/ase/msa/interleave/test_msa_ilvod_w.c index e19170c364..9b2b0d82ac 100644 --- a/tests/tcg/mips/user/ase/msa/interleave/test_msa_ilvod_w.c +++ b/tests/tcg/mips/user/ase/msa/interleave/test_msa_ilvod_w.c @@ -123,6 +123,8 @@ int32_t main(void) { 0x704f164d704f164dULL, 0x8df188d88df188d8ULL, }, }; + reset_msa_registers(); + gettimeofday(&start, NULL); for (i = 0; i < PATTERN_INPUTS_SHORT_COUNT; i++) { diff --git a/tests/tcg/mips/user/ase/msa/interleave/test_msa_ilvr_b.c b/tests/tcg/mips/user/ase/msa/interleave/test_msa_ilvr_b.c index 1e519e6e9e..105a710d34 100644 --- a/tests/tcg/mips/user/ase/msa/interleave/test_msa_ilvr_b.c +++ b/tests/tcg/mips/user/ase/msa/interleave/test_msa_ilvr_b.c @@ -123,6 +123,8 @@ int32_t main(void) { 0x5e5e3131e2e24e4eULL, 0x70704f4f16164d4dULL, }, }; + reset_msa_registers(); + gettimeofday(&start, NULL); for (i = 0; i < PATTERN_INPUTS_SHORT_COUNT; i++) { diff --git a/tests/tcg/mips/user/ase/msa/interleave/test_msa_ilvr_d.c b/tests/tcg/mips/user/ase/msa/interleave/test_msa_ilvr_d.c index be760430c7..22579c48c5 100644 --- a/tests/tcg/mips/user/ase/msa/interleave/test_msa_ilvr_d.c +++ b/tests/tcg/mips/user/ase/msa/interleave/test_msa_ilvr_d.c @@ -123,6 +123,8 @@ int32_t main(void) { 0x704f164d5e31e24eULL, 0x704f164d5e31e24eULL, }, }; + reset_msa_registers(); + gettimeofday(&start, NULL); for (i = 0; i < PATTERN_INPUTS_SHORT_COUNT; i++) { diff --git a/tests/tcg/mips/user/ase/msa/interleave/test_msa_ilvr_h.c b/tests/tcg/mips/user/ase/msa/interleave/test_msa_ilvr_h.c index cbd4685eca..ca416c02e6 100644 --- a/tests/tcg/mips/user/ase/msa/interleave/test_msa_ilvr_h.c +++ b/tests/tcg/mips/user/ase/msa/interleave/test_msa_ilvr_h.c @@ -123,6 +123,8 @@ int32_t main(void) { 0x5e315e31e24ee24eULL, 0x704f704f164d164dULL, }, }; + reset_msa_registers(); + gettimeofday(&start, NULL); for (i = 0; i < PATTERN_INPUTS_SHORT_COUNT; i++) { diff --git a/tests/tcg/mips/user/ase/msa/interleave/test_msa_ilvr_w.c b/tests/tcg/mips/user/ase/msa/interleave/test_msa_ilvr_w.c index 5f4cfd0377..6652c7fbf5 100644 --- a/tests/tcg/mips/user/ase/msa/interleave/test_msa_ilvr_w.c +++ b/tests/tcg/mips/user/ase/msa/interleave/test_msa_ilvr_w.c @@ -123,6 +123,8 @@ int32_t main(void) { 0x5e31e24e5e31e24eULL, 0x704f164d704f164dULL, }, }; + reset_msa_registers(); + gettimeofday(&start, NULL); for (i = 0; i < PATTERN_INPUTS_SHORT_COUNT; i++) { diff --git a/tests/tcg/mips/user/ase/msa/logic/test_msa_and_v.c b/tests/tcg/mips/user/ase/msa/logic/test_msa_and_v.c index 534c4201a8..1f864be5f2 100644 --- a/tests/tcg/mips/user/ase/msa/logic/test_msa_and_v.c +++ b/tests/tcg/mips/user/ase/msa/logic/test_msa_and_v.c @@ -123,6 +123,8 @@ int32_t main(void) { 0x704f164d5e31e24eULL, 0x8df188d8a942e2a0ULL, }, }; + reset_msa_registers(); + gettimeofday(&start, NULL); for (i = 0; i < PATTERN_INPUTS_SHORT_COUNT; i++) { diff --git a/tests/tcg/mips/user/ase/msa/logic/test_msa_nor_v.c b/tests/tcg/mips/user/ase/msa/logic/test_msa_nor_v.c index f781a8bb9d..0b0f5ddb5e 100644 --- a/tests/tcg/mips/user/ase/msa/logic/test_msa_nor_v.c +++ b/tests/tcg/mips/user/ase/msa/logic/test_msa_nor_v.c @@ -123,6 +123,8 @@ int32_t main(void) { 0x8fb0e9b2a1ce1db1ULL, 0x720e772756bd1d5fULL, }, }; + reset_msa_registers(); + gettimeofday(&start, NULL); for (i = 0; i < PATTERN_INPUTS_SHORT_COUNT; i++) { diff --git a/tests/tcg/mips/user/ase/msa/logic/test_msa_or_v.c b/tests/tcg/mips/user/ase/msa/logic/test_msa_or_v.c index 924f216e41..90f535aa29 100644 --- a/tests/tcg/mips/user/ase/msa/logic/test_msa_or_v.c +++ b/tests/tcg/mips/user/ase/msa/logic/test_msa_or_v.c @@ -123,6 +123,8 @@ int32_t main(void) { 0x704f164d5e31e24eULL, 0x8df188d8a942e2a0ULL, }, }; + reset_msa_registers(); + gettimeofday(&start, NULL); for (i = 0; i < PATTERN_INPUTS_SHORT_COUNT; i++) { diff --git a/tests/tcg/mips/user/ase/msa/logic/test_msa_xor_v.c b/tests/tcg/mips/user/ase/msa/logic/test_msa_xor_v.c index f0442e6577..398443d83a 100644 --- a/tests/tcg/mips/user/ase/msa/logic/test_msa_xor_v.c +++ b/tests/tcg/mips/user/ase/msa/logic/test_msa_xor_v.c @@ -123,6 +123,8 @@ int32_t main(void) { 0x0000000000000000ULL, 0x0000000000000000ULL, }, }; + reset_msa_registers(); + gettimeofday(&start, NULL); for (i = 0; i < PATTERN_INPUTS_SHORT_COUNT; i++) { diff --git a/tests/tcg/mips/user/ase/msa/pack/test_msa_pckev_b.c b/tests/tcg/mips/user/ase/msa/pack/test_msa_pckev_b.c index 409773d7f2..fdab88d5c9 100644 --- a/tests/tcg/mips/user/ase/msa/pack/test_msa_pckev_b.c +++ b/tests/tcg/mips/user/ase/msa/pack/test_msa_pckev_b.c @@ -123,6 +123,8 @@ int32_t main(void) { 0xf1d842a04f4d314eULL, 0xf1d842a04f4d314eULL, }, }; + reset_msa_registers(); + gettimeofday(&start, NULL); for (i = 0; i < PATTERN_INPUTS_SHORT_COUNT; i++) { diff --git a/tests/tcg/mips/user/ase/msa/pack/test_msa_pckev_d.c b/tests/tcg/mips/user/ase/msa/pack/test_msa_pckev_d.c index 8e89716416..e7083858cd 100644 --- a/tests/tcg/mips/user/ase/msa/pack/test_msa_pckev_d.c +++ b/tests/tcg/mips/user/ase/msa/pack/test_msa_pckev_d.c @@ -123,6 +123,8 @@ int32_t main(void) { 0x704f164d5e31e24eULL, 0x704f164d5e31e24eULL, }, }; + reset_msa_registers(); + gettimeofday(&start, NULL); for (i = 0; i < PATTERN_INPUTS_SHORT_COUNT; i++) { diff --git a/tests/tcg/mips/user/ase/msa/pack/test_msa_pckev_h.c b/tests/tcg/mips/user/ase/msa/pack/test_msa_pckev_h.c index b389587dfe..bfd401f379 100644 --- a/tests/tcg/mips/user/ase/msa/pack/test_msa_pckev_h.c +++ b/tests/tcg/mips/user/ase/msa/pack/test_msa_pckev_h.c @@ -123,6 +123,8 @@ int32_t main(void) { 0x88d8e2a0164de24eULL, 0x88d8e2a0164de24eULL, }, }; + reset_msa_registers(); + gettimeofday(&start, NULL); for (i = 0; i < PATTERN_INPUTS_SHORT_COUNT; i++) { diff --git a/tests/tcg/mips/user/ase/msa/pack/test_msa_pckev_w.c b/tests/tcg/mips/user/ase/msa/pack/test_msa_pckev_w.c index d393ad5066..e58372d750 100644 --- a/tests/tcg/mips/user/ase/msa/pack/test_msa_pckev_w.c +++ b/tests/tcg/mips/user/ase/msa/pack/test_msa_pckev_w.c @@ -123,6 +123,8 @@ int32_t main(void) { 0xa942e2a05e31e24eULL, 0xa942e2a05e31e24eULL, }, }; + reset_msa_registers(); + gettimeofday(&start, NULL); for (i = 0; i < PATTERN_INPUTS_SHORT_COUNT; i++) { diff --git a/tests/tcg/mips/user/ase/msa/pack/test_msa_pckod_b.c b/tests/tcg/mips/user/ase/msa/pack/test_msa_pckod_b.c index ab363a0cdc..4cefecd0ec 100644 --- a/tests/tcg/mips/user/ase/msa/pack/test_msa_pckod_b.c +++ b/tests/tcg/mips/user/ase/msa/pack/test_msa_pckod_b.c @@ -123,6 +123,8 @@ int32_t main(void) { 0x8d88a9e270165ee2ULL, 0x8d88a9e270165ee2ULL, }, }; + reset_msa_registers(); + gettimeofday(&start, NULL); for (i = 0; i < PATTERN_INPUTS_SHORT_COUNT; i++) { diff --git a/tests/tcg/mips/user/ase/msa/pack/test_msa_pckod_d.c b/tests/tcg/mips/user/ase/msa/pack/test_msa_pckod_d.c index 09a61408bc..a7ea137148 100644 --- a/tests/tcg/mips/user/ase/msa/pack/test_msa_pckod_d.c +++ b/tests/tcg/mips/user/ase/msa/pack/test_msa_pckod_d.c @@ -123,6 +123,8 @@ int32_t main(void) { 0x8df188d8a942e2a0ULL, 0x8df188d8a942e2a0ULL, }, }; + reset_msa_registers(); + gettimeofday(&start, NULL); for (i = 0; i < PATTERN_INPUTS_SHORT_COUNT; i++) { diff --git a/tests/tcg/mips/user/ase/msa/pack/test_msa_pckod_h.c b/tests/tcg/mips/user/ase/msa/pack/test_msa_pckod_h.c index d7a8c5b5af..bc7edcc595 100644 --- a/tests/tcg/mips/user/ase/msa/pack/test_msa_pckod_h.c +++ b/tests/tcg/mips/user/ase/msa/pack/test_msa_pckod_h.c @@ -123,6 +123,8 @@ int32_t main(void) { 0x8df1a942704f5e31ULL, 0x8df1a942704f5e31ULL, }, }; + reset_msa_registers(); + gettimeofday(&start, NULL); for (i = 0; i < PATTERN_INPUTS_SHORT_COUNT; i++) { diff --git a/tests/tcg/mips/user/ase/msa/pack/test_msa_pckod_w.c b/tests/tcg/mips/user/ase/msa/pack/test_msa_pckod_w.c index 4b732d0359..ca8c4fb0b6 100644 --- a/tests/tcg/mips/user/ase/msa/pack/test_msa_pckod_w.c +++ b/tests/tcg/mips/user/ase/msa/pack/test_msa_pckod_w.c @@ -123,6 +123,8 @@ int32_t main(void) { 0x8df188d8704f164dULL, 0x8df188d8704f164dULL, }, }; + reset_msa_registers(); + gettimeofday(&start, NULL); for (i = 0; i < PATTERN_INPUTS_SHORT_COUNT; i++) { diff --git a/tests/tcg/mips/user/ase/msa/pack/test_msa_vshf_b.c b/tests/tcg/mips/user/ase/msa/pack/test_msa_vshf_b.c index d9ccf575fa..c088643b8c 100644 --- a/tests/tcg/mips/user/ase/msa/pack/test_msa_vshf_b.c +++ b/tests/tcg/mips/user/ase/msa/pack/test_msa_vshf_b.c @@ -41,7 +41,7 @@ int32_t main(void) uint64_t b128_result[TEST_COUNT_TOTAL][2]; uint64_t b128_expect[TEST_COUNT_TOTAL][2] = { - { 0x0000000000000000ULL, 0x0000000000000000ULL, }, /* 0 */ + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 0 */ { 0x0000000000000000ULL, 0x0000000000000000ULL, }, { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, }, { 0x0000000000000000ULL, 0x0000000000000000ULL, }, @@ -123,6 +123,8 @@ int32_t main(void) { 0x0000000000000000ULL, 0x0000000000000000ULL, }, }; + reset_msa_registers(); + gettimeofday(&start, NULL); for (i = 0; i < PATTERN_INPUTS_SHORT_COUNT; i++) { diff --git a/tests/tcg/mips/user/ase/msa/pack/test_msa_vshf_d.c b/tests/tcg/mips/user/ase/msa/pack/test_msa_vshf_d.c index 6c555fbb23..06f3604bef 100644 --- a/tests/tcg/mips/user/ase/msa/pack/test_msa_vshf_d.c +++ b/tests/tcg/mips/user/ase/msa/pack/test_msa_vshf_d.c @@ -41,7 +41,7 @@ int32_t main(void) uint64_t b128_result[TEST_COUNT_TOTAL][2]; uint64_t b128_expect[TEST_COUNT_TOTAL][2] = { - { 0x0000000000000000ULL, 0x0000000000000000ULL, }, /* 0 */ + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 0 */ { 0x0000000000000000ULL, 0x0000000000000000ULL, }, { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, }, { 0x0000000000000000ULL, 0x0000000000000000ULL, }, @@ -123,6 +123,8 @@ int32_t main(void) { 0x0000000000000000ULL, 0x0000000000000000ULL, }, }; + reset_msa_registers(); + gettimeofday(&start, NULL); for (i = 0; i < PATTERN_INPUTS_SHORT_COUNT; i++) { diff --git a/tests/tcg/mips/user/ase/msa/pack/test_msa_vshf_h.c b/tests/tcg/mips/user/ase/msa/pack/test_msa_vshf_h.c index 9dfcb51fe5..f28d949d02 100644 --- a/tests/tcg/mips/user/ase/msa/pack/test_msa_vshf_h.c +++ b/tests/tcg/mips/user/ase/msa/pack/test_msa_vshf_h.c @@ -41,7 +41,7 @@ int32_t main(void) uint64_t b128_result[TEST_COUNT_TOTAL][2]; uint64_t b128_expect[TEST_COUNT_TOTAL][2] = { - { 0x0000000000000000ULL, 0x0000000000000000ULL, }, /* 0 */ + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 0 */ { 0x0000000000000000ULL, 0x0000000000000000ULL, }, { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, }, { 0x0000000000000000ULL, 0x0000000000000000ULL, }, @@ -123,6 +123,8 @@ int32_t main(void) { 0x0000000000000000ULL, 0x0000000000000000ULL, }, }; + reset_msa_registers(); + gettimeofday(&start, NULL); for (i = 0; i < PATTERN_INPUTS_SHORT_COUNT; i++) { diff --git a/tests/tcg/mips/user/ase/msa/pack/test_msa_vshf_w.c b/tests/tcg/mips/user/ase/msa/pack/test_msa_vshf_w.c index 97074c0924..78e26d4ca0 100644 --- a/tests/tcg/mips/user/ase/msa/pack/test_msa_vshf_w.c +++ b/tests/tcg/mips/user/ase/msa/pack/test_msa_vshf_w.c @@ -41,7 +41,7 @@ int32_t main(void) uint64_t b128_result[TEST_COUNT_TOTAL][2]; uint64_t b128_expect[TEST_COUNT_TOTAL][2] = { - { 0x0000000000000000ULL, 0x0000000000000000ULL, }, /* 0 */ + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 0 */ { 0x0000000000000000ULL, 0x0000000000000000ULL, }, { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, }, { 0x0000000000000000ULL, 0x0000000000000000ULL, }, @@ -123,6 +123,8 @@ int32_t main(void) { 0x0000000000000000ULL, 0x0000000000000000ULL, }, }; + reset_msa_registers(); + gettimeofday(&start, NULL); for (i = 0; i < PATTERN_INPUTS_SHORT_COUNT; i++) { diff --git a/tests/tcg/mips/user/ase/msa/shift/test_msa_sll_b.c b/tests/tcg/mips/user/ase/msa/shift/test_msa_sll_b.c new file mode 100644 index 0000000000..6b1aa962d4 --- /dev/null +++ b/tests/tcg/mips/user/ase/msa/shift/test_msa_sll_b.c @@ -0,0 +1,155 @@ +/* + * Test program for MSA instruction SLL.B + * + * Copyright (C) 2019 Wave Computing, Inc. + * Copyright (C) 2019 Aleksandar Markovic <amarkovic@wavecomp.com> + * + * This program 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, see <https://www.gnu.org/licenses/>. + * + */ + +#include <sys/time.h> +#include <stdint.h> + +#include "../../../../include/wrappers_msa.h" +#include "../../../../include/test_inputs_128.h" +#include "../../../../include/test_utils_128.h" + +#define TEST_COUNT_TOTAL ( \ + (PATTERN_INPUTS_SHORT_COUNT) * (PATTERN_INPUTS_SHORT_COUNT) + \ + (RANDOM_INPUTS_SHORT_COUNT) * (RANDOM_INPUTS_SHORT_COUNT)) + + +int32_t main(void) +{ + char *instruction_name = "SLL.B"; + int32_t ret; + uint32_t i, j; + struct timeval start, end; + double elapsed_time; + + uint64_t b128_result[TEST_COUNT_TOTAL][2]; + uint64_t b128_expect[TEST_COUNT_TOTAL][2] = { + { 0x8080808080808080ULL, 0x8080808080808080ULL, }, /* 0 */ + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, + { 0xfcfcfcfcfcfcfcfcULL, 0xfcfcfcfcfcfcfcfcULL, }, + { 0xe0e0e0e0e0e0e0e0ULL, 0xe0e0e0e0e0e0e0e0ULL, }, + { 0xf0f0f0f0f0f0f0f0ULL, 0xf0f0f0f0f0f0f0f0ULL, }, + { 0xf8f8f8f8f8f8f8f8ULL, 0xf8f8f8f8f8f8f8f8ULL, }, + { 0xf8c0fff8c0fff8c0ULL, 0xfff8c0fff8c0fff8ULL, }, + { 0xf0fe80f0fe80f0feULL, 0x80f0fe80f0fe80f0ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, /* 8 */ + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, /* 16 */ + { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, }, + { 0xa8a8a8a8a8a8a8a8ULL, 0xa8a8a8a8a8a8a8a8ULL, }, + { 0x4040404040404040ULL, 0x4040404040404040ULL, }, + { 0xa0a0a0a0a0a0a0a0ULL, 0xa0a0a0a0a0a0a0a0ULL, }, + { 0x5050505050505050ULL, 0x5050505050505050ULL, }, + { 0x5080aa5080aa5080ULL, 0xaa5080aa5080aa50ULL, }, + { 0xa05400a05400a054ULL, 0x00a05400a05400a0ULL, }, + { 0x8080808080808080ULL, 0x8080808080808080ULL, }, /* 24 */ + { 0x5555555555555555ULL, 0x5555555555555555ULL, }, + { 0x5454545454545454ULL, 0x5454545454545454ULL, }, + { 0xa0a0a0a0a0a0a0a0ULL, 0xa0a0a0a0a0a0a0a0ULL, }, + { 0x5050505050505050ULL, 0x5050505050505050ULL, }, + { 0xa8a8a8a8a8a8a8a8ULL, 0xa8a8a8a8a8a8a8a8ULL, }, + { 0xa84055a84055a840ULL, 0x55a84055a84055a8ULL, }, + { 0x50aa8050aa8050aaULL, 0x8050aa8050aa8050ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, /* 32 */ + { 0xccccccccccccccccULL, 0xccccccccccccccccULL, }, + { 0x3030303030303030ULL, 0x3030303030303030ULL, }, + { 0x8080808080808080ULL, 0x8080808080808080ULL, }, + { 0xc0c0c0c0c0c0c0c0ULL, 0xc0c0c0c0c0c0c0c0ULL, }, + { 0x6060606060606060ULL, 0x6060606060606060ULL, }, + { 0x6000cc6000cc6000ULL, 0xcc6000cc6000cc60ULL, }, + { 0xc09800c09800c098ULL, 0x00c09800c09800c0ULL, }, + { 0x8080808080808080ULL, 0x8080808080808080ULL, }, /* 40 */ + { 0x3333333333333333ULL, 0x3333333333333333ULL, }, + { 0xccccccccccccccccULL, 0xccccccccccccccccULL, }, + { 0x6060606060606060ULL, 0x6060606060606060ULL, }, + { 0x3030303030303030ULL, 0x3030303030303030ULL, }, + { 0x9898989898989898ULL, 0x9898989898989898ULL, }, + { 0x98c03398c03398c0ULL, 0x3398c03398c03398ULL, }, + { 0x3066803066803066ULL, 0x8030668030668030ULL, }, + { 0x8000008000008000ULL, 0x0080000080000080ULL, }, /* 48 */ + { 0xe38e38e38e38e38eULL, 0x38e38e38e38e38e3ULL, }, + { 0x8c38e08c38e08c38ULL, 0xe08c38e08c38e08cULL, }, + { 0x60c00060c00060c0ULL, 0x0060c00060c00060ULL, }, + { 0x30e08030e08030e0ULL, 0x8030e08030e08030ULL, }, + { 0x1870c01870c01870ULL, 0xc01870c01870c018ULL, }, + { 0x1880381880381880ULL, 0x3818803818803818ULL, }, + { 0x301c00301c00301cULL, 0x00301c00301c0030ULL, }, + { 0x0080800080800080ULL, 0x8000808000808000ULL, }, /* 56 */ + { 0x1c71c71c71c71c71ULL, 0xc71c71c71c71c71cULL, }, + { 0x70c41c70c41c70c4ULL, 0x1c70c41c70c41c70ULL, }, + { 0x8020e08020e08020ULL, 0xe08020e08020e080ULL, }, + { 0xc01070c01070c010ULL, 0x70c01070c01070c0ULL, }, + { 0xe08838e08838e088ULL, 0x38e08838e08838e0ULL, }, + { 0xe040c7e040c7e040ULL, 0xc7e040c7e040c7e0ULL, }, + { 0xc0e280c0e280c0e2ULL, 0x80c0e280c0e280c0ULL, }, + { 0x88a880c02888a040ULL, 0x5880588080d8b0c0ULL, }, /* 64 */ + { 0x4080e66000108040ULL, 0x2c805878c080c0c0ULL, }, + { 0x80a880305000a840ULL, 0x8067c000f0d800c0ULL, }, + { 0x8800808000c45400ULL, 0x60ce0b5efcecc00cULL, }, + { 0xfbf800304d4ce008ULL, 0x9080d88040f852c0ULL, }, + { 0xd8800018a0988008ULL, 0x4880d868a08048c0ULL, }, + { 0xb0f8008c9a803808ULL, 0x00f7c000a8f840c0ULL, }, + { 0xfb00006040261c00ULL, 0x40eebb1a2afc48fcULL, }, + { 0xac6880a0b93c6080ULL, 0x380030c0c0582540ULL, }, /* 72 */ + { 0x6080ae5020788080ULL, 0x9c0030fc60809440ULL, }, + { 0xc06880a872805880ULL, 0x80d880805858a040ULL, }, + { 0xac008040409e2c00ULL, 0xe0b0c6ff56ac9414ULL, }, + { 0x703c80d05ec4404eULL, 0x688040004010e200ULL, }, + { 0x80c01668c088004eULL, 0x3480406020008800ULL, }, + { 0x003c8034bc80104eULL, 0x80f1000048104000ULL, }, + { 0x708080a080628880ULL, 0xa0e288d8520888a0ULL, }, + }; + + reset_msa_registers(); + + gettimeofday(&start, NULL); + + for (i = 0; i < PATTERN_INPUTS_SHORT_COUNT; i++) { + for (j = 0; j < PATTERN_INPUTS_SHORT_COUNT; j++) { + do_msa_SLL_B(b128_pattern[i], b128_pattern[j], + b128_result[PATTERN_INPUTS_SHORT_COUNT * i + j]); + } + } + + for (i = 0; i < RANDOM_INPUTS_SHORT_COUNT; i++) { + for (j = 0; j < RANDOM_INPUTS_SHORT_COUNT; j++) { + do_msa_SLL_B(b128_random[i], b128_random[j], + b128_result[((PATTERN_INPUTS_SHORT_COUNT) * + (PATTERN_INPUTS_SHORT_COUNT)) + + RANDOM_INPUTS_SHORT_COUNT * i + j]); + } + } + + gettimeofday(&end, NULL); + + elapsed_time = (end.tv_sec - start.tv_sec) * 1000.0; + elapsed_time += (end.tv_usec - start.tv_usec) / 1000.0; + + ret = check_results(instruction_name, TEST_COUNT_TOTAL, elapsed_time, + &b128_result[0][0], &b128_expect[0][0]); + + return ret; +} diff --git a/tests/tcg/mips/user/ase/msa/shift/test_msa_sll_d.c b/tests/tcg/mips/user/ase/msa/shift/test_msa_sll_d.c new file mode 100644 index 0000000000..deb3b11740 --- /dev/null +++ b/tests/tcg/mips/user/ase/msa/shift/test_msa_sll_d.c @@ -0,0 +1,155 @@ +/* + * Test program for MSA instruction SLL.D + * + * Copyright (C) 2019 Wave Computing, Inc. + * Copyright (C) 2019 Aleksandar Markovic <amarkovic@wavecomp.com> + * + * This program 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, see <https://www.gnu.org/licenses/>. + * + */ + +#include <sys/time.h> +#include <stdint.h> + +#include "../../../../include/wrappers_msa.h" +#include "../../../../include/test_inputs_128.h" +#include "../../../../include/test_utils_128.h" + +#define TEST_COUNT_TOTAL ( \ + (PATTERN_INPUTS_SHORT_COUNT) * (PATTERN_INPUTS_SHORT_COUNT) + \ + (RANDOM_INPUTS_SHORT_COUNT) * (RANDOM_INPUTS_SHORT_COUNT)) + + +int32_t main(void) +{ + char *instruction_name = "SLL.D"; + int32_t ret; + uint32_t i, j; + struct timeval start, end; + double elapsed_time; + + uint64_t b128_result[TEST_COUNT_TOTAL][2]; + uint64_t b128_expect[TEST_COUNT_TOTAL][2] = { + { 0x8000000000000000ULL, 0x8000000000000000ULL, }, /* 0 */ + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, + { 0xfffffc0000000000ULL, 0xfffffc0000000000ULL, }, + { 0xffffffffffe00000ULL, 0xffffffffffe00000ULL, }, + { 0xfffffffffffff000ULL, 0xfffffffffffff000ULL, }, + { 0xfff8000000000000ULL, 0xfff8000000000000ULL, }, + { 0xffffffffffffc000ULL, 0xfffffff800000000ULL, }, + { 0xfffe000000000000ULL, 0xfffffffff0000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, /* 8 */ + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, /* 16 */ + { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, }, + { 0xaaaaa80000000000ULL, 0xaaaaa80000000000ULL, }, + { 0x5555555555400000ULL, 0x5555555555400000ULL, }, + { 0xaaaaaaaaaaaaa000ULL, 0xaaaaaaaaaaaaa000ULL, }, + { 0x5550000000000000ULL, 0x5550000000000000ULL, }, + { 0xaaaaaaaaaaaa8000ULL, 0x5555555000000000ULL, }, + { 0x5554000000000000ULL, 0xaaaaaaaaa0000000ULL, }, + { 0x8000000000000000ULL, 0x8000000000000000ULL, }, /* 24 */ + { 0x5555555555555555ULL, 0x5555555555555555ULL, }, + { 0x5555540000000000ULL, 0x5555540000000000ULL, }, + { 0xaaaaaaaaaaa00000ULL, 0xaaaaaaaaaaa00000ULL, }, + { 0x5555555555555000ULL, 0x5555555555555000ULL, }, + { 0xaaa8000000000000ULL, 0xaaa8000000000000ULL, }, + { 0x5555555555554000ULL, 0xaaaaaaa800000000ULL, }, + { 0xaaaa000000000000ULL, 0x5555555550000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, /* 32 */ + { 0xccccccccccccccccULL, 0xccccccccccccccccULL, }, + { 0x3333300000000000ULL, 0x3333300000000000ULL, }, + { 0x9999999999800000ULL, 0x9999999999800000ULL, }, + { 0xccccccccccccc000ULL, 0xccccccccccccc000ULL, }, + { 0x6660000000000000ULL, 0x6660000000000000ULL, }, + { 0x3333333333330000ULL, 0x6666666000000000ULL, }, + { 0x9998000000000000ULL, 0xccccccccc0000000ULL, }, + { 0x8000000000000000ULL, 0x8000000000000000ULL, }, /* 40 */ + { 0x3333333333333333ULL, 0x3333333333333333ULL, }, + { 0xcccccc0000000000ULL, 0xcccccc0000000000ULL, }, + { 0x6666666666600000ULL, 0x6666666666600000ULL, }, + { 0x3333333333333000ULL, 0x3333333333333000ULL, }, + { 0x9998000000000000ULL, 0x9998000000000000ULL, }, + { 0xccccccccccccc000ULL, 0x9999999800000000ULL, }, + { 0x6666000000000000ULL, 0x3333333330000000ULL, }, + { 0x0000000000000000ULL, 0x8000000000000000ULL, }, /* 48 */ + { 0xe38e38e38e38e38eULL, 0x38e38e38e38e38e3ULL, }, + { 0xe38e380000000000ULL, 0x38e38c0000000000ULL, }, + { 0x1c71c71c71c00000ULL, 0xc71c71c71c600000ULL, }, + { 0xe38e38e38e38e000ULL, 0x38e38e38e38e3000ULL, }, + { 0x1c70000000000000ULL, 0xc718000000000000ULL, }, + { 0x8e38e38e38e38000ULL, 0x1c71c71800000000ULL, }, + { 0xc71c000000000000ULL, 0x8e38e38e30000000ULL, }, + { 0x8000000000000000ULL, 0x0000000000000000ULL, }, /* 56 */ + { 0x1c71c71c71c71c71ULL, 0xc71c71c71c71c71cULL, }, + { 0x1c71c40000000000ULL, 0xc71c700000000000ULL, }, + { 0xe38e38e38e200000ULL, 0x38e38e38e3800000ULL, }, + { 0x1c71c71c71c71000ULL, 0xc71c71c71c71c000ULL, }, + { 0xe388000000000000ULL, 0x38e0000000000000ULL, }, + { 0x71c71c71c71c4000ULL, 0xe38e38e000000000ULL, }, + { 0x38e2000000000000ULL, 0x71c71c71c0000000ULL, }, + { 0x886ae6cc28625540ULL, 0x70b5efe7bb00c000ULL, }, /* 64 */ + { 0x6ae6cc2862554000ULL, 0xc000000000000000ULL, }, + { 0x886ae6cc28625540ULL, 0xb5efe7bb00c00000ULL, }, + { 0xb9b30a1895500000ULL, 0xfe7bb00c00000000ULL, }, + { 0xfbbe00634d93c708ULL, 0x7bb1a153f52fc000ULL, }, + { 0xbe00634d93c70800ULL, 0xc000000000000000ULL, }, + { 0xfbbe00634d93c708ULL, 0xb1a153f52fc00000ULL, }, + { 0x8018d364f1c20000ULL, 0x153f52fc00000000ULL, }, + { 0xac5aaeaab9cf8b80ULL, 0x8c6ffab2b2514000ULL, }, /* 72 */ + { 0x5aaeaab9cf8b8000ULL, 0x4000000000000000ULL, }, + { 0xac5aaeaab9cf8b80ULL, 0x6ffab2b251400000ULL, }, + { 0xabaaae73e2e00000ULL, 0xab2b251400000000ULL, }, + { 0x704f164d5e31e24eULL, 0x188d8a942e2a0000ULL, }, + { 0x4f164d5e31e24e00ULL, 0x0000000000000000ULL, }, + { 0x704f164d5e31e24eULL, 0x8d8a942e2a000000ULL, }, + { 0xc593578c78938000ULL, 0xa942e2a000000000ULL, }, + }; + + reset_msa_registers(); + + gettimeofday(&start, NULL); + + for (i = 0; i < PATTERN_INPUTS_SHORT_COUNT; i++) { + for (j = 0; j < PATTERN_INPUTS_SHORT_COUNT; j++) { + do_msa_SLL_D(b128_pattern[i], b128_pattern[j], + b128_result[PATTERN_INPUTS_SHORT_COUNT * i + j]); + } + } + + for (i = 0; i < RANDOM_INPUTS_SHORT_COUNT; i++) { + for (j = 0; j < RANDOM_INPUTS_SHORT_COUNT; j++) { + do_msa_SLL_D(b128_random[i], b128_random[j], + b128_result[((PATTERN_INPUTS_SHORT_COUNT) * + (PATTERN_INPUTS_SHORT_COUNT)) + + RANDOM_INPUTS_SHORT_COUNT * i + j]); + } + } + + gettimeofday(&end, NULL); + + elapsed_time = (end.tv_sec - start.tv_sec) * 1000.0; + elapsed_time += (end.tv_usec - start.tv_usec) / 1000.0; + + ret = check_results(instruction_name, TEST_COUNT_TOTAL, elapsed_time, + &b128_result[0][0], &b128_expect[0][0]); + + return ret; +} diff --git a/tests/tcg/mips/user/ase/msa/shift/test_msa_sll_h.c b/tests/tcg/mips/user/ase/msa/shift/test_msa_sll_h.c new file mode 100644 index 0000000000..edb3b11be5 --- /dev/null +++ b/tests/tcg/mips/user/ase/msa/shift/test_msa_sll_h.c @@ -0,0 +1,155 @@ +/* + * Test program for MSA instruction SLL.H + * + * Copyright (C) 2019 Wave Computing, Inc. + * Copyright (C) 2019 Aleksandar Markovic <amarkovic@wavecomp.com> + * + * This program 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, see <https://www.gnu.org/licenses/>. + * + */ + +#include <sys/time.h> +#include <stdint.h> + +#include "../../../../include/wrappers_msa.h" +#include "../../../../include/test_inputs_128.h" +#include "../../../../include/test_utils_128.h" + +#define TEST_COUNT_TOTAL ( \ + (PATTERN_INPUTS_SHORT_COUNT) * (PATTERN_INPUTS_SHORT_COUNT) + \ + (RANDOM_INPUTS_SHORT_COUNT) * (RANDOM_INPUTS_SHORT_COUNT)) + + +int32_t main(void) +{ + char *instruction_name = "SLL.H"; + int32_t ret; + uint32_t i, j; + struct timeval start, end; + double elapsed_time; + + uint64_t b128_result[TEST_COUNT_TOTAL][2]; + uint64_t b128_expect[TEST_COUNT_TOTAL][2] = { + { 0x8000800080008000ULL, 0x8000800080008000ULL, }, /* 0 */ + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, + { 0xfc00fc00fc00fc00ULL, 0xfc00fc00fc00fc00ULL, }, + { 0xffe0ffe0ffe0ffe0ULL, 0xffe0ffe0ffe0ffe0ULL, }, + { 0xf000f000f000f000ULL, 0xf000f000f000f000ULL, }, + { 0xfff8fff8fff8fff8ULL, 0xfff8fff8fff8fff8ULL, }, + { 0xc000fff8ff00c000ULL, 0xfff8ff00c000fff8ULL, }, + { 0xfffef000ff80fffeULL, 0xf000ff80fffef000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, /* 8 */ + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, /* 16 */ + { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, }, + { 0xa800a800a800a800ULL, 0xa800a800a800a800ULL, }, + { 0x5540554055405540ULL, 0x5540554055405540ULL, }, + { 0xa000a000a000a000ULL, 0xa000a000a000a000ULL, }, + { 0x5550555055505550ULL, 0x5550555055505550ULL, }, + { 0x80005550aa008000ULL, 0x5550aa0080005550ULL, }, + { 0x5554a00055005554ULL, 0xa00055005554a000ULL, }, + { 0x8000800080008000ULL, 0x8000800080008000ULL, }, /* 24 */ + { 0x5555555555555555ULL, 0x5555555555555555ULL, }, + { 0x5400540054005400ULL, 0x5400540054005400ULL, }, + { 0xaaa0aaa0aaa0aaa0ULL, 0xaaa0aaa0aaa0aaa0ULL, }, + { 0x5000500050005000ULL, 0x5000500050005000ULL, }, + { 0xaaa8aaa8aaa8aaa8ULL, 0xaaa8aaa8aaa8aaa8ULL, }, + { 0x4000aaa855004000ULL, 0xaaa855004000aaa8ULL, }, + { 0xaaaa5000aa80aaaaULL, 0x5000aa80aaaa5000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, /* 32 */ + { 0xccccccccccccccccULL, 0xccccccccccccccccULL, }, + { 0x3000300030003000ULL, 0x3000300030003000ULL, }, + { 0x9980998099809980ULL, 0x9980998099809980ULL, }, + { 0xc000c000c000c000ULL, 0xc000c000c000c000ULL, }, + { 0x6660666066606660ULL, 0x6660666066606660ULL, }, + { 0x00006660cc000000ULL, 0x6660cc0000006660ULL, }, + { 0x9998c00066009998ULL, 0xc00066009998c000ULL, }, + { 0x8000800080008000ULL, 0x8000800080008000ULL, }, /* 40 */ + { 0x3333333333333333ULL, 0x3333333333333333ULL, }, + { 0xcc00cc00cc00cc00ULL, 0xcc00cc00cc00cc00ULL, }, + { 0x6660666066606660ULL, 0x6660666066606660ULL, }, + { 0x3000300030003000ULL, 0x3000300030003000ULL, }, + { 0x9998999899989998ULL, 0x9998999899989998ULL, }, + { 0xc00099983300c000ULL, 0x99983300c0009998ULL, }, + { 0x6666300099806666ULL, 0x3000998066663000ULL, }, + { 0x0000800000000000ULL, 0x8000000000008000ULL, }, /* 48 */ + { 0xe38e38e38e38e38eULL, 0x38e38e38e38e38e3ULL, }, + { 0x38008c00e0003800ULL, 0x8c00e00038008c00ULL, }, + { 0x71c01c60c70071c0ULL, 0x1c60c70071c01c60ULL, }, + { 0xe00030008000e000ULL, 0x30008000e0003000ULL, }, + { 0x1c70c71871c01c70ULL, 0xc71871c01c70c718ULL, }, + { 0x8000c71838008000ULL, 0xc71838008000c718ULL, }, + { 0xc71c30001c00c71cULL, 0x30001c00c71c3000ULL, }, + { 0x8000000080008000ULL, 0x0000800080000000ULL, }, /* 56 */ + { 0x1c71c71c71c71c71ULL, 0xc71c71c71c71c71cULL, }, + { 0xc40070001c00c400ULL, 0x70001c00c4007000ULL, }, + { 0x8e20e38038e08e20ULL, 0xe38038e08e20e380ULL, }, + { 0x1000c00070001000ULL, 0xc00070001000c000ULL, }, + { 0xe38838e08e38e388ULL, 0x38e08e38e38838e0ULL, }, + { 0x400038e0c7004000ULL, 0x38e0c700400038e0ULL, }, + { 0x38e2c000e38038e2ULL, 0xc000e38038e2c000ULL, }, + { 0xa800c000a1885540ULL, 0xb3808000d800c000ULL, }, /* 64 */ + { 0x8000366043104000ULL, 0xb38078008000c000ULL, }, + { 0xa800300000005540ULL, 0x67000000d80000c0ULL, }, + { 0x0000800050c40000ULL, 0x96ce5e00f9ecb00cULL, }, + { 0xf8003000364cc708ULL, 0x7b808000f800c000ULL, }, + { 0x800003186c980800ULL, 0x7b8068008000c000ULL, }, + { 0xf8008c008000c708ULL, 0xf7000000f8002fc0ULL, }, + { 0x000060009b260000ULL, 0x25ee1a0054fc52fcULL, }, + { 0x6800a000e73c8b80ULL, 0xec00c00058004000ULL, }, /* 72 */ + { 0x80007550ce788000ULL, 0xec00fc0080004000ULL, }, + { 0x6800a80080008b80ULL, 0xd800800058005140ULL, }, + { 0x00004000739e0000ULL, 0x4fb0ff00acac2514ULL, }, + { 0x3c00d00078c4e24eULL, 0xf880000010000000ULL, }, + { 0xc000b268f1884e00ULL, 0xf880600000000000ULL, }, + { 0x3c0034008000e24eULL, 0xf100000010002a00ULL, }, + { 0x8000a000bc628000ULL, 0x1be2d800a508e2a0ULL, }, + }; + + reset_msa_registers(); + + gettimeofday(&start, NULL); + + for (i = 0; i < PATTERN_INPUTS_SHORT_COUNT; i++) { + for (j = 0; j < PATTERN_INPUTS_SHORT_COUNT; j++) { + do_msa_SLL_H(b128_pattern[i], b128_pattern[j], + b128_result[PATTERN_INPUTS_SHORT_COUNT * i + j]); + } + } + + for (i = 0; i < RANDOM_INPUTS_SHORT_COUNT; i++) { + for (j = 0; j < RANDOM_INPUTS_SHORT_COUNT; j++) { + do_msa_SLL_H(b128_random[i], b128_random[j], + b128_result[((PATTERN_INPUTS_SHORT_COUNT) * + (PATTERN_INPUTS_SHORT_COUNT)) + + RANDOM_INPUTS_SHORT_COUNT * i + j]); + } + } + + gettimeofday(&end, NULL); + + elapsed_time = (end.tv_sec - start.tv_sec) * 1000.0; + elapsed_time += (end.tv_usec - start.tv_usec) / 1000.0; + + ret = check_results(instruction_name, TEST_COUNT_TOTAL, elapsed_time, + &b128_result[0][0], &b128_expect[0][0]); + + return ret; +} diff --git a/tests/tcg/mips/user/ase/msa/shift/test_msa_sll_w.c b/tests/tcg/mips/user/ase/msa/shift/test_msa_sll_w.c new file mode 100644 index 0000000000..4cafaab334 --- /dev/null +++ b/tests/tcg/mips/user/ase/msa/shift/test_msa_sll_w.c @@ -0,0 +1,155 @@ +/* + * Test program for MSA instruction SLL.W + * + * Copyright (C) 2019 Wave Computing, Inc. + * Copyright (C) 2019 Aleksandar Markovic <amarkovic@wavecomp.com> + * + * This program 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, see <https://www.gnu.org/licenses/>. + * + */ + +#include <sys/time.h> +#include <stdint.h> + +#include "../../../../include/wrappers_msa.h" +#include "../../../../include/test_inputs_128.h" +#include "../../../../include/test_utils_128.h" + +#define TEST_COUNT_TOTAL ( \ + (PATTERN_INPUTS_SHORT_COUNT) * (PATTERN_INPUTS_SHORT_COUNT) + \ + (RANDOM_INPUTS_SHORT_COUNT) * (RANDOM_INPUTS_SHORT_COUNT)) + + +int32_t main(void) +{ + char *instruction_name = "SLL.W"; + int32_t ret; + uint32_t i, j; + struct timeval start, end; + double elapsed_time; + + uint64_t b128_result[TEST_COUNT_TOTAL][2]; + uint64_t b128_expect[TEST_COUNT_TOTAL][2] = { + { 0x8000000080000000ULL, 0x8000000080000000ULL, }, /* 0 */ + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, + { 0xfffffc00fffffc00ULL, 0xfffffc00fffffc00ULL, }, + { 0xffe00000ffe00000ULL, 0xffe00000ffe00000ULL, }, + { 0xfffff000fffff000ULL, 0xfffff000fffff000ULL, }, + { 0xfff80000fff80000ULL, 0xfff80000fff80000ULL, }, + { 0xfffffff8ffffc000ULL, 0xff000000fffffff8ULL, }, + { 0xf0000000fffe0000ULL, 0xffffff80f0000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, /* 8 */ + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, /* 16 */ + { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, }, + { 0xaaaaa800aaaaa800ULL, 0xaaaaa800aaaaa800ULL, }, + { 0x5540000055400000ULL, 0x5540000055400000ULL, }, + { 0xaaaaa000aaaaa000ULL, 0xaaaaa000aaaaa000ULL, }, + { 0x5550000055500000ULL, 0x5550000055500000ULL, }, + { 0x55555550aaaa8000ULL, 0xaa00000055555550ULL, }, + { 0xa000000055540000ULL, 0x55555500a0000000ULL, }, + { 0x8000000080000000ULL, 0x8000000080000000ULL, }, /* 24 */ + { 0x5555555555555555ULL, 0x5555555555555555ULL, }, + { 0x5555540055555400ULL, 0x5555540055555400ULL, }, + { 0xaaa00000aaa00000ULL, 0xaaa00000aaa00000ULL, }, + { 0x5555500055555000ULL, 0x5555500055555000ULL, }, + { 0xaaa80000aaa80000ULL, 0xaaa80000aaa80000ULL, }, + { 0xaaaaaaa855554000ULL, 0x55000000aaaaaaa8ULL, }, + { 0x50000000aaaa0000ULL, 0xaaaaaa8050000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, /* 32 */ + { 0xccccccccccccccccULL, 0xccccccccccccccccULL, }, + { 0x3333300033333000ULL, 0x3333300033333000ULL, }, + { 0x9980000099800000ULL, 0x9980000099800000ULL, }, + { 0xccccc000ccccc000ULL, 0xccccc000ccccc000ULL, }, + { 0x6660000066600000ULL, 0x6660000066600000ULL, }, + { 0x6666666033330000ULL, 0xcc00000066666660ULL, }, + { 0xc000000099980000ULL, 0x66666600c0000000ULL, }, + { 0x8000000080000000ULL, 0x8000000080000000ULL, }, /* 40 */ + { 0x3333333333333333ULL, 0x3333333333333333ULL, }, + { 0xcccccc00cccccc00ULL, 0xcccccc00cccccc00ULL, }, + { 0x6660000066600000ULL, 0x6660000066600000ULL, }, + { 0x3333300033333000ULL, 0x3333300033333000ULL, }, + { 0x9998000099980000ULL, 0x9998000099980000ULL, }, + { 0x99999998ccccc000ULL, 0x3300000099999998ULL, }, + { 0x3000000066660000ULL, 0x9999998030000000ULL, }, + { 0x8000000000000000ULL, 0x0000000080000000ULL, }, /* 48 */ + { 0xe38e38e38e38e38eULL, 0x38e38e38e38e38e3ULL, }, + { 0x38e38c00e38e3800ULL, 0x8e38e00038e38c00ULL, }, + { 0x1c60000071c00000ULL, 0xc70000001c600000ULL, }, + { 0xe38e30008e38e000ULL, 0x38e38000e38e3000ULL, }, + { 0xc71800001c700000ULL, 0x71c00000c7180000ULL, }, + { 0x1c71c71838e38000ULL, 0x380000001c71c718ULL, }, + { 0x30000000c71c0000ULL, 0x71c71c0030000000ULL, }, + { 0x0000000080000000ULL, 0x8000000000000000ULL, }, /* 56 */ + { 0x1c71c71c71c71c71ULL, 0xc71c71c71c71c71cULL, }, + { 0xc71c70001c71c400ULL, 0x71c71c00c71c7000ULL, }, + { 0xe38000008e200000ULL, 0x38e00000e3800000ULL, }, + { 0x1c71c00071c71000ULL, 0xc71c70001c71c000ULL, }, + { 0x38e00000e3880000ULL, 0x8e38000038e00000ULL, }, + { 0xe38e38e0c71c4000ULL, 0xc7000000e38e38e0ULL, }, + { 0xc000000038e20000ULL, 0x8e38e380c0000000ULL, }, + { 0xae6cc00028625540ULL, 0x80000000bb00c000ULL, }, /* 64 */ + { 0x4357366062554000ULL, 0x78000000c0000000ULL, }, + { 0xab9b300028625540ULL, 0x0000000000c00000ULL, }, + { 0x5cd9800095500000ULL, 0x5e000000fe7bb00cULL, }, + { 0xe00630004d93c708ULL, 0x80000000f52fc000ULL, }, + { 0xddf0031893c70800ULL, 0x68000000c0000000ULL, }, + { 0xf8018c004d93c708ULL, 0x000000002fc00000ULL, }, + { 0xc00c6000f1c20000ULL, 0x1a000000153f52fcULL, }, + { 0xaaeaa000b9cf8b80ULL, 0xc0000000b2514000ULL, }, /* 72 */ + { 0x62d57550cf8b8000ULL, 0xfc00000040000000ULL, }, + { 0x6abaa800b9cf8b80ULL, 0x8000000051400000ULL, }, + { 0x55d54000e2e00000ULL, 0xff000000ab2b2514ULL, }, + { 0xf164d0005e31e24eULL, 0x000000002e2a0000ULL, }, + { 0x8278b26831e24e00ULL, 0x6000000000000000ULL, }, + { 0x3c5934005e31e24eULL, 0x000000002a000000ULL, }, + { 0xe2c9a00078938000ULL, 0xd8000000a942e2a0ULL, }, + }; + + reset_msa_registers(); + + gettimeofday(&start, NULL); + + for (i = 0; i < PATTERN_INPUTS_SHORT_COUNT; i++) { + for (j = 0; j < PATTERN_INPUTS_SHORT_COUNT; j++) { + do_msa_SLL_W(b128_pattern[i], b128_pattern[j], + b128_result[PATTERN_INPUTS_SHORT_COUNT * i + j]); + } + } + + for (i = 0; i < RANDOM_INPUTS_SHORT_COUNT; i++) { + for (j = 0; j < RANDOM_INPUTS_SHORT_COUNT; j++) { + do_msa_SLL_W(b128_random[i], b128_random[j], + b128_result[((PATTERN_INPUTS_SHORT_COUNT) * + (PATTERN_INPUTS_SHORT_COUNT)) + + RANDOM_INPUTS_SHORT_COUNT * i + j]); + } + } + + gettimeofday(&end, NULL); + + elapsed_time = (end.tv_sec - start.tv_sec) * 1000.0; + elapsed_time += (end.tv_usec - start.tv_usec) / 1000.0; + + ret = check_results(instruction_name, TEST_COUNT_TOTAL, elapsed_time, + &b128_result[0][0], &b128_expect[0][0]); + + return ret; +} diff --git a/tests/tcg/mips/user/ase/msa/shift/test_msa_sra_b.c b/tests/tcg/mips/user/ase/msa/shift/test_msa_sra_b.c new file mode 100644 index 0000000000..b1432c2806 --- /dev/null +++ b/tests/tcg/mips/user/ase/msa/shift/test_msa_sra_b.c @@ -0,0 +1,155 @@ +/* + * Test program for MSA instruction SRA.B + * + * Copyright (C) 2019 Wave Computing, Inc. + * Copyright (C) 2019 Aleksandar Markovic <amarkovic@wavecomp.com> + * + * This program 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, see <https://www.gnu.org/licenses/>. + * + */ + +#include <sys/time.h> +#include <stdint.h> + +#include "../../../../include/wrappers_msa.h" +#include "../../../../include/test_inputs_128.h" +#include "../../../../include/test_utils_128.h" + +#define TEST_COUNT_TOTAL ( \ + (PATTERN_INPUTS_SHORT_COUNT) * (PATTERN_INPUTS_SHORT_COUNT) + \ + (RANDOM_INPUTS_SHORT_COUNT) * (RANDOM_INPUTS_SHORT_COUNT)) + + +int32_t main(void) +{ + char *instruction_name = "SRA.B"; + int32_t ret; + uint32_t i, j; + struct timeval start, end; + double elapsed_time; + + uint64_t b128_result[TEST_COUNT_TOTAL][2]; + uint64_t b128_expect[TEST_COUNT_TOTAL][2] = { + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 0 */ + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, /* 8 */ + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 16 */ + { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, }, + { 0xeaeaeaeaeaeaeaeaULL, 0xeaeaeaeaeaeaeaeaULL, }, + { 0xfdfdfdfdfdfdfdfdULL, 0xfdfdfdfdfdfdfdfdULL, }, + { 0xfafafafafafafafaULL, 0xfafafafafafafafaULL, }, + { 0xf5f5f5f5f5f5f5f5ULL, 0xf5f5f5f5f5f5f5f5ULL, }, + { 0xf5feaaf5feaaf5feULL, 0xaaf5feaaf5feaaf5ULL, }, + { 0xfad5fffad5fffad5ULL, 0xfffad5fffad5fffaULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, /* 24 */ + { 0x5555555555555555ULL, 0x5555555555555555ULL, }, + { 0x1515151515151515ULL, 0x1515151515151515ULL, }, + { 0x0202020202020202ULL, 0x0202020202020202ULL, }, + { 0x0505050505050505ULL, 0x0505050505050505ULL, }, + { 0x0a0a0a0a0a0a0a0aULL, 0x0a0a0a0a0a0a0a0aULL, }, + { 0x0a01550a01550a01ULL, 0x550a01550a01550aULL, }, + { 0x052a00052a00052aULL, 0x00052a00052a0005ULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 32 */ + { 0xccccccccccccccccULL, 0xccccccccccccccccULL, }, + { 0xf3f3f3f3f3f3f3f3ULL, 0xf3f3f3f3f3f3f3f3ULL, }, + { 0xfefefefefefefefeULL, 0xfefefefefefefefeULL, }, + { 0xfcfcfcfcfcfcfcfcULL, 0xfcfcfcfcfcfcfcfcULL, }, + { 0xf9f9f9f9f9f9f9f9ULL, 0xf9f9f9f9f9f9f9f9ULL, }, + { 0xf9ffccf9ffccf9ffULL, 0xccf9ffccf9ffccf9ULL, }, + { 0xfce6fffce6fffce6ULL, 0xfffce6fffce6fffcULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, /* 40 */ + { 0x3333333333333333ULL, 0x3333333333333333ULL, }, + { 0x0c0c0c0c0c0c0c0cULL, 0x0c0c0c0c0c0c0c0cULL, }, + { 0x0101010101010101ULL, 0x0101010101010101ULL, }, + { 0x0303030303030303ULL, 0x0303030303030303ULL, }, + { 0x0606060606060606ULL, 0x0606060606060606ULL, }, + { 0x0600330600330600ULL, 0x3306003306003306ULL, }, + { 0x0319000319000319ULL, 0x0003190003190003ULL, }, + { 0xffff00ffff00ffffULL, 0x00ffff00ffff00ffULL, }, /* 48 */ + { 0xe38e38e38e38e38eULL, 0x38e38e38e38e38e3ULL, }, + { 0xf8e30ef8e30ef8e3ULL, 0x0ef8e30ef8e30ef8ULL, }, + { 0xfffc01fffc01fffcULL, 0x01fffc01fffc01ffULL, }, + { 0xfef803fef803fef8ULL, 0x03fef803fef803feULL, }, + { 0xfcf107fcf107fcf1ULL, 0x07fcf107fcf107fcULL, }, + { 0xfcfe38fcfe38fcfeULL, 0x38fcfe38fcfe38fcULL, }, + { 0xfec700fec700fec7ULL, 0x00fec700fec700feULL, }, + { 0x0000ff0000ff0000ULL, 0xff0000ff0000ff00ULL, }, /* 56 */ + { 0x1c71c71c71c71c71ULL, 0xc71c71c71c71c71cULL, }, + { 0x071cf1071cf1071cULL, 0xf1071cf1071cf107ULL, }, + { 0x0003fe0003fe0003ULL, 0xfe0003fe0003fe00ULL, }, + { 0x0107fc0107fc0107ULL, 0xfc0107fc0107fc01ULL, }, + { 0x030ef8030ef8030eULL, 0xf8030ef8030ef803ULL, }, + { 0x0301c70301c70301ULL, 0xc70301c70301c703ULL, }, + { 0x0138ff0138ff0138ULL, 0xff0138ff0138ff01ULL, }, + { 0x881afffc28180240ULL, 0x09000101ff0fb000ULL, }, /* 64 */ + { 0xf101e6f9010c0040ULL, 0x12000117ff00ec00ULL, }, + { 0xf81afff314000a40ULL, 0x00670000ff0ffd00ULL, }, + { 0x8800fffe00311501ULL, 0x02330b5eff1eec0cULL, }, + { 0xfbef00064de4fe08ULL, 0x02fff700000752ffULL, }, + { 0xfffe000c02f2ff08ULL, 0x04fff706000014ffULL, }, + { 0xffef001826fff808ULL, 0x00f7fe00020702ffULL, }, + { 0xfbff000301c9f100ULL, 0x00fbbb1a0a0f14fcULL, }, + { 0xac16fefab9f3fc80ULL, 0x04fff8fffe052501ULL, }, /* 72 */ + { 0xf501aef5fdf9ff80ULL, 0x09fff8fffd000901ULL, }, + { 0xfa16feeadcfff180ULL, 0x00d8fffff5050101ULL, }, + { 0xac00fefdfee7e2feULL, 0x01ecc6ffd50a0914ULL, }, + { 0x701300045e0cff4eULL, 0xf1fff1fffe08e2faULL, }, + { 0x0e0116090206ff4eULL, 0xe3fff1f6fd00f8faULL, }, + { 0x071300132f00fc4eULL, 0xfff1fefff508fffaULL, }, + { 0x700000020118f801ULL, 0xfcf888d8d410f8a0ULL, }, + }; + + reset_msa_registers(); + + gettimeofday(&start, NULL); + + for (i = 0; i < PATTERN_INPUTS_SHORT_COUNT; i++) { + for (j = 0; j < PATTERN_INPUTS_SHORT_COUNT; j++) { + do_msa_SRA_B(b128_pattern[i], b128_pattern[j], + b128_result[PATTERN_INPUTS_SHORT_COUNT * i + j]); + } + } + + for (i = 0; i < RANDOM_INPUTS_SHORT_COUNT; i++) { + for (j = 0; j < RANDOM_INPUTS_SHORT_COUNT; j++) { + do_msa_SRA_B(b128_random[i], b128_random[j], + b128_result[((PATTERN_INPUTS_SHORT_COUNT) * + (PATTERN_INPUTS_SHORT_COUNT)) + + RANDOM_INPUTS_SHORT_COUNT * i + j]); + } + } + + gettimeofday(&end, NULL); + + elapsed_time = (end.tv_sec - start.tv_sec) * 1000.0; + elapsed_time += (end.tv_usec - start.tv_usec) / 1000.0; + + ret = check_results(instruction_name, TEST_COUNT_TOTAL, elapsed_time, + &b128_result[0][0], &b128_expect[0][0]); + + return ret; +} diff --git a/tests/tcg/mips/user/ase/msa/shift/test_msa_sra_d.c b/tests/tcg/mips/user/ase/msa/shift/test_msa_sra_d.c new file mode 100644 index 0000000000..cb6c12dde1 --- /dev/null +++ b/tests/tcg/mips/user/ase/msa/shift/test_msa_sra_d.c @@ -0,0 +1,155 @@ +/* + * Test program for MSA instruction SRA.D + * + * Copyright (C) 2019 Wave Computing, Inc. + * Copyright (C) 2019 Aleksandar Markovic <amarkovic@wavecomp.com> + * + * This program 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, see <https://www.gnu.org/licenses/>. + * + */ + +#include <sys/time.h> +#include <stdint.h> + +#include "../../../../include/wrappers_msa.h" +#include "../../../../include/test_inputs_128.h" +#include "../../../../include/test_utils_128.h" + +#define TEST_COUNT_TOTAL ( \ + (PATTERN_INPUTS_SHORT_COUNT) * (PATTERN_INPUTS_SHORT_COUNT) + \ + (RANDOM_INPUTS_SHORT_COUNT) * (RANDOM_INPUTS_SHORT_COUNT)) + + +int32_t main(void) +{ + char *instruction_name = "SRA.D"; + int32_t ret; + uint32_t i, j; + struct timeval start, end; + double elapsed_time; + + uint64_t b128_result[TEST_COUNT_TOTAL][2]; + uint64_t b128_expect[TEST_COUNT_TOTAL][2] = { + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 0 */ + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, /* 8 */ + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 16 */ + { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, }, + { 0xffffffffffeaaaaaULL, 0xffffffffffeaaaaaULL, }, + { 0xfffffd5555555555ULL, 0xfffffd5555555555ULL, }, + { 0xfffaaaaaaaaaaaaaULL, 0xfffaaaaaaaaaaaaaULL, }, + { 0xfffffffffffff555ULL, 0xfffffffffffff555ULL, }, + { 0xfffeaaaaaaaaaaaaULL, 0xfffffffff5555555ULL, }, + { 0xffffffffffffd555ULL, 0xfffffffaaaaaaaaaULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, /* 24 */ + { 0x5555555555555555ULL, 0x5555555555555555ULL, }, + { 0x0000000000155555ULL, 0x0000000000155555ULL, }, + { 0x000002aaaaaaaaaaULL, 0x000002aaaaaaaaaaULL, }, + { 0x0005555555555555ULL, 0x0005555555555555ULL, }, + { 0x0000000000000aaaULL, 0x0000000000000aaaULL, }, + { 0x0001555555555555ULL, 0x000000000aaaaaaaULL, }, + { 0x0000000000002aaaULL, 0x0000000555555555ULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 32 */ + { 0xccccccccccccccccULL, 0xccccccccccccccccULL, }, + { 0xfffffffffff33333ULL, 0xfffffffffff33333ULL, }, + { 0xfffffe6666666666ULL, 0xfffffe6666666666ULL, }, + { 0xfffcccccccccccccULL, 0xfffcccccccccccccULL, }, + { 0xfffffffffffff999ULL, 0xfffffffffffff999ULL, }, + { 0xffff333333333333ULL, 0xfffffffff9999999ULL, }, + { 0xffffffffffffe666ULL, 0xfffffffcccccccccULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, /* 40 */ + { 0x3333333333333333ULL, 0x3333333333333333ULL, }, + { 0x00000000000cccccULL, 0x00000000000cccccULL, }, + { 0x0000019999999999ULL, 0x0000019999999999ULL, }, + { 0x0003333333333333ULL, 0x0003333333333333ULL, }, + { 0x0000000000000666ULL, 0x0000000000000666ULL, }, + { 0x0000ccccccccccccULL, 0x0000000006666666ULL, }, + { 0x0000000000001999ULL, 0x0000000333333333ULL, }, + { 0xffffffffffffffffULL, 0x0000000000000000ULL, }, /* 48 */ + { 0xe38e38e38e38e38eULL, 0x38e38e38e38e38e3ULL, }, + { 0xfffffffffff8e38eULL, 0x00000000000e38e3ULL, }, + { 0xffffff1c71c71c71ULL, 0x000001c71c71c71cULL, }, + { 0xfffe38e38e38e38eULL, 0x00038e38e38e38e3ULL, }, + { 0xfffffffffffffc71ULL, 0x000000000000071cULL, }, + { 0xffff8e38e38e38e3ULL, 0x00000000071c71c7ULL, }, + { 0xfffffffffffff1c7ULL, 0x000000038e38e38eULL, }, + { 0x0000000000000000ULL, 0xffffffffffffffffULL, }, /* 56 */ + { 0x1c71c71c71c71c71ULL, 0xc71c71c71c71c71cULL, }, + { 0x0000000000071c71ULL, 0xfffffffffff1c71cULL, }, + { 0x000000e38e38e38eULL, 0xfffffe38e38e38e3ULL, }, + { 0x0001c71c71c71c71ULL, 0xfffc71c71c71c71cULL, }, + { 0x000000000000038eULL, 0xfffffffffffff8e3ULL, }, + { 0x000071c71c71c71cULL, 0xfffffffff8e38e38ULL, }, + { 0x0000000000000e38ULL, 0xfffffffc71c71c71ULL, }, + { 0x886ae6cc28625540ULL, 0x0004b670b5efe7bbULL, }, /* 64 */ + { 0xff886ae6cc286255ULL, 0x0000000000000004ULL, }, + { 0x886ae6cc28625540ULL, 0x000004b670b5efe7ULL, }, + { 0xfffe21ab9b30a189ULL, 0x000000004b670b5eULL, }, + { 0xfbbe00634d93c708ULL, 0x00012f7bb1a153f5ULL, }, + { 0xfffbbe00634d93c7ULL, 0x0000000000000001ULL, }, + { 0xfbbe00634d93c708ULL, 0x0000012f7bb1a153ULL, }, + { 0xffffeef8018d364fULL, 0x0000000012f7bb1aULL, }, + { 0xac5aaeaab9cf8b80ULL, 0x00027d8c6ffab2b2ULL, }, /* 72 */ + { 0xffac5aaeaab9cf8bULL, 0x0000000000000002ULL, }, + { 0xac5aaeaab9cf8b80ULL, 0x0000027d8c6ffab2ULL, }, + { 0xfffeb16abaaae73eULL, 0x0000000027d8c6ffULL, }, + { 0x704f164d5e31e24eULL, 0xfff8df188d8a942eULL, }, + { 0x00704f164d5e31e2ULL, 0xfffffffffffffff8ULL, }, + { 0x704f164d5e31e24eULL, 0xfffff8df188d8a94ULL, }, + { 0x0001c13c593578c7ULL, 0xffffffff8df188d8ULL, }, + }; + + reset_msa_registers(); + + gettimeofday(&start, NULL); + + for (i = 0; i < PATTERN_INPUTS_SHORT_COUNT; i++) { + for (j = 0; j < PATTERN_INPUTS_SHORT_COUNT; j++) { + do_msa_SRA_D(b128_pattern[i], b128_pattern[j], + b128_result[PATTERN_INPUTS_SHORT_COUNT * i + j]); + } + } + + for (i = 0; i < RANDOM_INPUTS_SHORT_COUNT; i++) { + for (j = 0; j < RANDOM_INPUTS_SHORT_COUNT; j++) { + do_msa_SRA_D(b128_random[i], b128_random[j], + b128_result[((PATTERN_INPUTS_SHORT_COUNT) * + (PATTERN_INPUTS_SHORT_COUNT)) + + RANDOM_INPUTS_SHORT_COUNT * i + j]); + } + } + + gettimeofday(&end, NULL); + + elapsed_time = (end.tv_sec - start.tv_sec) * 1000.0; + elapsed_time += (end.tv_usec - start.tv_usec) / 1000.0; + + ret = check_results(instruction_name, TEST_COUNT_TOTAL, elapsed_time, + &b128_result[0][0], &b128_expect[0][0]); + + return ret; +} diff --git a/tests/tcg/mips/user/ase/msa/shift/test_msa_sra_h.c b/tests/tcg/mips/user/ase/msa/shift/test_msa_sra_h.c new file mode 100644 index 0000000000..2e505089de --- /dev/null +++ b/tests/tcg/mips/user/ase/msa/shift/test_msa_sra_h.c @@ -0,0 +1,155 @@ +/* + * Test program for MSA instruction SRA.H + * + * Copyright (C) 2019 Wave Computing, Inc. + * Copyright (C) 2019 Aleksandar Markovic <amarkovic@wavecomp.com> + * + * This program 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, see <https://www.gnu.org/licenses/>. + * + */ + +#include <sys/time.h> +#include <stdint.h> + +#include "../../../../include/wrappers_msa.h" +#include "../../../../include/test_inputs_128.h" +#include "../../../../include/test_utils_128.h" + +#define TEST_COUNT_TOTAL ( \ + (PATTERN_INPUTS_SHORT_COUNT) * (PATTERN_INPUTS_SHORT_COUNT) + \ + (RANDOM_INPUTS_SHORT_COUNT) * (RANDOM_INPUTS_SHORT_COUNT)) + + +int32_t main(void) +{ + char *instruction_name = "SRA.H"; + int32_t ret; + uint32_t i, j; + struct timeval start, end; + double elapsed_time; + + uint64_t b128_result[TEST_COUNT_TOTAL][2]; + uint64_t b128_expect[TEST_COUNT_TOTAL][2] = { + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 0 */ + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, /* 8 */ + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 16 */ + { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, }, + { 0xffeaffeaffeaffeaULL, 0xffeaffeaffeaffeaULL, }, + { 0xfd55fd55fd55fd55ULL, 0xfd55fd55fd55fd55ULL, }, + { 0xfffafffafffafffaULL, 0xfffafffafffafffaULL, }, + { 0xf555f555f555f555ULL, 0xf555f555f555f555ULL, }, + { 0xfffef555ffaafffeULL, 0xf555ffaafffef555ULL, }, + { 0xd555fffaff55d555ULL, 0xfffaff55d555fffaULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, /* 24 */ + { 0x5555555555555555ULL, 0x5555555555555555ULL, }, + { 0x0015001500150015ULL, 0x0015001500150015ULL, }, + { 0x02aa02aa02aa02aaULL, 0x02aa02aa02aa02aaULL, }, + { 0x0005000500050005ULL, 0x0005000500050005ULL, }, + { 0x0aaa0aaa0aaa0aaaULL, 0x0aaa0aaa0aaa0aaaULL, }, + { 0x00010aaa00550001ULL, 0x0aaa005500010aaaULL, }, + { 0x2aaa000500aa2aaaULL, 0x000500aa2aaa0005ULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 32 */ + { 0xccccccccccccccccULL, 0xccccccccccccccccULL, }, + { 0xfff3fff3fff3fff3ULL, 0xfff3fff3fff3fff3ULL, }, + { 0xfe66fe66fe66fe66ULL, 0xfe66fe66fe66fe66ULL, }, + { 0xfffcfffcfffcfffcULL, 0xfffcfffcfffcfffcULL, }, + { 0xf999f999f999f999ULL, 0xf999f999f999f999ULL, }, + { 0xfffff999ffccffffULL, 0xf999ffccfffff999ULL, }, + { 0xe666fffcff99e666ULL, 0xfffcff99e666fffcULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, /* 40 */ + { 0x3333333333333333ULL, 0x3333333333333333ULL, }, + { 0x000c000c000c000cULL, 0x000c000c000c000cULL, }, + { 0x0199019901990199ULL, 0x0199019901990199ULL, }, + { 0x0003000300030003ULL, 0x0003000300030003ULL, }, + { 0x0666066606660666ULL, 0x0666066606660666ULL, }, + { 0x0000066600330000ULL, 0x0666003300000666ULL, }, + { 0x1999000300661999ULL, 0x0003006619990003ULL, }, + { 0xffff0000ffffffffULL, 0x0000ffffffff0000ULL, }, /* 48 */ + { 0xe38e38e38e38e38eULL, 0x38e38e38e38e38e3ULL, }, + { 0xfff8000effe3fff8ULL, 0x000effe3fff8000eULL, }, + { 0xff1c01c7fc71ff1cULL, 0x01c7fc71ff1c01c7ULL, }, + { 0xfffe0003fff8fffeULL, 0x0003fff8fffe0003ULL, }, + { 0xfc71071cf1c7fc71ULL, 0x071cf1c7fc71071cULL, }, + { 0xffff071cff8effffULL, 0x071cff8effff071cULL, }, + { 0xf1c70003ff1cf1c7ULL, 0x0003ff1cf1c70003ULL, }, + { 0x0000ffff00000000ULL, 0xffff00000000ffffULL, }, /* 56 */ + { 0x1c71c71c71c71c71ULL, 0xc71c71c71c71c71cULL, }, + { 0x0007fff1001c0007ULL, 0xfff1001c0007fff1ULL, }, + { 0x00e3fe38038e00e3ULL, 0xfe38038e00e3fe38ULL, }, + { 0x0001fffc00070001ULL, 0xfffc00070001fffcULL, }, + { 0x038ef8e30e38038eULL, 0xf8e30e38038ef8e3ULL, }, + { 0x0000f8e300710000ULL, 0xf8e300710000f8e3ULL, }, + { 0x0e38fffc00e30e38ULL, 0xfffc00e30e38fffcULL, }, + { 0xffe2fffe0a185540ULL, 0x00960000fffffffbULL, }, /* 64 */ + { 0xfffefcd9050c0055ULL, 0x00960002fffffffbULL, }, + { 0xffe2fff900005540ULL, 0x004b0000fffffb00ULL, }, + { 0xffffffff14310001ULL, 0x25b3000bff9eb00cULL, }, + { 0xfffe00001364c708ULL, 0x0025fffe00020005ULL, }, + { 0xffff000c09b2ffc7ULL, 0x0025ffee00000005ULL, }, + { 0xfffe00000000c708ULL, 0x0012ffff0002052fULL, }, + { 0xffff000026c9ffffULL, 0x097bffbb054f52fcULL, }, + { 0xffebfffaee738b80ULL, 0x004ffffffff50002ULL, }, /* 72 */ + { 0xfffef5d5f739ff8bULL, 0x004ffff1ffff0002ULL, }, + { 0xffebffebffff8b80ULL, 0x0027fffffff50251ULL, }, + { 0xfffffffddce7fffeULL, 0x13ecffc6eaca2514ULL, }, + { 0x001c0001178ce24eULL, 0xff1bfffefff5fffeULL, }, + { 0x000102c90bc6ffe2ULL, 0xff1bffe2fffffffeULL, }, + { 0x001c00050000e24eULL, 0xff8dfffffff5fe2aULL, }, + { 0x000000002f18ffffULL, 0xc6f8ff88ea50e2a0ULL, }, + }; + + reset_msa_registers(); + + gettimeofday(&start, NULL); + + for (i = 0; i < PATTERN_INPUTS_SHORT_COUNT; i++) { + for (j = 0; j < PATTERN_INPUTS_SHORT_COUNT; j++) { + do_msa_SRA_H(b128_pattern[i], b128_pattern[j], + b128_result[PATTERN_INPUTS_SHORT_COUNT * i + j]); + } + } + + for (i = 0; i < RANDOM_INPUTS_SHORT_COUNT; i++) { + for (j = 0; j < RANDOM_INPUTS_SHORT_COUNT; j++) { + do_msa_SRA_H(b128_random[i], b128_random[j], + b128_result[((PATTERN_INPUTS_SHORT_COUNT) * + (PATTERN_INPUTS_SHORT_COUNT)) + + RANDOM_INPUTS_SHORT_COUNT * i + j]); + } + } + + gettimeofday(&end, NULL); + + elapsed_time = (end.tv_sec - start.tv_sec) * 1000.0; + elapsed_time += (end.tv_usec - start.tv_usec) / 1000.0; + + ret = check_results(instruction_name, TEST_COUNT_TOTAL, elapsed_time, + &b128_result[0][0], &b128_expect[0][0]); + + return ret; +} diff --git a/tests/tcg/mips/user/ase/msa/shift/test_msa_sra_w.c b/tests/tcg/mips/user/ase/msa/shift/test_msa_sra_w.c new file mode 100644 index 0000000000..f4ba1b5621 --- /dev/null +++ b/tests/tcg/mips/user/ase/msa/shift/test_msa_sra_w.c @@ -0,0 +1,155 @@ +/* + * Test program for MSA instruction SRA.W + * + * Copyright (C) 2019 Wave Computing, Inc. + * Copyright (C) 2019 Aleksandar Markovic <amarkovic@wavecomp.com> + * + * This program 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, see <https://www.gnu.org/licenses/>. + * + */ + +#include <sys/time.h> +#include <stdint.h> + +#include "../../../../include/wrappers_msa.h" +#include "../../../../include/test_inputs_128.h" +#include "../../../../include/test_utils_128.h" + +#define TEST_COUNT_TOTAL ( \ + (PATTERN_INPUTS_SHORT_COUNT) * (PATTERN_INPUTS_SHORT_COUNT) + \ + (RANDOM_INPUTS_SHORT_COUNT) * (RANDOM_INPUTS_SHORT_COUNT)) + + +int32_t main(void) +{ + char *instruction_name = "SRA.W"; + int32_t ret; + uint32_t i, j; + struct timeval start, end; + double elapsed_time; + + uint64_t b128_result[TEST_COUNT_TOTAL][2]; + uint64_t b128_expect[TEST_COUNT_TOTAL][2] = { + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 0 */ + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, /* 8 */ + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 16 */ + { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, }, + { 0xffeaaaaaffeaaaaaULL, 0xffeaaaaaffeaaaaaULL, }, + { 0xfffffd55fffffd55ULL, 0xfffffd55fffffd55ULL, }, + { 0xfffaaaaafffaaaaaULL, 0xfffaaaaafffaaaaaULL, }, + { 0xfffff555fffff555ULL, 0xfffff555fffff555ULL, }, + { 0xf5555555fffeaaaaULL, 0xffffffaaf5555555ULL, }, + { 0xfffffffaffffd555ULL, 0xff555555fffffffaULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, /* 24 */ + { 0x5555555555555555ULL, 0x5555555555555555ULL, }, + { 0x0015555500155555ULL, 0x0015555500155555ULL, }, + { 0x000002aa000002aaULL, 0x000002aa000002aaULL, }, + { 0x0005555500055555ULL, 0x0005555500055555ULL, }, + { 0x00000aaa00000aaaULL, 0x00000aaa00000aaaULL, }, + { 0x0aaaaaaa00015555ULL, 0x000000550aaaaaaaULL, }, + { 0x0000000500002aaaULL, 0x00aaaaaa00000005ULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 32 */ + { 0xccccccccccccccccULL, 0xccccccccccccccccULL, }, + { 0xfff33333fff33333ULL, 0xfff33333fff33333ULL, }, + { 0xfffffe66fffffe66ULL, 0xfffffe66fffffe66ULL, }, + { 0xfffcccccfffcccccULL, 0xfffcccccfffcccccULL, }, + { 0xfffff999fffff999ULL, 0xfffff999fffff999ULL, }, + { 0xf9999999ffff3333ULL, 0xffffffccf9999999ULL, }, + { 0xfffffffcffffe666ULL, 0xff999999fffffffcULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, /* 40 */ + { 0x3333333333333333ULL, 0x3333333333333333ULL, }, + { 0x000ccccc000cccccULL, 0x000ccccc000cccccULL, }, + { 0x0000019900000199ULL, 0x0000019900000199ULL, }, + { 0x0003333300033333ULL, 0x0003333300033333ULL, }, + { 0x0000066600000666ULL, 0x0000066600000666ULL, }, + { 0x066666660000ccccULL, 0x0000003306666666ULL, }, + { 0x0000000300001999ULL, 0x0066666600000003ULL, }, + { 0xffffffffffffffffULL, 0x00000000ffffffffULL, }, /* 48 */ + { 0xe38e38e38e38e38eULL, 0x38e38e38e38e38e3ULL, }, + { 0xfff8e38effe38e38ULL, 0x000e38e3fff8e38eULL, }, + { 0xffffff1cfffffc71ULL, 0x000001c7ffffff1cULL, }, + { 0xfffe38e3fff8e38eULL, 0x00038e38fffe38e3ULL, }, + { 0xfffffc71fffff1c7ULL, 0x0000071cfffffc71ULL, }, + { 0xfc71c71cfffe38e3ULL, 0x00000038fc71c71cULL, }, + { 0xfffffffeffffc71cULL, 0x0071c71cfffffffeULL, }, + { 0x0000000000000000ULL, 0xffffffff00000000ULL, }, /* 56 */ + { 0x1c71c71c71c71c71ULL, 0xc71c71c71c71c71cULL, }, + { 0x00071c71001c71c7ULL, 0xfff1c71c00071c71ULL, }, + { 0x000000e30000038eULL, 0xfffffe38000000e3ULL, }, + { 0x0001c71c00071c71ULL, 0xfffc71c70001c71cULL, }, + { 0x0000038e00000e38ULL, 0xfffff8e30000038eULL, }, + { 0x038e38e30001c71cULL, 0xffffffc7038e38e3ULL, }, + { 0x00000001000038e3ULL, 0xff8e38e300000001ULL, }, + { 0xfff886ae28625540ULL, 0x00000001ffffe7bbULL, }, /* 64 */ + { 0xf10d5cd900286255ULL, 0x00000012ffffffffULL, }, + { 0xffe21ab928625540ULL, 0x00000000ffffffe7ULL, }, + { 0xfffc43570000a189ULL, 0x0000004bfe7bb00cULL, }, + { 0xffffbbe04d93c708ULL, 0x00000000000153f5ULL, }, + { 0xff77c00c004d93c7ULL, 0x0000000400000001ULL, }, + { 0xfffeef804d93c708ULL, 0x0000000000000153ULL, }, + { 0xffffddf00001364fULL, 0x00000012153f52fcULL, }, + { 0xfffac5aab9cf8b80ULL, 0x00000000fffab2b2ULL, }, /* 72 */ + { 0xf58b55d5ffb9cf8bULL, 0x00000009fffffffaULL, }, + { 0xffeb16abb9cf8b80ULL, 0x00000000fffffab2ULL, }, + { 0xfffd62d5fffee73eULL, 0x00000027ab2b2514ULL, }, + { 0x000704f15e31e24eULL, 0xfffffffefffa942eULL, }, + { 0x0e09e2c9005e31e2ULL, 0xffffffe3fffffffaULL, }, + { 0x001c13c55e31e24eULL, 0xfffffffffffffa94ULL, }, + { 0x00038278000178c7ULL, 0xffffff8da942e2a0ULL, }, + }; + + reset_msa_registers(); + + gettimeofday(&start, NULL); + + for (i = 0; i < PATTERN_INPUTS_SHORT_COUNT; i++) { + for (j = 0; j < PATTERN_INPUTS_SHORT_COUNT; j++) { + do_msa_SRA_W(b128_pattern[i], b128_pattern[j], + b128_result[PATTERN_INPUTS_SHORT_COUNT * i + j]); + } + } + + for (i = 0; i < RANDOM_INPUTS_SHORT_COUNT; i++) { + for (j = 0; j < RANDOM_INPUTS_SHORT_COUNT; j++) { + do_msa_SRA_W(b128_random[i], b128_random[j], + b128_result[((PATTERN_INPUTS_SHORT_COUNT) * + (PATTERN_INPUTS_SHORT_COUNT)) + + RANDOM_INPUTS_SHORT_COUNT * i + j]); + } + } + + gettimeofday(&end, NULL); + + elapsed_time = (end.tv_sec - start.tv_sec) * 1000.0; + elapsed_time += (end.tv_usec - start.tv_usec) / 1000.0; + + ret = check_results(instruction_name, TEST_COUNT_TOTAL, elapsed_time, + &b128_result[0][0], &b128_expect[0][0]); + + return ret; +} diff --git a/tests/tcg/mips/user/ase/msa/shift/test_msa_srar_b.c b/tests/tcg/mips/user/ase/msa/shift/test_msa_srar_b.c new file mode 100644 index 0000000000..73e60314e5 --- /dev/null +++ b/tests/tcg/mips/user/ase/msa/shift/test_msa_srar_b.c @@ -0,0 +1,155 @@ +/* + * Test program for MSA instruction SRAR.B + * + * Copyright (C) 2019 Wave Computing, Inc. + * Copyright (C) 2019 Aleksandar Markovic <amarkovic@wavecomp.com> + * + * This program 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, see <https://www.gnu.org/licenses/>. + * + */ + +#include <sys/time.h> +#include <stdint.h> + +#include "../../../../include/wrappers_msa.h" +#include "../../../../include/test_inputs_128.h" +#include "../../../../include/test_utils_128.h" + +#define TEST_COUNT_TOTAL ( \ + (PATTERN_INPUTS_SHORT_COUNT) * (PATTERN_INPUTS_SHORT_COUNT) + \ + (RANDOM_INPUTS_SHORT_COUNT) * (RANDOM_INPUTS_SHORT_COUNT)) + + +int32_t main(void) +{ + char *instruction_name = "SRAR.B"; + int32_t ret; + uint32_t i, j; + struct timeval start, end; + double elapsed_time; + + uint64_t b128_result[TEST_COUNT_TOTAL][2]; + uint64_t b128_expect[TEST_COUNT_TOTAL][2] = { + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, /* 0 */ + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000ff0000ff0000ULL, 0xff0000ff0000ff00ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, /* 8 */ + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 16 */ + { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, }, + { 0xebebebebebebebebULL, 0xebebebebebebebebULL, }, + { 0xfdfdfdfdfdfdfdfdULL, 0xfdfdfdfdfdfdfdfdULL, }, + { 0xfbfbfbfbfbfbfbfbULL, 0xfbfbfbfbfbfbfbfbULL, }, + { 0xf5f5f5f5f5f5f5f5ULL, 0xf5f5f5f5f5f5f5f5ULL, }, + { 0xf5ffaaf5ffaaf5ffULL, 0xaaf5ffaaf5ffaaf5ULL, }, + { 0xfbd5fffbd5fffbd5ULL, 0xfffbd5fffbd5fffbULL, }, + { 0x0101010101010101ULL, 0x0101010101010101ULL, }, /* 24 */ + { 0x5555555555555555ULL, 0x5555555555555555ULL, }, + { 0x1515151515151515ULL, 0x1515151515151515ULL, }, + { 0x0303030303030303ULL, 0x0303030303030303ULL, }, + { 0x0505050505050505ULL, 0x0505050505050505ULL, }, + { 0x0b0b0b0b0b0b0b0bULL, 0x0b0b0b0b0b0b0b0bULL, }, + { 0x0b01550b01550b01ULL, 0x550b01550b01550bULL, }, + { 0x052b01052b01052bULL, 0x01052b01052b0105ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, /* 32 */ + { 0xccccccccccccccccULL, 0xccccccccccccccccULL, }, + { 0xf3f3f3f3f3f3f3f3ULL, 0xf3f3f3f3f3f3f3f3ULL, }, + { 0xfefefefefefefefeULL, 0xfefefefefefefefeULL, }, + { 0xfdfdfdfdfdfdfdfdULL, 0xfdfdfdfdfdfdfdfdULL, }, + { 0xfafafafafafafafaULL, 0xfafafafafafafafaULL, }, + { 0xfaffccfaffccfaffULL, 0xccfaffccfaffccfaULL, }, + { 0xfde600fde600fde6ULL, 0x00fde600fde600fdULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, /* 40 */ + { 0x3333333333333333ULL, 0x3333333333333333ULL, }, + { 0x0d0d0d0d0d0d0d0dULL, 0x0d0d0d0d0d0d0d0dULL, }, + { 0x0202020202020202ULL, 0x0202020202020202ULL, }, + { 0x0303030303030303ULL, 0x0303030303030303ULL, }, + { 0x0606060606060606ULL, 0x0606060606060606ULL, }, + { 0x0601330601330601ULL, 0x3306013306013306ULL, }, + { 0x031a00031a00031aULL, 0x00031a00031a0003ULL, }, + { 0x00ff0000ff0000ffULL, 0x0000ff0000ff0000ULL, }, /* 48 */ + { 0xe38e38e38e38e38eULL, 0x38e38e38e38e38e3ULL, }, + { 0xf9e40ef9e40ef9e4ULL, 0x0ef9e40ef9e40ef9ULL, }, + { 0xfffc02fffc02fffcULL, 0x02fffc02fffc02ffULL, }, + { 0xfef904fef904fef9ULL, 0x04fef904fef904feULL, }, + { 0xfcf207fcf207fcf2ULL, 0x07fcf207fcf207fcULL, }, + { 0xfcfe38fcfe38fcfeULL, 0x38fcfe38fcfe38fcULL, }, + { 0xfec700fec700fec7ULL, 0x00fec700fec700feULL, }, + { 0x0001000001000001ULL, 0x0000010000010000ULL, }, /* 56 */ + { 0x1c71c71c71c71c71ULL, 0xc71c71c71c71c71cULL, }, + { 0x071cf2071cf2071cULL, 0xf2071cf2071cf207ULL, }, + { 0x0104fe0104fe0104ULL, 0xfe0104fe0104fe01ULL, }, + { 0x0207fc0207fc0207ULL, 0xfc0207fc0207fc02ULL, }, + { 0x040ef9040ef9040eULL, 0xf9040ef9040ef904ULL, }, + { 0x0402c70402c70402ULL, 0xc70402c70402c704ULL, }, + { 0x0239000239000239ULL, 0x0002390002390002ULL, }, + { 0x881b00fd28190340ULL, 0x09010101000fb001ULL, }, /* 64 */ + { 0xf102e6fa010c0140ULL, 0x130101180001ec01ULL, }, + { 0xf91b00f314010b40ULL, 0x01670001000ffe01ULL, }, + { 0x880100fe01311501ULL, 0x02340b5eff1fec0cULL, }, + { 0xfbf000064de5fe08ULL, 0x0200f70000085200ULL, }, + { 0xffff000c02f20008ULL, 0x0500f70701001500ULL, }, + { 0x00f0001927fff908ULL, 0x00f7ff0003080300ULL, }, + { 0xfbff000301caf200ULL, 0x01fcbb1a0b1015fcULL, }, + { 0xac17fffbb9f4fc80ULL, 0x0500f900ff052501ULL, }, /* 72 */ + { 0xf601aef5fefaff80ULL, 0x0a00f900fd000901ULL, }, + { 0xfb17ffebdd00f180ULL, 0x00d8ff00f5050101ULL, }, + { 0xac01fffdffe8e3feULL, 0x01ecc6ffd60b0914ULL, }, + { 0x701400055e0cff4eULL, 0xf200f1ffff08e2faULL, }, + { 0x0e01160a0306004eULL, 0xe300f1f6fd01f9faULL, }, + { 0x071400132f00fc4eULL, 0xfff1fe00f508fffaULL, }, + { 0x700100020119f901ULL, 0xfcf988d8d511f9a0ULL, }, + }; + + reset_msa_registers(); + + gettimeofday(&start, NULL); + + for (i = 0; i < PATTERN_INPUTS_SHORT_COUNT; i++) { + for (j = 0; j < PATTERN_INPUTS_SHORT_COUNT; j++) { + do_msa_SRAR_B(b128_pattern[i], b128_pattern[j], + b128_result[PATTERN_INPUTS_SHORT_COUNT * i + j]); + } + } + + for (i = 0; i < RANDOM_INPUTS_SHORT_COUNT; i++) { + for (j = 0; j < RANDOM_INPUTS_SHORT_COUNT; j++) { + do_msa_SRAR_B(b128_random[i], b128_random[j], + b128_result[((PATTERN_INPUTS_SHORT_COUNT) * + (PATTERN_INPUTS_SHORT_COUNT)) + + RANDOM_INPUTS_SHORT_COUNT * i + j]); + } + } + + gettimeofday(&end, NULL); + + elapsed_time = (end.tv_sec - start.tv_sec) * 1000.0; + elapsed_time += (end.tv_usec - start.tv_usec) / 1000.0; + + ret = check_results(instruction_name, TEST_COUNT_TOTAL, elapsed_time, + &b128_result[0][0], &b128_expect[0][0]); + + return ret; +} diff --git a/tests/tcg/mips/user/ase/msa/shift/test_msa_srar_d.c b/tests/tcg/mips/user/ase/msa/shift/test_msa_srar_d.c new file mode 100644 index 0000000000..b784897090 --- /dev/null +++ b/tests/tcg/mips/user/ase/msa/shift/test_msa_srar_d.c @@ -0,0 +1,155 @@ +/* + * Test program for MSA instruction SRAR.D + * + * Copyright (C) 2019 Wave Computing, Inc. + * Copyright (C) 2019 Aleksandar Markovic <amarkovic@wavecomp.com> + * + * This program 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, see <https://www.gnu.org/licenses/>. + * + */ + +#include <sys/time.h> +#include <stdint.h> + +#include "../../../../include/wrappers_msa.h" +#include "../../../../include/test_inputs_128.h" +#include "../../../../include/test_utils_128.h" + +#define TEST_COUNT_TOTAL ( \ + (PATTERN_INPUTS_SHORT_COUNT) * (PATTERN_INPUTS_SHORT_COUNT) + \ + (RANDOM_INPUTS_SHORT_COUNT) * (RANDOM_INPUTS_SHORT_COUNT)) + + +int32_t main(void) +{ + char *instruction_name = "SRAR.D"; + int32_t ret; + uint32_t i, j; + struct timeval start, end; + double elapsed_time; + + uint64_t b128_result[TEST_COUNT_TOTAL][2]; + uint64_t b128_expect[TEST_COUNT_TOTAL][2] = { + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, /* 0 */ + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, /* 8 */ + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 16 */ + { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, }, + { 0xffffffffffeaaaabULL, 0xffffffffffeaaaabULL, }, + { 0xfffffd5555555555ULL, 0xfffffd5555555555ULL, }, + { 0xfffaaaaaaaaaaaabULL, 0xfffaaaaaaaaaaaabULL, }, + { 0xfffffffffffff555ULL, 0xfffffffffffff555ULL, }, + { 0xfffeaaaaaaaaaaabULL, 0xfffffffff5555555ULL, }, + { 0xffffffffffffd555ULL, 0xfffffffaaaaaaaabULL, }, + { 0x0000000000000001ULL, 0x0000000000000001ULL, }, /* 24 */ + { 0x5555555555555555ULL, 0x5555555555555555ULL, }, + { 0x0000000000155555ULL, 0x0000000000155555ULL, }, + { 0x000002aaaaaaaaabULL, 0x000002aaaaaaaaabULL, }, + { 0x0005555555555555ULL, 0x0005555555555555ULL, }, + { 0x0000000000000aabULL, 0x0000000000000aabULL, }, + { 0x0001555555555555ULL, 0x000000000aaaaaabULL, }, + { 0x0000000000002aabULL, 0x0000000555555555ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, /* 32 */ + { 0xccccccccccccccccULL, 0xccccccccccccccccULL, }, + { 0xfffffffffff33333ULL, 0xfffffffffff33333ULL, }, + { 0xfffffe6666666666ULL, 0xfffffe6666666666ULL, }, + { 0xfffccccccccccccdULL, 0xfffccccccccccccdULL, }, + { 0xfffffffffffff99aULL, 0xfffffffffffff99aULL, }, + { 0xffff333333333333ULL, 0xfffffffff999999aULL, }, + { 0xffffffffffffe666ULL, 0xfffffffccccccccdULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, /* 40 */ + { 0x3333333333333333ULL, 0x3333333333333333ULL, }, + { 0x00000000000ccccdULL, 0x00000000000ccccdULL, }, + { 0x000001999999999aULL, 0x000001999999999aULL, }, + { 0x0003333333333333ULL, 0x0003333333333333ULL, }, + { 0x0000000000000666ULL, 0x0000000000000666ULL, }, + { 0x0000cccccccccccdULL, 0x0000000006666666ULL, }, + { 0x000000000000199aULL, 0x0000000333333333ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, /* 48 */ + { 0xe38e38e38e38e38eULL, 0x38e38e38e38e38e3ULL, }, + { 0xfffffffffff8e38eULL, 0x00000000000e38e4ULL, }, + { 0xffffff1c71c71c72ULL, 0x000001c71c71c71cULL, }, + { 0xfffe38e38e38e38eULL, 0x00038e38e38e38e4ULL, }, + { 0xfffffffffffffc72ULL, 0x000000000000071cULL, }, + { 0xffff8e38e38e38e4ULL, 0x00000000071c71c7ULL, }, + { 0xfffffffffffff1c7ULL, 0x000000038e38e38eULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, /* 56 */ + { 0x1c71c71c71c71c71ULL, 0xc71c71c71c71c71cULL, }, + { 0x0000000000071c72ULL, 0xfffffffffff1c71cULL, }, + { 0x000000e38e38e38eULL, 0xfffffe38e38e38e4ULL, }, + { 0x0001c71c71c71c72ULL, 0xfffc71c71c71c71cULL, }, + { 0x000000000000038eULL, 0xfffffffffffff8e4ULL, }, + { 0x000071c71c71c71cULL, 0xfffffffff8e38e39ULL, }, + { 0x0000000000000e39ULL, 0xfffffffc71c71c72ULL, }, + { 0x886ae6cc28625540ULL, 0x0004b670b5efe7bbULL, }, /* 64 */ + { 0xff886ae6cc286255ULL, 0x0000000000000005ULL, }, + { 0x886ae6cc28625540ULL, 0x000004b670b5efe8ULL, }, + { 0xfffe21ab9b30a189ULL, 0x000000004b670b5fULL, }, + { 0xfbbe00634d93c708ULL, 0x00012f7bb1a153f5ULL, }, + { 0xfffbbe00634d93c7ULL, 0x0000000000000001ULL, }, + { 0xfbbe00634d93c708ULL, 0x0000012f7bb1a154ULL, }, + { 0xffffeef8018d364fULL, 0x0000000012f7bb1aULL, }, + { 0xac5aaeaab9cf8b80ULL, 0x00027d8c6ffab2b2ULL, }, /* 72 */ + { 0xffac5aaeaab9cf8cULL, 0x0000000000000002ULL, }, + { 0xac5aaeaab9cf8b80ULL, 0x0000027d8c6ffab3ULL, }, + { 0xfffeb16abaaae73eULL, 0x0000000027d8c700ULL, }, + { 0x704f164d5e31e24eULL, 0xfff8df188d8a942eULL, }, + { 0x00704f164d5e31e2ULL, 0xfffffffffffffff9ULL, }, + { 0x704f164d5e31e24eULL, 0xfffff8df188d8a94ULL, }, + { 0x0001c13c593578c8ULL, 0xffffffff8df188d9ULL, }, + }; + + reset_msa_registers(); + + gettimeofday(&start, NULL); + + for (i = 0; i < PATTERN_INPUTS_SHORT_COUNT; i++) { + for (j = 0; j < PATTERN_INPUTS_SHORT_COUNT; j++) { + do_msa_SRAR_D(b128_pattern[i], b128_pattern[j], + b128_result[PATTERN_INPUTS_SHORT_COUNT * i + j]); + } + } + + for (i = 0; i < RANDOM_INPUTS_SHORT_COUNT; i++) { + for (j = 0; j < RANDOM_INPUTS_SHORT_COUNT; j++) { + do_msa_SRAR_D(b128_random[i], b128_random[j], + b128_result[((PATTERN_INPUTS_SHORT_COUNT) * + (PATTERN_INPUTS_SHORT_COUNT)) + + RANDOM_INPUTS_SHORT_COUNT * i + j]); + } + } + + gettimeofday(&end, NULL); + + elapsed_time = (end.tv_sec - start.tv_sec) * 1000.0; + elapsed_time += (end.tv_usec - start.tv_usec) / 1000.0; + + ret = check_results(instruction_name, TEST_COUNT_TOTAL, elapsed_time, + &b128_result[0][0], &b128_expect[0][0]); + + return ret; +} diff --git a/tests/tcg/mips/user/ase/msa/shift/test_msa_srar_h.c b/tests/tcg/mips/user/ase/msa/shift/test_msa_srar_h.c new file mode 100644 index 0000000000..476d2e1004 --- /dev/null +++ b/tests/tcg/mips/user/ase/msa/shift/test_msa_srar_h.c @@ -0,0 +1,155 @@ +/* + * Test program for MSA instruction SRAR.H + * + * Copyright (C) 2019 Wave Computing, Inc. + * Copyright (C) 2019 Aleksandar Markovic <amarkovic@wavecomp.com> + * + * This program 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, see <https://www.gnu.org/licenses/>. + * + */ + +#include <sys/time.h> +#include <stdint.h> + +#include "../../../../include/wrappers_msa.h" +#include "../../../../include/test_inputs_128.h" +#include "../../../../include/test_utils_128.h" + +#define TEST_COUNT_TOTAL ( \ + (PATTERN_INPUTS_SHORT_COUNT) * (PATTERN_INPUTS_SHORT_COUNT) + \ + (RANDOM_INPUTS_SHORT_COUNT) * (RANDOM_INPUTS_SHORT_COUNT)) + + +int32_t main(void) +{ + char *instruction_name = "SRAR.H"; + int32_t ret; + uint32_t i, j; + struct timeval start, end; + double elapsed_time; + + uint64_t b128_result[TEST_COUNT_TOTAL][2]; + uint64_t b128_expect[TEST_COUNT_TOTAL][2] = { + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, /* 0 */ + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, /* 8 */ + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 16 */ + { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, }, + { 0xffebffebffebffebULL, 0xffebffebffebffebULL, }, + { 0xfd55fd55fd55fd55ULL, 0xfd55fd55fd55fd55ULL, }, + { 0xfffbfffbfffbfffbULL, 0xfffbfffbfffbfffbULL, }, + { 0xf555f555f555f555ULL, 0xf555f555f555f555ULL, }, + { 0xfffff555ffabffffULL, 0xf555ffabfffff555ULL, }, + { 0xd555fffbff55d555ULL, 0xfffbff55d555fffbULL, }, + { 0x0001000100010001ULL, 0x0001000100010001ULL, }, /* 24 */ + { 0x5555555555555555ULL, 0x5555555555555555ULL, }, + { 0x0015001500150015ULL, 0x0015001500150015ULL, }, + { 0x02ab02ab02ab02abULL, 0x02ab02ab02ab02abULL, }, + { 0x0005000500050005ULL, 0x0005000500050005ULL, }, + { 0x0aab0aab0aab0aabULL, 0x0aab0aab0aab0aabULL, }, + { 0x00010aab00550001ULL, 0x0aab005500010aabULL, }, + { 0x2aab000500ab2aabULL, 0x000500ab2aab0005ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, /* 32 */ + { 0xccccccccccccccccULL, 0xccccccccccccccccULL, }, + { 0xfff3fff3fff3fff3ULL, 0xfff3fff3fff3fff3ULL, }, + { 0xfe66fe66fe66fe66ULL, 0xfe66fe66fe66fe66ULL, }, + { 0xfffdfffdfffdfffdULL, 0xfffdfffdfffdfffdULL, }, + { 0xf99af99af99af99aULL, 0xf99af99af99af99aULL, }, + { 0xfffff99affcdffffULL, 0xf99affcdfffff99aULL, }, + { 0xe666fffdff9ae666ULL, 0xfffdff9ae666fffdULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, /* 40 */ + { 0x3333333333333333ULL, 0x3333333333333333ULL, }, + { 0x000d000d000d000dULL, 0x000d000d000d000dULL, }, + { 0x019a019a019a019aULL, 0x019a019a019a019aULL, }, + { 0x0003000300030003ULL, 0x0003000300030003ULL, }, + { 0x0666066606660666ULL, 0x0666066606660666ULL, }, + { 0x0001066600330001ULL, 0x0666003300010666ULL, }, + { 0x199a00030066199aULL, 0x00030066199a0003ULL, }, + { 0x00000000ffff0000ULL, 0x0000ffff00000000ULL, }, /* 48 */ + { 0xe38e38e38e38e38eULL, 0x38e38e38e38e38e3ULL, }, + { 0xfff9000effe4fff9ULL, 0x000effe4fff9000eULL, }, + { 0xff1c01c7fc72ff1cULL, 0x01c7fc72ff1c01c7ULL, }, + { 0xfffe0004fff9fffeULL, 0x0004fff9fffe0004ULL, }, + { 0xfc72071cf1c7fc72ULL, 0x071cf1c7fc72071cULL, }, + { 0x0000071cff8e0000ULL, 0x071cff8e0000071cULL, }, + { 0xf1c70004ff1cf1c7ULL, 0x0004ff1cf1c70004ULL, }, + { 0x0000000000010000ULL, 0x0000000100000000ULL, }, /* 56 */ + { 0x1c71c71c71c71c71ULL, 0xc71c71c71c71c71cULL, }, + { 0x0007fff2001c0007ULL, 0xfff2001c0007fff2ULL, }, + { 0x00e4fe39038e00e4ULL, 0xfe39038e00e4fe39ULL, }, + { 0x0002fffc00070002ULL, 0xfffc00070002fffcULL, }, + { 0x038ef8e40e39038eULL, 0xf8e40e39038ef8e4ULL, }, + { 0x0000f8e400720000ULL, 0xf8e400720000f8e4ULL, }, + { 0x0e39fffc00e40e39ULL, 0xfffc00e40e39fffcULL, }, + { 0xffe2fffe0a195540ULL, 0x009700000000fffbULL, }, /* 64 */ + { 0xfffefcda050c0055ULL, 0x009700030000fffbULL, }, + { 0xffe2fffa00005540ULL, 0x004b00000000fb01ULL, }, + { 0xffffffff14310001ULL, 0x25b4000bff9fb00cULL, }, + { 0xffff00001365c708ULL, 0x0026ffff00030005ULL, }, + { 0x0000000c09b2ffc7ULL, 0x0026ffef00000005ULL, }, + { 0xffff00000001c708ULL, 0x0013ffff00030530ULL, }, + { 0x0000000026caffffULL, 0x097cffbb055052fcULL, }, + { 0xffebfffbee748b80ULL, 0x0050fffffff50002ULL, }, /* 72 */ + { 0xfffff5d5f73aff8cULL, 0x0050fff2ffff0002ULL, }, + { 0xffebffecffff8b80ULL, 0x00280000fff50251ULL, }, + { 0xfffffffddce8fffeULL, 0x13ecffc7eacb2514ULL, }, + { 0x001c0001178ce24eULL, 0xff1cfffefff5fffeULL, }, + { 0x000202ca0bc6ffe2ULL, 0xff1cffe2fffffffeULL, }, + { 0x001c00060001e24eULL, 0xff8efffffff5fe2aULL, }, + { 0x000100012f190000ULL, 0xc6f9ff89ea51e2a0ULL, }, + }; + + reset_msa_registers(); + + gettimeofday(&start, NULL); + + for (i = 0; i < PATTERN_INPUTS_SHORT_COUNT; i++) { + for (j = 0; j < PATTERN_INPUTS_SHORT_COUNT; j++) { + do_msa_SRAR_H(b128_pattern[i], b128_pattern[j], + b128_result[PATTERN_INPUTS_SHORT_COUNT * i + j]); + } + } + + for (i = 0; i < RANDOM_INPUTS_SHORT_COUNT; i++) { + for (j = 0; j < RANDOM_INPUTS_SHORT_COUNT; j++) { + do_msa_SRAR_H(b128_random[i], b128_random[j], + b128_result[((PATTERN_INPUTS_SHORT_COUNT) * + (PATTERN_INPUTS_SHORT_COUNT)) + + RANDOM_INPUTS_SHORT_COUNT * i + j]); + } + } + + gettimeofday(&end, NULL); + + elapsed_time = (end.tv_sec - start.tv_sec) * 1000.0; + elapsed_time += (end.tv_usec - start.tv_usec) / 1000.0; + + ret = check_results(instruction_name, TEST_COUNT_TOTAL, elapsed_time, + &b128_result[0][0], &b128_expect[0][0]); + + return ret; +} diff --git a/tests/tcg/mips/user/ase/msa/shift/test_msa_srar_w.c b/tests/tcg/mips/user/ase/msa/shift/test_msa_srar_w.c new file mode 100644 index 0000000000..87d717325b --- /dev/null +++ b/tests/tcg/mips/user/ase/msa/shift/test_msa_srar_w.c @@ -0,0 +1,155 @@ +/* + * Test program for MSA instruction SRAR.W + * + * Copyright (C) 2019 Wave Computing, Inc. + * Copyright (C) 2019 Aleksandar Markovic <amarkovic@wavecomp.com> + * + * This program 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, see <https://www.gnu.org/licenses/>. + * + */ + +#include <sys/time.h> +#include <stdint.h> + +#include "../../../../include/wrappers_msa.h" +#include "../../../../include/test_inputs_128.h" +#include "../../../../include/test_utils_128.h" + +#define TEST_COUNT_TOTAL ( \ + (PATTERN_INPUTS_SHORT_COUNT) * (PATTERN_INPUTS_SHORT_COUNT) + \ + (RANDOM_INPUTS_SHORT_COUNT) * (RANDOM_INPUTS_SHORT_COUNT)) + + +int32_t main(void) +{ + char *instruction_name = "SRAR.W"; + int32_t ret; + uint32_t i, j; + struct timeval start, end; + double elapsed_time; + + uint64_t b128_result[TEST_COUNT_TOTAL][2]; + uint64_t b128_expect[TEST_COUNT_TOTAL][2] = { + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, /* 0 */ + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, /* 8 */ + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 16 */ + { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, }, + { 0xffeaaaabffeaaaabULL, 0xffeaaaabffeaaaabULL, }, + { 0xfffffd55fffffd55ULL, 0xfffffd55fffffd55ULL, }, + { 0xfffaaaabfffaaaabULL, 0xfffaaaabfffaaaabULL, }, + { 0xfffff555fffff555ULL, 0xfffff555fffff555ULL, }, + { 0xf5555555fffeaaabULL, 0xffffffabf5555555ULL, }, + { 0xfffffffbffffd555ULL, 0xff555555fffffffbULL, }, + { 0x0000000100000001ULL, 0x0000000100000001ULL, }, /* 24 */ + { 0x5555555555555555ULL, 0x5555555555555555ULL, }, + { 0x0015555500155555ULL, 0x0015555500155555ULL, }, + { 0x000002ab000002abULL, 0x000002ab000002abULL, }, + { 0x0005555500055555ULL, 0x0005555500055555ULL, }, + { 0x00000aab00000aabULL, 0x00000aab00000aabULL, }, + { 0x0aaaaaab00015555ULL, 0x000000550aaaaaabULL, }, + { 0x0000000500002aabULL, 0x00aaaaab00000005ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, /* 32 */ + { 0xccccccccccccccccULL, 0xccccccccccccccccULL, }, + { 0xfff33333fff33333ULL, 0xfff33333fff33333ULL, }, + { 0xfffffe66fffffe66ULL, 0xfffffe66fffffe66ULL, }, + { 0xfffccccdfffccccdULL, 0xfffccccdfffccccdULL, }, + { 0xfffff99afffff99aULL, 0xfffff99afffff99aULL, }, + { 0xf999999affff3333ULL, 0xffffffcdf999999aULL, }, + { 0xfffffffdffffe666ULL, 0xff99999afffffffdULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, /* 40 */ + { 0x3333333333333333ULL, 0x3333333333333333ULL, }, + { 0x000ccccd000ccccdULL, 0x000ccccd000ccccdULL, }, + { 0x0000019a0000019aULL, 0x0000019a0000019aULL, }, + { 0x0003333300033333ULL, 0x0003333300033333ULL, }, + { 0x0000066600000666ULL, 0x0000066600000666ULL, }, + { 0x066666660000cccdULL, 0x0000003306666666ULL, }, + { 0x000000030000199aULL, 0x0066666600000003ULL, }, + { 0x00000000ffffffffULL, 0x0000000000000000ULL, }, /* 48 */ + { 0xe38e38e38e38e38eULL, 0x38e38e38e38e38e3ULL, }, + { 0xfff8e38effe38e39ULL, 0x000e38e4fff8e38eULL, }, + { 0xffffff1cfffffc72ULL, 0x000001c7ffffff1cULL, }, + { 0xfffe38e4fff8e38eULL, 0x00038e39fffe38e4ULL, }, + { 0xfffffc72fffff1c7ULL, 0x0000071cfffffc72ULL, }, + { 0xfc71c71cfffe38e4ULL, 0x00000039fc71c71cULL, }, + { 0xfffffffeffffc71cULL, 0x0071c71cfffffffeULL, }, + { 0x0000000000000001ULL, 0x0000000000000000ULL, }, /* 56 */ + { 0x1c71c71c71c71c71ULL, 0xc71c71c71c71c71cULL, }, + { 0x00071c72001c71c7ULL, 0xfff1c71c00071c72ULL, }, + { 0x000000e40000038eULL, 0xfffffe39000000e4ULL, }, + { 0x0001c71c00071c72ULL, 0xfffc71c70001c71cULL, }, + { 0x0000038e00000e39ULL, 0xfffff8e40000038eULL, }, + { 0x038e38e40001c71cULL, 0xffffffc7038e38e4ULL, }, + { 0x00000002000038e4ULL, 0xff8e38e400000002ULL, }, + { 0xfff886ae28625540ULL, 0x00000001ffffe7bbULL, }, /* 64 */ + { 0xf10d5cda00286255ULL, 0x0000001300000000ULL, }, + { 0xffe21aba28625540ULL, 0x00000001ffffffe8ULL, }, + { 0xfffc43570000a189ULL, 0x0000004bfe7bb00cULL, }, + { 0xffffbbe04d93c708ULL, 0x00000000000153f5ULL, }, + { 0xff77c00c004d93c7ULL, 0x0000000500000001ULL, }, + { 0xfffeef804d93c708ULL, 0x0000000000000154ULL, }, + { 0xffffddf00001364fULL, 0x00000013153f52fcULL, }, + { 0xfffac5abb9cf8b80ULL, 0x00000001fffab2b2ULL, }, /* 72 */ + { 0xf58b55d5ffb9cf8cULL, 0x0000000afffffffbULL, }, + { 0xffeb16acb9cf8b80ULL, 0x00000000fffffab3ULL, }, + { 0xfffd62d5fffee73eULL, 0x00000028ab2b2514ULL, }, + { 0x000704f15e31e24eULL, 0xfffffffefffa942eULL, }, + { 0x0e09e2ca005e31e2ULL, 0xffffffe3fffffffbULL, }, + { 0x001c13c65e31e24eULL, 0xfffffffffffffa94ULL, }, + { 0x00038279000178c8ULL, 0xffffff8ea942e2a0ULL, }, + }; + + reset_msa_registers(); + + gettimeofday(&start, NULL); + + for (i = 0; i < PATTERN_INPUTS_SHORT_COUNT; i++) { + for (j = 0; j < PATTERN_INPUTS_SHORT_COUNT; j++) { + do_msa_SRAR_W(b128_pattern[i], b128_pattern[j], + b128_result[PATTERN_INPUTS_SHORT_COUNT * i + j]); + } + } + + for (i = 0; i < RANDOM_INPUTS_SHORT_COUNT; i++) { + for (j = 0; j < RANDOM_INPUTS_SHORT_COUNT; j++) { + do_msa_SRAR_W(b128_random[i], b128_random[j], + b128_result[((PATTERN_INPUTS_SHORT_COUNT) * + (PATTERN_INPUTS_SHORT_COUNT)) + + RANDOM_INPUTS_SHORT_COUNT * i + j]); + } + } + + gettimeofday(&end, NULL); + + elapsed_time = (end.tv_sec - start.tv_sec) * 1000.0; + elapsed_time += (end.tv_usec - start.tv_usec) / 1000.0; + + ret = check_results(instruction_name, TEST_COUNT_TOTAL, elapsed_time, + &b128_result[0][0], &b128_expect[0][0]); + + return ret; +} diff --git a/tests/tcg/mips/user/ase/msa/shift/test_msa_srl_b.c b/tests/tcg/mips/user/ase/msa/shift/test_msa_srl_b.c new file mode 100644 index 0000000000..e0d460bc00 --- /dev/null +++ b/tests/tcg/mips/user/ase/msa/shift/test_msa_srl_b.c @@ -0,0 +1,155 @@ +/* + * Test program for MSA instruction SRL.B + * + * Copyright (C) 2019 Wave Computing, Inc. + * Copyright (C) 2019 Aleksandar Markovic <amarkovic@wavecomp.com> + * + * This program 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, see <https://www.gnu.org/licenses/>. + * + */ + +#include <sys/time.h> +#include <stdint.h> + +#include "../../../../include/wrappers_msa.h" +#include "../../../../include/test_inputs_128.h" +#include "../../../../include/test_utils_128.h" + +#define TEST_COUNT_TOTAL ( \ + (PATTERN_INPUTS_SHORT_COUNT) * (PATTERN_INPUTS_SHORT_COUNT) + \ + (RANDOM_INPUTS_SHORT_COUNT) * (RANDOM_INPUTS_SHORT_COUNT)) + + +int32_t main(void) +{ + char *instruction_name = "SRL.B"; + int32_t ret; + uint32_t i, j; + struct timeval start, end; + double elapsed_time; + + uint64_t b128_result[TEST_COUNT_TOTAL][2]; + uint64_t b128_expect[TEST_COUNT_TOTAL][2] = { + { 0x0101010101010101ULL, 0x0101010101010101ULL, }, /* 0 */ + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, + { 0x3f3f3f3f3f3f3f3fULL, 0x3f3f3f3f3f3f3f3fULL, }, + { 0x0707070707070707ULL, 0x0707070707070707ULL, }, + { 0x0f0f0f0f0f0f0f0fULL, 0x0f0f0f0f0f0f0f0fULL, }, + { 0x1f1f1f1f1f1f1f1fULL, 0x1f1f1f1f1f1f1f1fULL, }, + { 0x1f03ff1f03ff1f03ULL, 0xff1f03ff1f03ff1fULL, }, + { 0x0f7f010f7f010f7fULL, 0x010f7f010f7f010fULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, /* 8 */ + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0101010101010101ULL, 0x0101010101010101ULL, }, /* 16 */ + { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, }, + { 0x2a2a2a2a2a2a2a2aULL, 0x2a2a2a2a2a2a2a2aULL, }, + { 0x0505050505050505ULL, 0x0505050505050505ULL, }, + { 0x0a0a0a0a0a0a0a0aULL, 0x0a0a0a0a0a0a0a0aULL, }, + { 0x1515151515151515ULL, 0x1515151515151515ULL, }, + { 0x1502aa1502aa1502ULL, 0xaa1502aa1502aa15ULL, }, + { 0x0a55010a55010a55ULL, 0x010a55010a55010aULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, /* 24 */ + { 0x5555555555555555ULL, 0x5555555555555555ULL, }, + { 0x1515151515151515ULL, 0x1515151515151515ULL, }, + { 0x0202020202020202ULL, 0x0202020202020202ULL, }, + { 0x0505050505050505ULL, 0x0505050505050505ULL, }, + { 0x0a0a0a0a0a0a0a0aULL, 0x0a0a0a0a0a0a0a0aULL, }, + { 0x0a01550a01550a01ULL, 0x550a01550a01550aULL, }, + { 0x052a00052a00052aULL, 0x00052a00052a0005ULL, }, + { 0x0101010101010101ULL, 0x0101010101010101ULL, }, /* 32 */ + { 0xccccccccccccccccULL, 0xccccccccccccccccULL, }, + { 0x3333333333333333ULL, 0x3333333333333333ULL, }, + { 0x0606060606060606ULL, 0x0606060606060606ULL, }, + { 0x0c0c0c0c0c0c0c0cULL, 0x0c0c0c0c0c0c0c0cULL, }, + { 0x1919191919191919ULL, 0x1919191919191919ULL, }, + { 0x1903cc1903cc1903ULL, 0xcc1903cc1903cc19ULL, }, + { 0x0c66010c66010c66ULL, 0x010c66010c66010cULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, /* 40 */ + { 0x3333333333333333ULL, 0x3333333333333333ULL, }, + { 0x0c0c0c0c0c0c0c0cULL, 0x0c0c0c0c0c0c0c0cULL, }, + { 0x0101010101010101ULL, 0x0101010101010101ULL, }, + { 0x0303030303030303ULL, 0x0303030303030303ULL, }, + { 0x0606060606060606ULL, 0x0606060606060606ULL, }, + { 0x0600330600330600ULL, 0x3306003306003306ULL, }, + { 0x0319000319000319ULL, 0x0003190003190003ULL, }, + { 0x0101000101000101ULL, 0x0001010001010001ULL, }, /* 48 */ + { 0xe38e38e38e38e38eULL, 0x38e38e38e38e38e3ULL, }, + { 0x38230e38230e3823ULL, 0x0e38230e38230e38ULL, }, + { 0x0704010704010704ULL, 0x0107040107040107ULL, }, + { 0x0e08030e08030e08ULL, 0x030e08030e08030eULL, }, + { 0x1c11071c11071c11ULL, 0x071c11071c11071cULL, }, + { 0x1c02381c02381c02ULL, 0x381c02381c02381cULL, }, + { 0x0e47000e47000e47ULL, 0x000e47000e47000eULL, }, + { 0x0000010000010000ULL, 0x0100000100000100ULL, }, /* 56 */ + { 0x1c71c71c71c71c71ULL, 0xc71c71c71c71c71cULL, }, + { 0x071c31071c31071cULL, 0x31071c31071c3107ULL, }, + { 0x0003060003060003ULL, 0x0600030600030600ULL, }, + { 0x01070c01070c0107ULL, 0x0c01070c01070c01ULL, }, + { 0x030e18030e18030eULL, 0x18030e18030e1803ULL, }, + { 0x0301c70301c70301ULL, 0xc70301c70301c703ULL, }, + { 0x0138010138010138ULL, 0x0101380101380101ULL, }, + { 0x881a030c28180240ULL, 0x09000101030fb000ULL, }, /* 64 */ + { 0x1101e619010c0040ULL, 0x1200011707002c00ULL, }, + { 0x081a033314000a40ULL, 0x006700001f0f0500ULL, }, + { 0x8800030600311501ULL, 0x02330b5e7f1e2c0cULL, }, + { 0xfb2f00064d240608ULL, 0x020117000007520fULL, }, + { 0x1f02000c02120108ULL, 0x040117060000140fULL, }, + { 0x0f2f001826011808ULL, 0x00f702000207020fULL, }, + { 0xfb01000301493100ULL, 0x007bbb1a0a0f14fcULL, }, + { 0xac16020ab9330480ULL, 0x0401180302052501ULL, }, /* 72 */ + { 0x1501ae1505190180ULL, 0x0901183f05000901ULL, }, + { 0x0a16022a5c011180ULL, 0x00d8030115050101ULL, }, + { 0xac00020502672202ULL, 0x016cc6ff550a0914ULL, }, + { 0x701300045e0c074eULL, 0x110111030208e20aULL, }, + { 0x0e0116090206014eULL, 0x230111360500380aULL, }, + { 0x071300132f001c4eULL, 0x01f102011508070aULL, }, + { 0x7000000201183801ULL, 0x047888d8541038a0ULL, }, + }; + + reset_msa_registers(); + + gettimeofday(&start, NULL); + + for (i = 0; i < PATTERN_INPUTS_SHORT_COUNT; i++) { + for (j = 0; j < PATTERN_INPUTS_SHORT_COUNT; j++) { + do_msa_SRL_B(b128_pattern[i], b128_pattern[j], + b128_result[PATTERN_INPUTS_SHORT_COUNT * i + j]); + } + } + + for (i = 0; i < RANDOM_INPUTS_SHORT_COUNT; i++) { + for (j = 0; j < RANDOM_INPUTS_SHORT_COUNT; j++) { + do_msa_SRL_B(b128_random[i], b128_random[j], + b128_result[((PATTERN_INPUTS_SHORT_COUNT) * + (PATTERN_INPUTS_SHORT_COUNT)) + + RANDOM_INPUTS_SHORT_COUNT * i + j]); + } + } + + gettimeofday(&end, NULL); + + elapsed_time = (end.tv_sec - start.tv_sec) * 1000.0; + elapsed_time += (end.tv_usec - start.tv_usec) / 1000.0; + + ret = check_results(instruction_name, TEST_COUNT_TOTAL, elapsed_time, + &b128_result[0][0], &b128_expect[0][0]); + + return ret; +} diff --git a/tests/tcg/mips/user/ase/msa/shift/test_msa_srl_d.c b/tests/tcg/mips/user/ase/msa/shift/test_msa_srl_d.c new file mode 100644 index 0000000000..e4b88a3cc4 --- /dev/null +++ b/tests/tcg/mips/user/ase/msa/shift/test_msa_srl_d.c @@ -0,0 +1,155 @@ +/* + * Test program for MSA instruction SRL.D + * + * Copyright (C) 2019 Wave Computing, Inc. + * Copyright (C) 2019 Aleksandar Markovic <amarkovic@wavecomp.com> + * + * This program 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, see <https://www.gnu.org/licenses/>. + * + */ + +#include <sys/time.h> +#include <stdint.h> + +#include "../../../../include/wrappers_msa.h" +#include "../../../../include/test_inputs_128.h" +#include "../../../../include/test_utils_128.h" + +#define TEST_COUNT_TOTAL ( \ + (PATTERN_INPUTS_SHORT_COUNT) * (PATTERN_INPUTS_SHORT_COUNT) + \ + (RANDOM_INPUTS_SHORT_COUNT) * (RANDOM_INPUTS_SHORT_COUNT)) + + +int32_t main(void) +{ + char *instruction_name = "SRL.D"; + int32_t ret; + uint32_t i, j; + struct timeval start, end; + double elapsed_time; + + uint64_t b128_result[TEST_COUNT_TOTAL][2]; + uint64_t b128_expect[TEST_COUNT_TOTAL][2] = { + { 0x0000000000000001ULL, 0x0000000000000001ULL, }, /* 0 */ + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, + { 0x00000000003fffffULL, 0x00000000003fffffULL, }, + { 0x000007ffffffffffULL, 0x000007ffffffffffULL, }, + { 0x000fffffffffffffULL, 0x000fffffffffffffULL, }, + { 0x0000000000001fffULL, 0x0000000000001fffULL, }, + { 0x0003ffffffffffffULL, 0x000000001fffffffULL, }, + { 0x0000000000007fffULL, 0x0000000fffffffffULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, /* 8 */ + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000001ULL, 0x0000000000000001ULL, }, /* 16 */ + { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, }, + { 0x00000000002aaaaaULL, 0x00000000002aaaaaULL, }, + { 0x0000055555555555ULL, 0x0000055555555555ULL, }, + { 0x000aaaaaaaaaaaaaULL, 0x000aaaaaaaaaaaaaULL, }, + { 0x0000000000001555ULL, 0x0000000000001555ULL, }, + { 0x0002aaaaaaaaaaaaULL, 0x0000000015555555ULL, }, + { 0x0000000000005555ULL, 0x0000000aaaaaaaaaULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, /* 24 */ + { 0x5555555555555555ULL, 0x5555555555555555ULL, }, + { 0x0000000000155555ULL, 0x0000000000155555ULL, }, + { 0x000002aaaaaaaaaaULL, 0x000002aaaaaaaaaaULL, }, + { 0x0005555555555555ULL, 0x0005555555555555ULL, }, + { 0x0000000000000aaaULL, 0x0000000000000aaaULL, }, + { 0x0001555555555555ULL, 0x000000000aaaaaaaULL, }, + { 0x0000000000002aaaULL, 0x0000000555555555ULL, }, + { 0x0000000000000001ULL, 0x0000000000000001ULL, }, /* 32 */ + { 0xccccccccccccccccULL, 0xccccccccccccccccULL, }, + { 0x0000000000333333ULL, 0x0000000000333333ULL, }, + { 0x0000066666666666ULL, 0x0000066666666666ULL, }, + { 0x000cccccccccccccULL, 0x000cccccccccccccULL, }, + { 0x0000000000001999ULL, 0x0000000000001999ULL, }, + { 0x0003333333333333ULL, 0x0000000019999999ULL, }, + { 0x0000000000006666ULL, 0x0000000cccccccccULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, /* 40 */ + { 0x3333333333333333ULL, 0x3333333333333333ULL, }, + { 0x00000000000cccccULL, 0x00000000000cccccULL, }, + { 0x0000019999999999ULL, 0x0000019999999999ULL, }, + { 0x0003333333333333ULL, 0x0003333333333333ULL, }, + { 0x0000000000000666ULL, 0x0000000000000666ULL, }, + { 0x0000ccccccccccccULL, 0x0000000006666666ULL, }, + { 0x0000000000001999ULL, 0x0000000333333333ULL, }, + { 0x0000000000000001ULL, 0x0000000000000000ULL, }, /* 48 */ + { 0xe38e38e38e38e38eULL, 0x38e38e38e38e38e3ULL, }, + { 0x000000000038e38eULL, 0x00000000000e38e3ULL, }, + { 0x0000071c71c71c71ULL, 0x000001c71c71c71cULL, }, + { 0x000e38e38e38e38eULL, 0x00038e38e38e38e3ULL, }, + { 0x0000000000001c71ULL, 0x000000000000071cULL, }, + { 0x00038e38e38e38e3ULL, 0x00000000071c71c7ULL, }, + { 0x00000000000071c7ULL, 0x000000038e38e38eULL, }, + { 0x0000000000000000ULL, 0x0000000000000001ULL, }, /* 56 */ + { 0x1c71c71c71c71c71ULL, 0xc71c71c71c71c71cULL, }, + { 0x0000000000071c71ULL, 0x000000000031c71cULL, }, + { 0x000000e38e38e38eULL, 0x00000638e38e38e3ULL, }, + { 0x0001c71c71c71c71ULL, 0x000c71c71c71c71cULL, }, + { 0x000000000000038eULL, 0x00000000000018e3ULL, }, + { 0x000071c71c71c71cULL, 0x0000000018e38e38ULL, }, + { 0x0000000000000e38ULL, 0x0000000c71c71c71ULL, }, + { 0x886ae6cc28625540ULL, 0x0004b670b5efe7bbULL, }, /* 64 */ + { 0x00886ae6cc286255ULL, 0x0000000000000004ULL, }, + { 0x886ae6cc28625540ULL, 0x000004b670b5efe7ULL, }, + { 0x000221ab9b30a189ULL, 0x000000004b670b5eULL, }, + { 0xfbbe00634d93c708ULL, 0x00012f7bb1a153f5ULL, }, + { 0x00fbbe00634d93c7ULL, 0x0000000000000001ULL, }, + { 0xfbbe00634d93c708ULL, 0x0000012f7bb1a153ULL, }, + { 0x0003eef8018d364fULL, 0x0000000012f7bb1aULL, }, + { 0xac5aaeaab9cf8b80ULL, 0x00027d8c6ffab2b2ULL, }, /* 72 */ + { 0x00ac5aaeaab9cf8bULL, 0x0000000000000002ULL, }, + { 0xac5aaeaab9cf8b80ULL, 0x0000027d8c6ffab2ULL, }, + { 0x0002b16abaaae73eULL, 0x0000000027d8c6ffULL, }, + { 0x704f164d5e31e24eULL, 0x0008df188d8a942eULL, }, + { 0x00704f164d5e31e2ULL, 0x0000000000000008ULL, }, + { 0x704f164d5e31e24eULL, 0x000008df188d8a94ULL, }, + { 0x0001c13c593578c7ULL, 0x000000008df188d8ULL, }, + }; + + reset_msa_registers(); + + gettimeofday(&start, NULL); + + for (i = 0; i < PATTERN_INPUTS_SHORT_COUNT; i++) { + for (j = 0; j < PATTERN_INPUTS_SHORT_COUNT; j++) { + do_msa_SRL_D(b128_pattern[i], b128_pattern[j], + b128_result[PATTERN_INPUTS_SHORT_COUNT * i + j]); + } + } + + for (i = 0; i < RANDOM_INPUTS_SHORT_COUNT; i++) { + for (j = 0; j < RANDOM_INPUTS_SHORT_COUNT; j++) { + do_msa_SRL_D(b128_random[i], b128_random[j], + b128_result[((PATTERN_INPUTS_SHORT_COUNT) * + (PATTERN_INPUTS_SHORT_COUNT)) + + RANDOM_INPUTS_SHORT_COUNT * i + j]); + } + } + + gettimeofday(&end, NULL); + + elapsed_time = (end.tv_sec - start.tv_sec) * 1000.0; + elapsed_time += (end.tv_usec - start.tv_usec) / 1000.0; + + ret = check_results(instruction_name, TEST_COUNT_TOTAL, elapsed_time, + &b128_result[0][0], &b128_expect[0][0]); + + return ret; +} diff --git a/tests/tcg/mips/user/ase/msa/shift/test_msa_srl_h.c b/tests/tcg/mips/user/ase/msa/shift/test_msa_srl_h.c new file mode 100644 index 0000000000..1eb64403c2 --- /dev/null +++ b/tests/tcg/mips/user/ase/msa/shift/test_msa_srl_h.c @@ -0,0 +1,155 @@ +/* + * Test program for MSA instruction SRL.H + * + * Copyright (C) 2019 Wave Computing, Inc. + * Copyright (C) 2019 Aleksandar Markovic <amarkovic@wavecomp.com> + * + * This program 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, see <https://www.gnu.org/licenses/>. + * + */ + +#include <sys/time.h> +#include <stdint.h> + +#include "../../../../include/wrappers_msa.h" +#include "../../../../include/test_inputs_128.h" +#include "../../../../include/test_utils_128.h" + +#define TEST_COUNT_TOTAL ( \ + (PATTERN_INPUTS_SHORT_COUNT) * (PATTERN_INPUTS_SHORT_COUNT) + \ + (RANDOM_INPUTS_SHORT_COUNT) * (RANDOM_INPUTS_SHORT_COUNT)) + + +int32_t main(void) +{ + char *instruction_name = "SRL.H"; + int32_t ret; + uint32_t i, j; + struct timeval start, end; + double elapsed_time; + + uint64_t b128_result[TEST_COUNT_TOTAL][2]; + uint64_t b128_expect[TEST_COUNT_TOTAL][2] = { + { 0x0001000100010001ULL, 0x0001000100010001ULL, }, /* 0 */ + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, + { 0x003f003f003f003fULL, 0x003f003f003f003fULL, }, + { 0x07ff07ff07ff07ffULL, 0x07ff07ff07ff07ffULL, }, + { 0x000f000f000f000fULL, 0x000f000f000f000fULL, }, + { 0x1fff1fff1fff1fffULL, 0x1fff1fff1fff1fffULL, }, + { 0x00031fff00ff0003ULL, 0x1fff00ff00031fffULL, }, + { 0x7fff000f01ff7fffULL, 0x000f01ff7fff000fULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, /* 8 */ + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0001000100010001ULL, 0x0001000100010001ULL, }, /* 16 */ + { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, }, + { 0x002a002a002a002aULL, 0x002a002a002a002aULL, }, + { 0x0555055505550555ULL, 0x0555055505550555ULL, }, + { 0x000a000a000a000aULL, 0x000a000a000a000aULL, }, + { 0x1555155515551555ULL, 0x1555155515551555ULL, }, + { 0x0002155500aa0002ULL, 0x155500aa00021555ULL, }, + { 0x5555000a01555555ULL, 0x000a01555555000aULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, /* 24 */ + { 0x5555555555555555ULL, 0x5555555555555555ULL, }, + { 0x0015001500150015ULL, 0x0015001500150015ULL, }, + { 0x02aa02aa02aa02aaULL, 0x02aa02aa02aa02aaULL, }, + { 0x0005000500050005ULL, 0x0005000500050005ULL, }, + { 0x0aaa0aaa0aaa0aaaULL, 0x0aaa0aaa0aaa0aaaULL, }, + { 0x00010aaa00550001ULL, 0x0aaa005500010aaaULL, }, + { 0x2aaa000500aa2aaaULL, 0x000500aa2aaa0005ULL, }, + { 0x0001000100010001ULL, 0x0001000100010001ULL, }, /* 32 */ + { 0xccccccccccccccccULL, 0xccccccccccccccccULL, }, + { 0x0033003300330033ULL, 0x0033003300330033ULL, }, + { 0x0666066606660666ULL, 0x0666066606660666ULL, }, + { 0x000c000c000c000cULL, 0x000c000c000c000cULL, }, + { 0x1999199919991999ULL, 0x1999199919991999ULL, }, + { 0x0003199900cc0003ULL, 0x199900cc00031999ULL, }, + { 0x6666000c01996666ULL, 0x000c01996666000cULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, /* 40 */ + { 0x3333333333333333ULL, 0x3333333333333333ULL, }, + { 0x000c000c000c000cULL, 0x000c000c000c000cULL, }, + { 0x0199019901990199ULL, 0x0199019901990199ULL, }, + { 0x0003000300030003ULL, 0x0003000300030003ULL, }, + { 0x0666066606660666ULL, 0x0666066606660666ULL, }, + { 0x0000066600330000ULL, 0x0666003300000666ULL, }, + { 0x1999000300661999ULL, 0x0003006619990003ULL, }, + { 0x0001000000010001ULL, 0x0000000100010000ULL, }, /* 48 */ + { 0xe38e38e38e38e38eULL, 0x38e38e38e38e38e3ULL, }, + { 0x0038000e00230038ULL, 0x000e00230038000eULL, }, + { 0x071c01c70471071cULL, 0x01c70471071c01c7ULL, }, + { 0x000e00030008000eULL, 0x00030008000e0003ULL, }, + { 0x1c71071c11c71c71ULL, 0x071c11c71c71071cULL, }, + { 0x0003071c008e0003ULL, 0x071c008e0003071cULL, }, + { 0x71c70003011c71c7ULL, 0x0003011c71c70003ULL, }, + { 0x0000000100000000ULL, 0x0001000000000001ULL, }, /* 56 */ + { 0x1c71c71c71c71c71ULL, 0xc71c71c71c71c71cULL, }, + { 0x00070031001c0007ULL, 0x0031001c00070031ULL, }, + { 0x00e30638038e00e3ULL, 0x0638038e00e30638ULL, }, + { 0x0001000c00070001ULL, 0x000c00070001000cULL, }, + { 0x038e18e30e38038eULL, 0x18e30e38038e18e3ULL, }, + { 0x000018e300710000ULL, 0x18e30071000018e3ULL, }, + { 0x0e38000c00e30e38ULL, 0x000c00e30e38000cULL, }, + { 0x0022000e0a185540ULL, 0x00960000001f000bULL, }, /* 64 */ + { 0x00021cd9050c0055ULL, 0x009600020001000bULL, }, + { 0x0022003900005540ULL, 0x004b0000001f0b00ULL, }, + { 0x0001000714310001ULL, 0x25b3000b3f9eb00cULL, }, + { 0x003e00001364c708ULL, 0x0025000200020005ULL, }, + { 0x0003000c09b200c7ULL, 0x0025002e00000005ULL, }, + { 0x003e00000000c708ULL, 0x001200010002052fULL, }, + { 0x0001000026c90003ULL, 0x097b00bb054f52fcULL, }, + { 0x002b000a2e738b80ULL, 0x004f000300150002ULL, }, /* 72 */ + { 0x000215d51739008bULL, 0x004f003100010002ULL, }, + { 0x002b002b00018b80ULL, 0x0027000100150251ULL, }, + { 0x000100055ce70002ULL, 0x13ec00c62aca2514ULL, }, + { 0x001c0001178ce24eULL, 0x011b00020015000eULL, }, + { 0x000102c90bc600e2ULL, 0x011b00220001000eULL, }, + { 0x001c00050000e24eULL, 0x008d000100150e2aULL, }, + { 0x000000002f180003ULL, 0x46f800882a50e2a0ULL, }, + }; + + reset_msa_registers(); + + gettimeofday(&start, NULL); + + for (i = 0; i < PATTERN_INPUTS_SHORT_COUNT; i++) { + for (j = 0; j < PATTERN_INPUTS_SHORT_COUNT; j++) { + do_msa_SRL_H(b128_pattern[i], b128_pattern[j], + b128_result[PATTERN_INPUTS_SHORT_COUNT * i + j]); + } + } + + for (i = 0; i < RANDOM_INPUTS_SHORT_COUNT; i++) { + for (j = 0; j < RANDOM_INPUTS_SHORT_COUNT; j++) { + do_msa_SRL_H(b128_random[i], b128_random[j], + b128_result[((PATTERN_INPUTS_SHORT_COUNT) * + (PATTERN_INPUTS_SHORT_COUNT)) + + RANDOM_INPUTS_SHORT_COUNT * i + j]); + } + } + + gettimeofday(&end, NULL); + + elapsed_time = (end.tv_sec - start.tv_sec) * 1000.0; + elapsed_time += (end.tv_usec - start.tv_usec) / 1000.0; + + ret = check_results(instruction_name, TEST_COUNT_TOTAL, elapsed_time, + &b128_result[0][0], &b128_expect[0][0]); + + return ret; +} diff --git a/tests/tcg/mips/user/ase/msa/shift/test_msa_srl_w.c b/tests/tcg/mips/user/ase/msa/shift/test_msa_srl_w.c new file mode 100644 index 0000000000..794833cc15 --- /dev/null +++ b/tests/tcg/mips/user/ase/msa/shift/test_msa_srl_w.c @@ -0,0 +1,155 @@ +/* + * Test program for MSA instruction SRL.W + * + * Copyright (C) 2019 Wave Computing, Inc. + * Copyright (C) 2019 Aleksandar Markovic <amarkovic@wavecomp.com> + * + * This program 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, see <https://www.gnu.org/licenses/>. + * + */ + +#include <sys/time.h> +#include <stdint.h> + +#include "../../../../include/wrappers_msa.h" +#include "../../../../include/test_inputs_128.h" +#include "../../../../include/test_utils_128.h" + +#define TEST_COUNT_TOTAL ( \ + (PATTERN_INPUTS_SHORT_COUNT) * (PATTERN_INPUTS_SHORT_COUNT) + \ + (RANDOM_INPUTS_SHORT_COUNT) * (RANDOM_INPUTS_SHORT_COUNT)) + + +int32_t main(void) +{ + char *instruction_name = "SRL.W"; + int32_t ret; + uint32_t i, j; + struct timeval start, end; + double elapsed_time; + + uint64_t b128_result[TEST_COUNT_TOTAL][2]; + uint64_t b128_expect[TEST_COUNT_TOTAL][2] = { + { 0x0000000100000001ULL, 0x0000000100000001ULL, }, /* 0 */ + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, + { 0x003fffff003fffffULL, 0x003fffff003fffffULL, }, + { 0x000007ff000007ffULL, 0x000007ff000007ffULL, }, + { 0x000fffff000fffffULL, 0x000fffff000fffffULL, }, + { 0x00001fff00001fffULL, 0x00001fff00001fffULL, }, + { 0x1fffffff0003ffffULL, 0x000000ff1fffffffULL, }, + { 0x0000000f00007fffULL, 0x01ffffff0000000fULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, /* 8 */ + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000100000001ULL, 0x0000000100000001ULL, }, /* 16 */ + { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, }, + { 0x002aaaaa002aaaaaULL, 0x002aaaaa002aaaaaULL, }, + { 0x0000055500000555ULL, 0x0000055500000555ULL, }, + { 0x000aaaaa000aaaaaULL, 0x000aaaaa000aaaaaULL, }, + { 0x0000155500001555ULL, 0x0000155500001555ULL, }, + { 0x155555550002aaaaULL, 0x000000aa15555555ULL, }, + { 0x0000000a00005555ULL, 0x015555550000000aULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, /* 24 */ + { 0x5555555555555555ULL, 0x5555555555555555ULL, }, + { 0x0015555500155555ULL, 0x0015555500155555ULL, }, + { 0x000002aa000002aaULL, 0x000002aa000002aaULL, }, + { 0x0005555500055555ULL, 0x0005555500055555ULL, }, + { 0x00000aaa00000aaaULL, 0x00000aaa00000aaaULL, }, + { 0x0aaaaaaa00015555ULL, 0x000000550aaaaaaaULL, }, + { 0x0000000500002aaaULL, 0x00aaaaaa00000005ULL, }, + { 0x0000000100000001ULL, 0x0000000100000001ULL, }, /* 32 */ + { 0xccccccccccccccccULL, 0xccccccccccccccccULL, }, + { 0x0033333300333333ULL, 0x0033333300333333ULL, }, + { 0x0000066600000666ULL, 0x0000066600000666ULL, }, + { 0x000ccccc000cccccULL, 0x000ccccc000cccccULL, }, + { 0x0000199900001999ULL, 0x0000199900001999ULL, }, + { 0x1999999900033333ULL, 0x000000cc19999999ULL, }, + { 0x0000000c00006666ULL, 0x019999990000000cULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, /* 40 */ + { 0x3333333333333333ULL, 0x3333333333333333ULL, }, + { 0x000ccccc000cccccULL, 0x000ccccc000cccccULL, }, + { 0x0000019900000199ULL, 0x0000019900000199ULL, }, + { 0x0003333300033333ULL, 0x0003333300033333ULL, }, + { 0x0000066600000666ULL, 0x0000066600000666ULL, }, + { 0x066666660000ccccULL, 0x0000003306666666ULL, }, + { 0x0000000300001999ULL, 0x0066666600000003ULL, }, + { 0x0000000100000001ULL, 0x0000000000000001ULL, }, /* 48 */ + { 0xe38e38e38e38e38eULL, 0x38e38e38e38e38e3ULL, }, + { 0x0038e38e00238e38ULL, 0x000e38e30038e38eULL, }, + { 0x0000071c00000471ULL, 0x000001c70000071cULL, }, + { 0x000e38e30008e38eULL, 0x00038e38000e38e3ULL, }, + { 0x00001c71000011c7ULL, 0x0000071c00001c71ULL, }, + { 0x1c71c71c000238e3ULL, 0x000000381c71c71cULL, }, + { 0x0000000e0000471cULL, 0x0071c71c0000000eULL, }, + { 0x0000000000000000ULL, 0x0000000100000000ULL, }, /* 56 */ + { 0x1c71c71c71c71c71ULL, 0xc71c71c71c71c71cULL, }, + { 0x00071c71001c71c7ULL, 0x0031c71c00071c71ULL, }, + { 0x000000e30000038eULL, 0x00000638000000e3ULL, }, + { 0x0001c71c00071c71ULL, 0x000c71c70001c71cULL, }, + { 0x0000038e00000e38ULL, 0x000018e30000038eULL, }, + { 0x038e38e30001c71cULL, 0x000000c7038e38e3ULL, }, + { 0x00000001000038e3ULL, 0x018e38e300000001ULL, }, + { 0x000886ae28625540ULL, 0x00000001000fe7bbULL, }, /* 64 */ + { 0x110d5cd900286255ULL, 0x000000120000000fULL, }, + { 0x00221ab928625540ULL, 0x0000000000000fe7ULL, }, + { 0x000443570000a189ULL, 0x0000004bfe7bb00cULL, }, + { 0x000fbbe04d93c708ULL, 0x00000000000153f5ULL, }, + { 0x1f77c00c004d93c7ULL, 0x0000000400000001ULL, }, + { 0x003eef804d93c708ULL, 0x0000000000000153ULL, }, + { 0x0007ddf00001364fULL, 0x00000012153f52fcULL, }, + { 0x000ac5aab9cf8b80ULL, 0x00000000000ab2b2ULL, }, /* 72 */ + { 0x158b55d500b9cf8bULL, 0x000000090000000aULL, }, + { 0x002b16abb9cf8b80ULL, 0x0000000000000ab2ULL, }, + { 0x000562d50002e73eULL, 0x00000027ab2b2514ULL, }, + { 0x000704f15e31e24eULL, 0x00000002000a942eULL, }, + { 0x0e09e2c9005e31e2ULL, 0x000000230000000aULL, }, + { 0x001c13c55e31e24eULL, 0x0000000100000a94ULL, }, + { 0x00038278000178c7ULL, 0x0000008da942e2a0ULL, }, + }; + + reset_msa_registers(); + + gettimeofday(&start, NULL); + + for (i = 0; i < PATTERN_INPUTS_SHORT_COUNT; i++) { + for (j = 0; j < PATTERN_INPUTS_SHORT_COUNT; j++) { + do_msa_SRL_W(b128_pattern[i], b128_pattern[j], + b128_result[PATTERN_INPUTS_SHORT_COUNT * i + j]); + } + } + + for (i = 0; i < RANDOM_INPUTS_SHORT_COUNT; i++) { + for (j = 0; j < RANDOM_INPUTS_SHORT_COUNT; j++) { + do_msa_SRL_W(b128_random[i], b128_random[j], + b128_result[((PATTERN_INPUTS_SHORT_COUNT) * + (PATTERN_INPUTS_SHORT_COUNT)) + + RANDOM_INPUTS_SHORT_COUNT * i + j]); + } + } + + gettimeofday(&end, NULL); + + elapsed_time = (end.tv_sec - start.tv_sec) * 1000.0; + elapsed_time += (end.tv_usec - start.tv_usec) / 1000.0; + + ret = check_results(instruction_name, TEST_COUNT_TOTAL, elapsed_time, + &b128_result[0][0], &b128_expect[0][0]); + + return ret; +} diff --git a/tests/tcg/mips/user/ase/msa/shift/test_msa_srlr_b.c b/tests/tcg/mips/user/ase/msa/shift/test_msa_srlr_b.c new file mode 100644 index 0000000000..4a900174cc --- /dev/null +++ b/tests/tcg/mips/user/ase/msa/shift/test_msa_srlr_b.c @@ -0,0 +1,155 @@ +/* + * Test program for MSA instruction SRLR.B + * + * Copyright (C) 2019 Wave Computing, Inc. + * Copyright (C) 2019 Aleksandar Markovic <amarkovic@wavecomp.com> + * + * This program 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, see <https://www.gnu.org/licenses/>. + * + */ + +#include <sys/time.h> +#include <stdint.h> + +#include "../../../../include/wrappers_msa.h" +#include "../../../../include/test_inputs_128.h" +#include "../../../../include/test_utils_128.h" + +#define TEST_COUNT_TOTAL ( \ + (PATTERN_INPUTS_SHORT_COUNT) * (PATTERN_INPUTS_SHORT_COUNT) + \ + (RANDOM_INPUTS_SHORT_COUNT) * (RANDOM_INPUTS_SHORT_COUNT)) + + +int32_t main(void) +{ + char *instruction_name = "SRLR.B"; + int32_t ret; + uint32_t i, j; + struct timeval start, end; + double elapsed_time; + + uint64_t b128_result[TEST_COUNT_TOTAL][2]; + uint64_t b128_expect[TEST_COUNT_TOTAL][2] = { + { 0x0202020202020202ULL, 0x0202020202020202ULL, }, /* 0 */ + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, + { 0x4040404040404040ULL, 0x4040404040404040ULL, }, + { 0x0808080808080808ULL, 0x0808080808080808ULL, }, + { 0x1010101010101010ULL, 0x1010101010101010ULL, }, + { 0x2020202020202020ULL, 0x2020202020202020ULL, }, + { 0x2004ff2004ff2004ULL, 0xff2004ff2004ff20ULL, }, + { 0x1080021080021080ULL, 0x0210800210800210ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, /* 8 */ + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0101010101010101ULL, 0x0101010101010101ULL, }, /* 16 */ + { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, }, + { 0x2b2b2b2b2b2b2b2bULL, 0x2b2b2b2b2b2b2b2bULL, }, + { 0x0505050505050505ULL, 0x0505050505050505ULL, }, + { 0x0b0b0b0b0b0b0b0bULL, 0x0b0b0b0b0b0b0b0bULL, }, + { 0x1515151515151515ULL, 0x1515151515151515ULL, }, + { 0x1503aa1503aa1503ULL, 0xaa1503aa1503aa15ULL, }, + { 0x0b55010b55010b55ULL, 0x010b55010b55010bULL, }, + { 0x0101010101010101ULL, 0x0101010101010101ULL, }, /* 24 */ + { 0x5555555555555555ULL, 0x5555555555555555ULL, }, + { 0x1515151515151515ULL, 0x1515151515151515ULL, }, + { 0x0303030303030303ULL, 0x0303030303030303ULL, }, + { 0x0505050505050505ULL, 0x0505050505050505ULL, }, + { 0x0b0b0b0b0b0b0b0bULL, 0x0b0b0b0b0b0b0b0bULL, }, + { 0x0b01550b01550b01ULL, 0x550b01550b01550bULL, }, + { 0x052b01052b01052bULL, 0x01052b01052b0105ULL, }, + { 0x0202020202020202ULL, 0x0202020202020202ULL, }, /* 32 */ + { 0xccccccccccccccccULL, 0xccccccccccccccccULL, }, + { 0x3333333333333333ULL, 0x3333333333333333ULL, }, + { 0x0606060606060606ULL, 0x0606060606060606ULL, }, + { 0x0d0d0d0d0d0d0d0dULL, 0x0d0d0d0d0d0d0d0dULL, }, + { 0x1a1a1a1a1a1a1a1aULL, 0x1a1a1a1a1a1a1a1aULL, }, + { 0x1a03cc1a03cc1a03ULL, 0xcc1a03cc1a03cc1aULL, }, + { 0x0d66020d66020d66ULL, 0x020d66020d66020dULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, /* 40 */ + { 0x3333333333333333ULL, 0x3333333333333333ULL, }, + { 0x0d0d0d0d0d0d0d0dULL, 0x0d0d0d0d0d0d0d0dULL, }, + { 0x0202020202020202ULL, 0x0202020202020202ULL, }, + { 0x0303030303030303ULL, 0x0303030303030303ULL, }, + { 0x0606060606060606ULL, 0x0606060606060606ULL, }, + { 0x0601330601330601ULL, 0x3306013306013306ULL, }, + { 0x031a00031a00031aULL, 0x00031a00031a0003ULL, }, + { 0x0201000201000201ULL, 0x0002010002010002ULL, }, /* 48 */ + { 0xe38e38e38e38e38eULL, 0x38e38e38e38e38e3ULL, }, + { 0x39240e39240e3924ULL, 0x0e39240e39240e39ULL, }, + { 0x0704020704020704ULL, 0x0207040207040207ULL, }, + { 0x0e09040e09040e09ULL, 0x040e09040e09040eULL, }, + { 0x1c12071c12071c12ULL, 0x071c12071c12071cULL, }, + { 0x1c02381c02381c02ULL, 0x381c02381c02381cULL, }, + { 0x0e47000e47000e47ULL, 0x000e47000e47000eULL, }, + { 0x0001020001020001ULL, 0x0200010200010200ULL, }, /* 56 */ + { 0x1c71c71c71c71c71ULL, 0xc71c71c71c71c71cULL, }, + { 0x071c32071c32071cULL, 0x32071c32071c3207ULL, }, + { 0x0104060104060104ULL, 0x0601040601040601ULL, }, + { 0x02070c02070c0207ULL, 0x0c02070c02070c02ULL, }, + { 0x040e19040e19040eULL, 0x19040e19040e1904ULL, }, + { 0x0402c70402c70402ULL, 0xc70402c70402c704ULL, }, + { 0x0239020239020239ULL, 0x0202390202390202ULL, }, + { 0x881b040d28190340ULL, 0x09010101040fb001ULL, }, /* 64 */ + { 0x1102e61a010c0140ULL, 0x1301011808012c01ULL, }, + { 0x091b043314010b40ULL, 0x01670001200f0601ULL, }, + { 0x8801040601311501ULL, 0x02340b5e7f1f2c0cULL, }, + { 0xfb3000064d250608ULL, 0x0202170000085210ULL, }, + { 0x1f03000c02120208ULL, 0x0502170701001510ULL, }, + { 0x1030001927011908ULL, 0x00f7030003080310ULL, }, + { 0xfb010003014a3200ULL, 0x017cbb1a0b1015fcULL, }, + { 0xac17030bb9340480ULL, 0x0502190403052501ULL, }, /* 72 */ + { 0x1601ae15061a0180ULL, 0x0a02194005000901ULL, }, + { 0x0b17032b5d021180ULL, 0x00d8030215050101ULL, }, + { 0xac01030503682302ULL, 0x016cc6ff560b0914ULL, }, + { 0x701400055e0c074eULL, 0x120211030308e20aULL, }, + { 0x0e01160a0306024eULL, 0x230211360501390aULL, }, + { 0x071400132f001c4eULL, 0x01f102021508070aULL, }, + { 0x7001000201193901ULL, 0x047988d8551139a0ULL, }, + }; + + reset_msa_registers(); + + gettimeofday(&start, NULL); + + for (i = 0; i < PATTERN_INPUTS_SHORT_COUNT; i++) { + for (j = 0; j < PATTERN_INPUTS_SHORT_COUNT; j++) { + do_msa_SRLR_B(b128_pattern[i], b128_pattern[j], + b128_result[PATTERN_INPUTS_SHORT_COUNT * i + j]); + } + } + + for (i = 0; i < RANDOM_INPUTS_SHORT_COUNT; i++) { + for (j = 0; j < RANDOM_INPUTS_SHORT_COUNT; j++) { + do_msa_SRLR_B(b128_random[i], b128_random[j], + b128_result[((PATTERN_INPUTS_SHORT_COUNT) * + (PATTERN_INPUTS_SHORT_COUNT)) + + RANDOM_INPUTS_SHORT_COUNT * i + j]); + } + } + + gettimeofday(&end, NULL); + + elapsed_time = (end.tv_sec - start.tv_sec) * 1000.0; + elapsed_time += (end.tv_usec - start.tv_usec) / 1000.0; + + ret = check_results(instruction_name, TEST_COUNT_TOTAL, elapsed_time, + &b128_result[0][0], &b128_expect[0][0]); + + return ret; +} diff --git a/tests/tcg/mips/user/ase/msa/shift/test_msa_srlr_d.c b/tests/tcg/mips/user/ase/msa/shift/test_msa_srlr_d.c new file mode 100644 index 0000000000..69ba01f0d9 --- /dev/null +++ b/tests/tcg/mips/user/ase/msa/shift/test_msa_srlr_d.c @@ -0,0 +1,155 @@ +/* + * Test program for MSA instruction SRLR.D + * + * Copyright (C) 2019 Wave Computing, Inc. + * Copyright (C) 2019 Aleksandar Markovic <amarkovic@wavecomp.com> + * + * This program 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, see <https://www.gnu.org/licenses/>. + * + */ + +#include <sys/time.h> +#include <stdint.h> + +#include "../../../../include/wrappers_msa.h" +#include "../../../../include/test_inputs_128.h" +#include "../../../../include/test_utils_128.h" + +#define TEST_COUNT_TOTAL ( \ + (PATTERN_INPUTS_SHORT_COUNT) * (PATTERN_INPUTS_SHORT_COUNT) + \ + (RANDOM_INPUTS_SHORT_COUNT) * (RANDOM_INPUTS_SHORT_COUNT)) + + +int32_t main(void) +{ + char *instruction_name = "SRLR.D"; + int32_t ret; + uint32_t i, j; + struct timeval start, end; + double elapsed_time; + + uint64_t b128_result[TEST_COUNT_TOTAL][2]; + uint64_t b128_expect[TEST_COUNT_TOTAL][2] = { + { 0x0000000000000002ULL, 0x0000000000000002ULL, }, /* 0 */ + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, + { 0x0000000000400000ULL, 0x0000000000400000ULL, }, + { 0x0000080000000000ULL, 0x0000080000000000ULL, }, + { 0x0010000000000000ULL, 0x0010000000000000ULL, }, + { 0x0000000000002000ULL, 0x0000000000002000ULL, }, + { 0x0004000000000000ULL, 0x0000000020000000ULL, }, + { 0x0000000000008000ULL, 0x0000001000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, /* 8 */ + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000001ULL, 0x0000000000000001ULL, }, /* 16 */ + { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, }, + { 0x00000000002aaaabULL, 0x00000000002aaaabULL, }, + { 0x0000055555555555ULL, 0x0000055555555555ULL, }, + { 0x000aaaaaaaaaaaabULL, 0x000aaaaaaaaaaaabULL, }, + { 0x0000000000001555ULL, 0x0000000000001555ULL, }, + { 0x0002aaaaaaaaaaabULL, 0x0000000015555555ULL, }, + { 0x0000000000005555ULL, 0x0000000aaaaaaaabULL, }, + { 0x0000000000000001ULL, 0x0000000000000001ULL, }, /* 24 */ + { 0x5555555555555555ULL, 0x5555555555555555ULL, }, + { 0x0000000000155555ULL, 0x0000000000155555ULL, }, + { 0x000002aaaaaaaaabULL, 0x000002aaaaaaaaabULL, }, + { 0x0005555555555555ULL, 0x0005555555555555ULL, }, + { 0x0000000000000aabULL, 0x0000000000000aabULL, }, + { 0x0001555555555555ULL, 0x000000000aaaaaabULL, }, + { 0x0000000000002aabULL, 0x0000000555555555ULL, }, + { 0x0000000000000002ULL, 0x0000000000000002ULL, }, /* 32 */ + { 0xccccccccccccccccULL, 0xccccccccccccccccULL, }, + { 0x0000000000333333ULL, 0x0000000000333333ULL, }, + { 0x0000066666666666ULL, 0x0000066666666666ULL, }, + { 0x000ccccccccccccdULL, 0x000ccccccccccccdULL, }, + { 0x000000000000199aULL, 0x000000000000199aULL, }, + { 0x0003333333333333ULL, 0x000000001999999aULL, }, + { 0x0000000000006666ULL, 0x0000000ccccccccdULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, /* 40 */ + { 0x3333333333333333ULL, 0x3333333333333333ULL, }, + { 0x00000000000ccccdULL, 0x00000000000ccccdULL, }, + { 0x000001999999999aULL, 0x000001999999999aULL, }, + { 0x0003333333333333ULL, 0x0003333333333333ULL, }, + { 0x0000000000000666ULL, 0x0000000000000666ULL, }, + { 0x0000cccccccccccdULL, 0x0000000006666666ULL, }, + { 0x000000000000199aULL, 0x0000000333333333ULL, }, + { 0x0000000000000002ULL, 0x0000000000000000ULL, }, /* 48 */ + { 0xe38e38e38e38e38eULL, 0x38e38e38e38e38e3ULL, }, + { 0x000000000038e38eULL, 0x00000000000e38e4ULL, }, + { 0x0000071c71c71c72ULL, 0x000001c71c71c71cULL, }, + { 0x000e38e38e38e38eULL, 0x00038e38e38e38e4ULL, }, + { 0x0000000000001c72ULL, 0x000000000000071cULL, }, + { 0x00038e38e38e38e4ULL, 0x00000000071c71c7ULL, }, + { 0x00000000000071c7ULL, 0x000000038e38e38eULL, }, + { 0x0000000000000000ULL, 0x0000000000000002ULL, }, /* 56 */ + { 0x1c71c71c71c71c71ULL, 0xc71c71c71c71c71cULL, }, + { 0x0000000000071c72ULL, 0x000000000031c71cULL, }, + { 0x000000e38e38e38eULL, 0x00000638e38e38e4ULL, }, + { 0x0001c71c71c71c72ULL, 0x000c71c71c71c71cULL, }, + { 0x000000000000038eULL, 0x00000000000018e4ULL, }, + { 0x000071c71c71c71cULL, 0x0000000018e38e39ULL, }, + { 0x0000000000000e39ULL, 0x0000000c71c71c72ULL, }, + { 0x886ae6cc28625540ULL, 0x0004b670b5efe7bbULL, }, /* 64 */ + { 0x00886ae6cc286255ULL, 0x0000000000000005ULL, }, + { 0x886ae6cc28625540ULL, 0x000004b670b5efe8ULL, }, + { 0x000221ab9b30a189ULL, 0x000000004b670b5fULL, }, + { 0xfbbe00634d93c708ULL, 0x00012f7bb1a153f5ULL, }, + { 0x00fbbe00634d93c7ULL, 0x0000000000000001ULL, }, + { 0xfbbe00634d93c708ULL, 0x0000012f7bb1a154ULL, }, + { 0x0003eef8018d364fULL, 0x0000000012f7bb1aULL, }, + { 0xac5aaeaab9cf8b80ULL, 0x00027d8c6ffab2b2ULL, }, /* 72 */ + { 0x00ac5aaeaab9cf8cULL, 0x0000000000000002ULL, }, + { 0xac5aaeaab9cf8b80ULL, 0x0000027d8c6ffab3ULL, }, + { 0x0002b16abaaae73eULL, 0x0000000027d8c700ULL, }, + { 0x704f164d5e31e24eULL, 0x0008df188d8a942eULL, }, + { 0x00704f164d5e31e2ULL, 0x0000000000000009ULL, }, + { 0x704f164d5e31e24eULL, 0x000008df188d8a94ULL, }, + { 0x0001c13c593578c8ULL, 0x000000008df188d9ULL, }, + }; + + reset_msa_registers(); + + gettimeofday(&start, NULL); + + for (i = 0; i < PATTERN_INPUTS_SHORT_COUNT; i++) { + for (j = 0; j < PATTERN_INPUTS_SHORT_COUNT; j++) { + do_msa_SRLR_D(b128_pattern[i], b128_pattern[j], + b128_result[PATTERN_INPUTS_SHORT_COUNT * i + j]); + } + } + + for (i = 0; i < RANDOM_INPUTS_SHORT_COUNT; i++) { + for (j = 0; j < RANDOM_INPUTS_SHORT_COUNT; j++) { + do_msa_SRLR_D(b128_random[i], b128_random[j], + b128_result[((PATTERN_INPUTS_SHORT_COUNT) * + (PATTERN_INPUTS_SHORT_COUNT)) + + RANDOM_INPUTS_SHORT_COUNT * i + j]); + } + } + + gettimeofday(&end, NULL); + + elapsed_time = (end.tv_sec - start.tv_sec) * 1000.0; + elapsed_time += (end.tv_usec - start.tv_usec) / 1000.0; + + ret = check_results(instruction_name, TEST_COUNT_TOTAL, elapsed_time, + &b128_result[0][0], &b128_expect[0][0]); + + return ret; +} diff --git a/tests/tcg/mips/user/ase/msa/shift/test_msa_srlr_h.c b/tests/tcg/mips/user/ase/msa/shift/test_msa_srlr_h.c new file mode 100644 index 0000000000..514a143a6e --- /dev/null +++ b/tests/tcg/mips/user/ase/msa/shift/test_msa_srlr_h.c @@ -0,0 +1,155 @@ +/* + * Test program for MSA instruction SRLR.H + * + * Copyright (C) 2019 Wave Computing, Inc. + * Copyright (C) 2019 Aleksandar Markovic <amarkovic@wavecomp.com> + * + * This program 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, see <https://www.gnu.org/licenses/>. + * + */ + +#include <sys/time.h> +#include <stdint.h> + +#include "../../../../include/wrappers_msa.h" +#include "../../../../include/test_inputs_128.h" +#include "../../../../include/test_utils_128.h" + +#define TEST_COUNT_TOTAL ( \ + (PATTERN_INPUTS_SHORT_COUNT) * (PATTERN_INPUTS_SHORT_COUNT) + \ + (RANDOM_INPUTS_SHORT_COUNT) * (RANDOM_INPUTS_SHORT_COUNT)) + + +int32_t main(void) +{ + char *instruction_name = "SRLR.H"; + int32_t ret; + uint32_t i, j; + struct timeval start, end; + double elapsed_time; + + uint64_t b128_result[TEST_COUNT_TOTAL][2]; + uint64_t b128_expect[TEST_COUNT_TOTAL][2] = { + { 0x0002000200020002ULL, 0x0002000200020002ULL, }, /* 0 */ + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, + { 0x0040004000400040ULL, 0x0040004000400040ULL, }, + { 0x0800080008000800ULL, 0x0800080008000800ULL, }, + { 0x0010001000100010ULL, 0x0010001000100010ULL, }, + { 0x2000200020002000ULL, 0x2000200020002000ULL, }, + { 0x0004200001000004ULL, 0x2000010000042000ULL, }, + { 0x8000001002008000ULL, 0x0010020080000010ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, /* 8 */ + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0001000100010001ULL, 0x0001000100010001ULL, }, /* 16 */ + { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, }, + { 0x002b002b002b002bULL, 0x002b002b002b002bULL, }, + { 0x0555055505550555ULL, 0x0555055505550555ULL, }, + { 0x000b000b000b000bULL, 0x000b000b000b000bULL, }, + { 0x1555155515551555ULL, 0x1555155515551555ULL, }, + { 0x0003155500ab0003ULL, 0x155500ab00031555ULL, }, + { 0x5555000b01555555ULL, 0x000b01555555000bULL, }, + { 0x0001000100010001ULL, 0x0001000100010001ULL, }, /* 24 */ + { 0x5555555555555555ULL, 0x5555555555555555ULL, }, + { 0x0015001500150015ULL, 0x0015001500150015ULL, }, + { 0x02ab02ab02ab02abULL, 0x02ab02ab02ab02abULL, }, + { 0x0005000500050005ULL, 0x0005000500050005ULL, }, + { 0x0aab0aab0aab0aabULL, 0x0aab0aab0aab0aabULL, }, + { 0x00010aab00550001ULL, 0x0aab005500010aabULL, }, + { 0x2aab000500ab2aabULL, 0x000500ab2aab0005ULL, }, + { 0x0002000200020002ULL, 0x0002000200020002ULL, }, /* 32 */ + { 0xccccccccccccccccULL, 0xccccccccccccccccULL, }, + { 0x0033003300330033ULL, 0x0033003300330033ULL, }, + { 0x0666066606660666ULL, 0x0666066606660666ULL, }, + { 0x000d000d000d000dULL, 0x000d000d000d000dULL, }, + { 0x199a199a199a199aULL, 0x199a199a199a199aULL, }, + { 0x0003199a00cd0003ULL, 0x199a00cd0003199aULL, }, + { 0x6666000d019a6666ULL, 0x000d019a6666000dULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, /* 40 */ + { 0x3333333333333333ULL, 0x3333333333333333ULL, }, + { 0x000d000d000d000dULL, 0x000d000d000d000dULL, }, + { 0x019a019a019a019aULL, 0x019a019a019a019aULL, }, + { 0x0003000300030003ULL, 0x0003000300030003ULL, }, + { 0x0666066606660666ULL, 0x0666066606660666ULL, }, + { 0x0001066600330001ULL, 0x0666003300010666ULL, }, + { 0x199a00030066199aULL, 0x00030066199a0003ULL, }, + { 0x0002000000010002ULL, 0x0000000100020000ULL, }, /* 48 */ + { 0xe38e38e38e38e38eULL, 0x38e38e38e38e38e3ULL, }, + { 0x0039000e00240039ULL, 0x000e00240039000eULL, }, + { 0x071c01c70472071cULL, 0x01c70472071c01c7ULL, }, + { 0x000e00040009000eULL, 0x00040009000e0004ULL, }, + { 0x1c72071c11c71c72ULL, 0x071c11c71c72071cULL, }, + { 0x0004071c008e0004ULL, 0x071c008e0004071cULL, }, + { 0x71c70004011c71c7ULL, 0x0004011c71c70004ULL, }, + { 0x0000000200010000ULL, 0x0002000100000002ULL, }, /* 56 */ + { 0x1c71c71c71c71c71ULL, 0xc71c71c71c71c71cULL, }, + { 0x00070032001c0007ULL, 0x0032001c00070032ULL, }, + { 0x00e40639038e00e4ULL, 0x0639038e00e40639ULL, }, + { 0x0002000c00070002ULL, 0x000c00070002000cULL, }, + { 0x038e18e40e39038eULL, 0x18e40e39038e18e4ULL, }, + { 0x000018e400720000ULL, 0x18e40072000018e4ULL, }, + { 0x0e39000c00e40e39ULL, 0x000c00e40e39000cULL, }, + { 0x0022000e0a195540ULL, 0x009700000020000bULL, }, /* 64 */ + { 0x00021cda050c0055ULL, 0x009700030002000bULL, }, + { 0x0022003a00005540ULL, 0x004b000000200b01ULL, }, + { 0x0001000714310001ULL, 0x25b4000b3f9fb00cULL, }, + { 0x003f00001365c708ULL, 0x0026000300030005ULL, }, + { 0x0004000c09b200c7ULL, 0x0026002f00000005ULL, }, + { 0x003f00000001c708ULL, 0x0013000100030530ULL, }, + { 0x0002000026ca0003ULL, 0x097c00bb055052fcULL, }, + { 0x002b000b2e748b80ULL, 0x0050000300150002ULL, }, /* 72 */ + { 0x000315d5173a008cULL, 0x0050003200010002ULL, }, + { 0x002b002c00018b80ULL, 0x0028000200150251ULL, }, + { 0x000100055ce80002ULL, 0x13ec00c72acb2514ULL, }, + { 0x001c0001178ce24eULL, 0x011c00020015000eULL, }, + { 0x000202ca0bc600e2ULL, 0x011c00220001000eULL, }, + { 0x001c00060001e24eULL, 0x008e000100150e2aULL, }, + { 0x000100012f190004ULL, 0x46f900892a51e2a0ULL, }, + }; + + reset_msa_registers(); + + gettimeofday(&start, NULL); + + for (i = 0; i < PATTERN_INPUTS_SHORT_COUNT; i++) { + for (j = 0; j < PATTERN_INPUTS_SHORT_COUNT; j++) { + do_msa_SRLR_H(b128_pattern[i], b128_pattern[j], + b128_result[PATTERN_INPUTS_SHORT_COUNT * i + j]); + } + } + + for (i = 0; i < RANDOM_INPUTS_SHORT_COUNT; i++) { + for (j = 0; j < RANDOM_INPUTS_SHORT_COUNT; j++) { + do_msa_SRLR_H(b128_random[i], b128_random[j], + b128_result[((PATTERN_INPUTS_SHORT_COUNT) * + (PATTERN_INPUTS_SHORT_COUNT)) + + RANDOM_INPUTS_SHORT_COUNT * i + j]); + } + } + + gettimeofday(&end, NULL); + + elapsed_time = (end.tv_sec - start.tv_sec) * 1000.0; + elapsed_time += (end.tv_usec - start.tv_usec) / 1000.0; + + ret = check_results(instruction_name, TEST_COUNT_TOTAL, elapsed_time, + &b128_result[0][0], &b128_expect[0][0]); + + return ret; +} diff --git a/tests/tcg/mips/user/ase/msa/shift/test_msa_srlr_w.c b/tests/tcg/mips/user/ase/msa/shift/test_msa_srlr_w.c new file mode 100644 index 0000000000..940fd6f318 --- /dev/null +++ b/tests/tcg/mips/user/ase/msa/shift/test_msa_srlr_w.c @@ -0,0 +1,155 @@ +/* + * Test program for MSA instruction SRLR.W + * + * Copyright (C) 2019 Wave Computing, Inc. + * Copyright (C) 2019 Aleksandar Markovic <amarkovic@wavecomp.com> + * + * This program 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, see <https://www.gnu.org/licenses/>. + * + */ + +#include <sys/time.h> +#include <stdint.h> + +#include "../../../../include/wrappers_msa.h" +#include "../../../../include/test_inputs_128.h" +#include "../../../../include/test_utils_128.h" + +#define TEST_COUNT_TOTAL ( \ + (PATTERN_INPUTS_SHORT_COUNT) * (PATTERN_INPUTS_SHORT_COUNT) + \ + (RANDOM_INPUTS_SHORT_COUNT) * (RANDOM_INPUTS_SHORT_COUNT)) + + +int32_t main(void) +{ + char *instruction_name = "SRLR.W"; + int32_t ret; + uint32_t i, j; + struct timeval start, end; + double elapsed_time; + + uint64_t b128_result[TEST_COUNT_TOTAL][2]; + uint64_t b128_expect[TEST_COUNT_TOTAL][2] = { + { 0x0000000200000002ULL, 0x0000000200000002ULL, }, /* 0 */ + { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, + { 0x0040000000400000ULL, 0x0040000000400000ULL, }, + { 0x0000080000000800ULL, 0x0000080000000800ULL, }, + { 0x0010000000100000ULL, 0x0010000000100000ULL, }, + { 0x0000200000002000ULL, 0x0000200000002000ULL, }, + { 0x2000000000040000ULL, 0x0000010020000000ULL, }, + { 0x0000001000008000ULL, 0x0200000000000010ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, /* 8 */ + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, + { 0x0000000100000001ULL, 0x0000000100000001ULL, }, /* 16 */ + { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, }, + { 0x002aaaab002aaaabULL, 0x002aaaab002aaaabULL, }, + { 0x0000055500000555ULL, 0x0000055500000555ULL, }, + { 0x000aaaab000aaaabULL, 0x000aaaab000aaaabULL, }, + { 0x0000155500001555ULL, 0x0000155500001555ULL, }, + { 0x155555550002aaabULL, 0x000000ab15555555ULL, }, + { 0x0000000b00005555ULL, 0x015555550000000bULL, }, + { 0x0000000100000001ULL, 0x0000000100000001ULL, }, /* 24 */ + { 0x5555555555555555ULL, 0x5555555555555555ULL, }, + { 0x0015555500155555ULL, 0x0015555500155555ULL, }, + { 0x000002ab000002abULL, 0x000002ab000002abULL, }, + { 0x0005555500055555ULL, 0x0005555500055555ULL, }, + { 0x00000aab00000aabULL, 0x00000aab00000aabULL, }, + { 0x0aaaaaab00015555ULL, 0x000000550aaaaaabULL, }, + { 0x0000000500002aabULL, 0x00aaaaab00000005ULL, }, + { 0x0000000200000002ULL, 0x0000000200000002ULL, }, /* 32 */ + { 0xccccccccccccccccULL, 0xccccccccccccccccULL, }, + { 0x0033333300333333ULL, 0x0033333300333333ULL, }, + { 0x0000066600000666ULL, 0x0000066600000666ULL, }, + { 0x000ccccd000ccccdULL, 0x000ccccd000ccccdULL, }, + { 0x0000199a0000199aULL, 0x0000199a0000199aULL, }, + { 0x1999999a00033333ULL, 0x000000cd1999999aULL, }, + { 0x0000000d00006666ULL, 0x0199999a0000000dULL, }, + { 0x0000000000000000ULL, 0x0000000000000000ULL, }, /* 40 */ + { 0x3333333333333333ULL, 0x3333333333333333ULL, }, + { 0x000ccccd000ccccdULL, 0x000ccccd000ccccdULL, }, + { 0x0000019a0000019aULL, 0x0000019a0000019aULL, }, + { 0x0003333300033333ULL, 0x0003333300033333ULL, }, + { 0x0000066600000666ULL, 0x0000066600000666ULL, }, + { 0x066666660000cccdULL, 0x0000003306666666ULL, }, + { 0x000000030000199aULL, 0x0066666600000003ULL, }, + { 0x0000000200000001ULL, 0x0000000000000002ULL, }, /* 48 */ + { 0xe38e38e38e38e38eULL, 0x38e38e38e38e38e3ULL, }, + { 0x0038e38e00238e39ULL, 0x000e38e40038e38eULL, }, + { 0x0000071c00000472ULL, 0x000001c70000071cULL, }, + { 0x000e38e40008e38eULL, 0x00038e39000e38e4ULL, }, + { 0x00001c72000011c7ULL, 0x0000071c00001c72ULL, }, + { 0x1c71c71c000238e4ULL, 0x000000391c71c71cULL, }, + { 0x0000000e0000471cULL, 0x0071c71c0000000eULL, }, + { 0x0000000000000001ULL, 0x0000000200000000ULL, }, /* 56 */ + { 0x1c71c71c71c71c71ULL, 0xc71c71c71c71c71cULL, }, + { 0x00071c72001c71c7ULL, 0x0031c71c00071c72ULL, }, + { 0x000000e40000038eULL, 0x00000639000000e4ULL, }, + { 0x0001c71c00071c72ULL, 0x000c71c70001c71cULL, }, + { 0x0000038e00000e39ULL, 0x000018e40000038eULL, }, + { 0x038e38e40001c71cULL, 0x000000c7038e38e4ULL, }, + { 0x00000002000038e4ULL, 0x018e38e400000002ULL, }, + { 0x000886ae28625540ULL, 0x00000001000fe7bbULL, }, /* 64 */ + { 0x110d5cda00286255ULL, 0x0000001300000010ULL, }, + { 0x00221aba28625540ULL, 0x0000000100000fe8ULL, }, + { 0x000443570000a189ULL, 0x0000004bfe7bb00cULL, }, + { 0x000fbbe04d93c708ULL, 0x00000000000153f5ULL, }, + { 0x1f77c00c004d93c7ULL, 0x0000000500000001ULL, }, + { 0x003eef804d93c708ULL, 0x0000000000000154ULL, }, + { 0x0007ddf00001364fULL, 0x00000013153f52fcULL, }, + { 0x000ac5abb9cf8b80ULL, 0x00000001000ab2b2ULL, }, /* 72 */ + { 0x158b55d500b9cf8cULL, 0x0000000a0000000bULL, }, + { 0x002b16acb9cf8b80ULL, 0x0000000000000ab3ULL, }, + { 0x000562d50002e73eULL, 0x00000028ab2b2514ULL, }, + { 0x000704f15e31e24eULL, 0x00000002000a942eULL, }, + { 0x0e09e2ca005e31e2ULL, 0x000000230000000bULL, }, + { 0x001c13c65e31e24eULL, 0x0000000100000a94ULL, }, + { 0x00038279000178c8ULL, 0x0000008ea942e2a0ULL, }, + }; + + reset_msa_registers(); + + gettimeofday(&start, NULL); + + for (i = 0; i < PATTERN_INPUTS_SHORT_COUNT; i++) { + for (j = 0; j < PATTERN_INPUTS_SHORT_COUNT; j++) { + do_msa_SRLR_W(b128_pattern[i], b128_pattern[j], + b128_result[PATTERN_INPUTS_SHORT_COUNT * i + j]); + } + } + + for (i = 0; i < RANDOM_INPUTS_SHORT_COUNT; i++) { + for (j = 0; j < RANDOM_INPUTS_SHORT_COUNT; j++) { + do_msa_SRLR_W(b128_random[i], b128_random[j], + b128_result[((PATTERN_INPUTS_SHORT_COUNT) * + (PATTERN_INPUTS_SHORT_COUNT)) + + RANDOM_INPUTS_SHORT_COUNT * i + j]); + } + } + + gettimeofday(&end, NULL); + + elapsed_time = (end.tv_sec - start.tv_sec) * 1000.0; + elapsed_time += (end.tv_usec - start.tv_usec) / 1000.0; + + ret = check_results(instruction_name, TEST_COUNT_TOTAL, elapsed_time, + &b128_result[0][0], &b128_expect[0][0]); + + return ret; +} diff --git a/tests/tcg/mips/user/ase/msa/test_msa_compile.sh b/tests/tcg/mips/user/ase/msa/test_msa_compile.sh new file mode 100755 index 0000000000..2a39d892f0 --- /dev/null +++ b/tests/tcg/mips/user/ase/msa/test_msa_compile.sh @@ -0,0 +1,558 @@ + +# +# Bit Count +# --------- +# +/opt/img/bin/mips-img-linux-gnu-gcc bit-count/test_msa_nloc_b.c \ +-EL -static -mabi=64 -march=mips64r6 -mmsa -o /tmp/test_msa_nloc_b +/opt/img/bin/mips-img-linux-gnu-gcc bit-count/test_msa_nloc_h.c \ +-EL -static -mabi=64 -march=mips64r6 -mmsa -o /tmp/test_msa_nloc_h +/opt/img/bin/mips-img-linux-gnu-gcc bit-count/test_msa_nloc_w.c \ +-EL -static -mabi=64 -march=mips64r6 -mmsa -o /tmp/test_msa_nloc_w +/opt/img/bin/mips-img-linux-gnu-gcc bit-count/test_msa_nloc_d.c \ +-EL -static -mabi=64 -march=mips64r6 -mmsa -o /tmp/test_msa_nloc_d +/opt/img/bin/mips-img-linux-gnu-gcc bit-count/test_msa_nlzc_b.c \ +-EL -static -mabi=64 -march=mips64r6 -mmsa -o /tmp/test_msa_nlzc_b +/opt/img/bin/mips-img-linux-gnu-gcc bit-count/test_msa_nlzc_h.c \ +-EL -static -mabi=64 -march=mips64r6 -mmsa -o /tmp/test_msa_nlzc_h +/opt/img/bin/mips-img-linux-gnu-gcc bit-count/test_msa_nlzc_w.c \ +-EL -static -mabi=64 -march=mips64r6 -mmsa -o /tmp/test_msa_nlzc_w +/opt/img/bin/mips-img-linux-gnu-gcc bit-count/test_msa_nlzc_d.c \ +-EL -static -mabi=64 -march=mips64r6 -mmsa -o /tmp/test_msa_nlzc_d +/opt/img/bin/mips-img-linux-gnu-gcc bit-count/test_msa_pcnt_b.c \ +-EL -static -mabi=64 -march=mips64r6 -mmsa -o /tmp/test_msa_pcnt_b +/opt/img/bin/mips-img-linux-gnu-gcc bit-count/test_msa_pcnt_h.c \ +-EL -static -mabi=64 -march=mips64r6 -mmsa -o /tmp/test_msa_pcnt_h +/opt/img/bin/mips-img-linux-gnu-gcc bit-count/test_msa_pcnt_w.c \ +-EL -static -mabi=64 -march=mips64r6 -mmsa -o /tmp/test_msa_pcnt_w +/opt/img/bin/mips-img-linux-gnu-gcc bit-count/test_msa_pcnt_d.c \ +-EL -static -mabi=64 -march=mips64r6 -mmsa -o /tmp/test_msa_pcnt_d + +# +# Bit move +# -------- +# + +# +# Bit Set +# ------- +# +/opt/img/bin/mips-img-linux-gnu-gcc bit-set/test_msa_bclr_b.c \ +-EL -static -mabi=64 -march=mips64r6 -mmsa -o /tmp/test_msa_bclr_b +/opt/img/bin/mips-img-linux-gnu-gcc bit-set/test_msa_bclr_h.c \ +-EL -static -mabi=64 -march=mips64r6 -mmsa -o /tmp/test_msa_bclr_h +/opt/img/bin/mips-img-linux-gnu-gcc bit-set/test_msa_bclr_w.c \ +-EL -static -mabi=64 -march=mips64r6 -mmsa -o /tmp/test_msa_bclr_w +/opt/img/bin/mips-img-linux-gnu-gcc bit-set/test_msa_bclr_d.c \ +-EL -static -mabi=64 -march=mips64r6 -mmsa -o /tmp/test_msa_bclr_d +/opt/img/bin/mips-img-linux-gnu-gcc bit-set/test_msa_bneg_b.c \ +-EL -static -mabi=64 -march=mips64r6 -mmsa -o /tmp/test_msa_bneg_b +/opt/img/bin/mips-img-linux-gnu-gcc bit-set/test_msa_bneg_h.c \ +-EL -static -mabi=64 -march=mips64r6 -mmsa -o /tmp/test_msa_bneg_h +/opt/img/bin/mips-img-linux-gnu-gcc bit-set/test_msa_bneg_w.c \ +-EL -static -mabi=64 -march=mips64r6 -mmsa -o /tmp/test_msa_bneg_w +/opt/img/bin/mips-img-linux-gnu-gcc bit-set/test_msa_bneg_d.c \ +-EL -static -mabi=64 -march=mips64r6 -mmsa -o /tmp/test_msa_bneg_d +/opt/img/bin/mips-img-linux-gnu-gcc bit-set/test_msa_bset_b.c \ +-EL -static -mabi=64 -march=mips64r6 -mmsa -o /tmp/test_msa_bset_b +/opt/img/bin/mips-img-linux-gnu-gcc bit-set/test_msa_bset_h.c \ +-EL -static -mabi=64 -march=mips64r6 -mmsa -o /tmp/test_msa_bset_h +/opt/img/bin/mips-img-linux-gnu-gcc bit-set/test_msa_bset_w.c \ +-EL -static -mabi=64 -march=mips64r6 -mmsa -o /tmp/test_msa_bset_w +/opt/img/bin/mips-img-linux-gnu-gcc bit-set/test_msa_bset_d.c \ +-EL -static -mabi=64 -march=mips64r6 -mmsa -o /tmp/test_msa_bset_d + +# +# Fixed Multiply +# -------------- +# +/opt/img/bin/mips-img-linux-gnu-gcc fixed-multiply/test_msa_mul_q_h.c \ +-EL -static -mabi=64 -march=mips64r6 -mmsa -o /tmp/test_msa_mul_q_h +/opt/img/bin/mips-img-linux-gnu-gcc fixed-multiply/test_msa_mul_q_w.c \ +-EL -static -mabi=64 -march=mips64r6 -mmsa -o /tmp/test_msa_mul_q_w +/opt/img/bin/mips-img-linux-gnu-gcc fixed-multiply/test_msa_mulr_q_h.c \ +-EL -static -mabi=64 -march=mips64r6 -mmsa -o /tmp/test_msa_mulr_q_h +/opt/img/bin/mips-img-linux-gnu-gcc fixed-multiply/test_msa_mulr_q_w.c \ +-EL -static -mabi=64 -march=mips64r6 -mmsa -o /tmp/test_msa_mulr_q_w + +# +# Float Max Min +# ------------- +# +/opt/img/bin/mips-img-linux-gnu-gcc float-max-min/test_msa_fmax_a_w.c \ +-EL -static -mabi=64 -march=mips64r6 -mmsa -o /tmp/test_msa_fmax_a_w +/opt/img/bin/mips-img-linux-gnu-gcc float-max-min/test_msa_fmax_a_d.c \ +-EL -static -mabi=64 -march=mips64r6 -mmsa -o /tmp/test_msa_fmax_a_d +/opt/img/bin/mips-img-linux-gnu-gcc float-max-min/test_msa_fmax_w.c \ +-EL -static -mabi=64 -march=mips64r6 -mmsa -o /tmp/test_msa_fmax_w +/opt/img/bin/mips-img-linux-gnu-gcc float-max-min/test_msa_fmax_d.c \ +-EL -static -mabi=64 -march=mips64r6 -mmsa -o /tmp/test_msa_fmax_d +/opt/img/bin/mips-img-linux-gnu-gcc float-max-min/test_msa_fmin_a_w.c \ +-EL -static -mabi=64 -march=mips64r6 -mmsa -o /tmp/test_msa_fmin_a_w +/opt/img/bin/mips-img-linux-gnu-gcc float-max-min/test_msa_fmin_a_d.c \ +-EL -static -mabi=64 -march=mips64r6 -mmsa -o /tmp/test_msa_fmin_a_d +/opt/img/bin/mips-img-linux-gnu-gcc float-max-min/test_msa_fmin_w.c \ +-EL -static -mabi=64 -march=mips64r6 -mmsa -o /tmp/test_msa_fmin_w +/opt/img/bin/mips-img-linux-gnu-gcc float-max-min/test_msa_fmin_d.c \ +-EL -static -mabi=64 -march=mips64r6 -mmsa -o /tmp/test_msa_fmin_d + +# +# Int Add +# ------- +# +/opt/img/bin/mips-img-linux-gnu-gcc int-add/test_msa_add_a_b.c \ +-EL -static -mabi=64 -march=mips64r6 -mmsa -o /tmp/test_msa_add_a_b +/opt/img/bin/mips-img-linux-gnu-gcc int-add/test_msa_add_a_h.c \ +-EL -static -mabi=64 -march=mips64r6 -mmsa -o /tmp/test_msa_add_a_h +/opt/img/bin/mips-img-linux-gnu-gcc int-add/test_msa_add_a_w.c \ +-EL -static -mabi=64 -march=mips64r6 -mmsa -o /tmp/test_msa_add_a_w +/opt/img/bin/mips-img-linux-gnu-gcc int-add/test_msa_add_a_d.c \ +-EL -static -mabi=64 -march=mips64r6 -mmsa -o /tmp/test_msa_add_a_d +/opt/img/bin/mips-img-linux-gnu-gcc int-add/test_msa_adds_a_b.c \ +-EL -static -mabi=64 -march=mips64r6 -mmsa -o /tmp/test_msa_adds_a_b +/opt/img/bin/mips-img-linux-gnu-gcc int-add/test_msa_adds_a_h.c \ +-EL -static -mabi=64 -march=mips64r6 -mmsa -o /tmp/test_msa_adds_a_h +/opt/img/bin/mips-img-linux-gnu-gcc int-add/test_msa_adds_a_w.c \ +-EL -static -mabi=64 -march=mips64r6 -mmsa -o /tmp/test_msa_adds_a_w +/opt/img/bin/mips-img-linux-gnu-gcc int-add/test_msa_adds_a_d.c \ +-EL -static -mabi=64 -march=mips64r6 -mmsa -o /tmp/test_msa_adds_a_d +/opt/img/bin/mips-img-linux-gnu-gcc int-add/test_msa_adds_s_b.c \ +-EL -static -mabi=64 -march=mips64r6 -mmsa -o /tmp/test_msa_adds_s_b +/opt/img/bin/mips-img-linux-gnu-gcc int-add/test_msa_adds_s_h.c \ +-EL -static -mabi=64 -march=mips64r6 -mmsa -o /tmp/test_msa_adds_s_h +/opt/img/bin/mips-img-linux-gnu-gcc int-add/test_msa_adds_s_w.c \ +-EL -static -mabi=64 -march=mips64r6 -mmsa -o /tmp/test_msa_adds_s_w +/opt/img/bin/mips-img-linux-gnu-gcc int-add/test_msa_adds_s_d.c \ +-EL -static -mabi=64 -march=mips64r6 -mmsa -o /tmp/test_msa_adds_s_d +/opt/img/bin/mips-img-linux-gnu-gcc int-add/test_msa_adds_u_b.c \ +-EL -static -mabi=64 -march=mips64r6 -mmsa -o /tmp/test_msa_adds_u_b +/opt/img/bin/mips-img-linux-gnu-gcc int-add/test_msa_adds_u_h.c \ +-EL -static -mabi=64 -march=mips64r6 -mmsa -o /tmp/test_msa_adds_u_h +/opt/img/bin/mips-img-linux-gnu-gcc int-add/test_msa_adds_u_w.c \ +-EL -static -mabi=64 -march=mips64r6 -mmsa -o /tmp/test_msa_adds_u_w +/opt/img/bin/mips-img-linux-gnu-gcc int-add/test_msa_adds_u_d.c \ +-EL -static -mabi=64 -march=mips64r6 -mmsa -o /tmp/test_msa_adds_u_d +/opt/img/bin/mips-img-linux-gnu-gcc int-add/test_msa_addv_b.c \ +-EL -static -mabi=64 -march=mips64r6 -mmsa -o /tmp/test_msa_addv_b +/opt/img/bin/mips-img-linux-gnu-gcc int-add/test_msa_addv_h.c \ +-EL -static -mabi=64 -march=mips64r6 -mmsa -o /tmp/test_msa_addv_h +/opt/img/bin/mips-img-linux-gnu-gcc int-add/test_msa_addv_w.c \ +-EL -static -mabi=64 -march=mips64r6 -mmsa -o /tmp/test_msa_addv_w +/opt/img/bin/mips-img-linux-gnu-gcc int-add/test_msa_addv_d.c \ +-EL -static -mabi=64 -march=mips64r6 -mmsa -o /tmp/test_msa_addv_d +/opt/img/bin/mips-img-linux-gnu-gcc int-add/test_msa_hadd_s_h.c \ +-EL -static -mabi=64 -march=mips64r6 -mmsa -o /tmp/test_msa_hadd_s_h +/opt/img/bin/mips-img-linux-gnu-gcc int-add/test_msa_hadd_s_w.c \ +-EL -static -mabi=64 -march=mips64r6 -mmsa -o /tmp/test_msa_hadd_s_w +/opt/img/bin/mips-img-linux-gnu-gcc int-add/test_msa_hadd_s_d.c \ +-EL -static -mabi=64 -march=mips64r6 -mmsa -o /tmp/test_msa_hadd_s_d +/opt/img/bin/mips-img-linux-gnu-gcc int-add/test_msa_hadd_u_h.c \ +-EL -static -mabi=64 -march=mips64r6 -mmsa -o /tmp/test_msa_hadd_u_h +/opt/img/bin/mips-img-linux-gnu-gcc int-add/test_msa_hadd_u_w.c \ +-EL -static -mabi=64 -march=mips64r6 -mmsa -o /tmp/test_msa_hadd_u_w +/opt/img/bin/mips-img-linux-gnu-gcc int-add/test_msa_hadd_u_d.c \ +-EL -static -mabi=64 -march=mips64r6 -mmsa -o /tmp/test_msa_hadd_u_d + +# +# Int Average +# ----------- +# +/opt/img/bin/mips-img-linux-gnu-gcc int-average/test_msa_ave_s_b.c \ +-EL -static -mabi=64 -march=mips64r6 -mmsa -o /tmp/test_msa_ave_s_b +/opt/img/bin/mips-img-linux-gnu-gcc int-average/test_msa_ave_s_h.c \ +-EL -static -mabi=64 -march=mips64r6 -mmsa -o /tmp/test_msa_ave_s_h +/opt/img/bin/mips-img-linux-gnu-gcc int-average/test_msa_ave_s_w.c \ +-EL -static -mabi=64 -march=mips64r6 -mmsa -o /tmp/test_msa_ave_s_w +/opt/img/bin/mips-img-linux-gnu-gcc int-average/test_msa_ave_s_d.c \ +-EL -static -mabi=64 -march=mips64r6 -mmsa -o /tmp/test_msa_ave_s_d +/opt/img/bin/mips-img-linux-gnu-gcc int-average/test_msa_ave_u_b.c \ +-EL -static -mabi=64 -march=mips64r6 -mmsa -o /tmp/test_msa_ave_u_b +/opt/img/bin/mips-img-linux-gnu-gcc int-average/test_msa_ave_u_h.c \ +-EL -static -mabi=64 -march=mips64r6 -mmsa -o /tmp/test_msa_ave_u_h +/opt/img/bin/mips-img-linux-gnu-gcc int-average/test_msa_ave_u_w.c \ +-EL -static -mabi=64 -march=mips64r6 -mmsa -o /tmp/test_msa_ave_u_w +/opt/img/bin/mips-img-linux-gnu-gcc int-average/test_msa_ave_u_d.c \ +-EL -static -mabi=64 -march=mips64r6 -mmsa -o /tmp/test_msa_ave_u_d +/opt/img/bin/mips-img-linux-gnu-gcc int-average/test_msa_aver_s_b.c \ +-EL -static -mabi=64 -march=mips64r6 -mmsa -o /tmp/test_msa_aver_s_b +/opt/img/bin/mips-img-linux-gnu-gcc int-average/test_msa_aver_s_h.c \ +-EL -static -mabi=64 -march=mips64r6 -mmsa -o /tmp/test_msa_aver_s_h +/opt/img/bin/mips-img-linux-gnu-gcc int-average/test_msa_aver_s_w.c \ +-EL -static -mabi=64 -march=mips64r6 -mmsa -o /tmp/test_msa_aver_s_w +/opt/img/bin/mips-img-linux-gnu-gcc int-average/test_msa_aver_s_d.c \ +-EL -static -mabi=64 -march=mips64r6 -mmsa -o /tmp/test_msa_aver_s_d +/opt/img/bin/mips-img-linux-gnu-gcc int-average/test_msa_aver_u_b.c \ +-EL -static -mabi=64 -march=mips64r6 -mmsa -o /tmp/test_msa_aver_u_b +/opt/img/bin/mips-img-linux-gnu-gcc int-average/test_msa_aver_u_h.c \ +-EL -static -mabi=64 -march=mips64r6 -mmsa -o /tmp/test_msa_aver_u_h +/opt/img/bin/mips-img-linux-gnu-gcc int-average/test_msa_aver_u_w.c \ +-EL -static -mabi=64 -march=mips64r6 -mmsa -o /tmp/test_msa_aver_u_w +/opt/img/bin/mips-img-linux-gnu-gcc int-average/test_msa_aver_u_d.c \ +-EL -static -mabi=64 -march=mips64r6 -mmsa -o /tmp/test_msa_aver_u_d + +# +# Int Compare +# ----------- +# +/opt/img/bin/mips-img-linux-gnu-gcc int-compare/test_msa_ceq_b.c \ +-EL -static -mabi=64 -march=mips64r6 -mmsa -o /tmp/test_msa_ceq_b +/opt/img/bin/mips-img-linux-gnu-gcc int-compare/test_msa_ceq_h.c \ +-EL -static -mabi=64 -march=mips64r6 -mmsa -o /tmp/test_msa_ceq_h +/opt/img/bin/mips-img-linux-gnu-gcc int-compare/test_msa_ceq_w.c \ +-EL -static -mabi=64 -march=mips64r6 -mmsa -o /tmp/test_msa_ceq_w +/opt/img/bin/mips-img-linux-gnu-gcc int-compare/test_msa_ceq_d.c \ +-EL -static -mabi=64 -march=mips64r6 -mmsa -o /tmp/test_msa_ceq_d +/opt/img/bin/mips-img-linux-gnu-gcc int-compare/test_msa_cle_s_b.c \ +-EL -static -mabi=64 -march=mips64r6 -mmsa -o /tmp/test_msa_cle_s_b +/opt/img/bin/mips-img-linux-gnu-gcc int-compare/test_msa_cle_s_h.c \ +-EL -static -mabi=64 -march=mips64r6 -mmsa -o /tmp/test_msa_cle_s_h +/opt/img/bin/mips-img-linux-gnu-gcc int-compare/test_msa_cle_s_w.c \ +-EL -static -mabi=64 -march=mips64r6 -mmsa -o /tmp/test_msa_cle_s_w +/opt/img/bin/mips-img-linux-gnu-gcc int-compare/test_msa_cle_s_d.c \ +-EL -static -mabi=64 -march=mips64r6 -mmsa -o /tmp/test_msa_cle_s_d +/opt/img/bin/mips-img-linux-gnu-gcc int-compare/test_msa_cle_u_b.c \ +-EL -static -mabi=64 -march=mips64r6 -mmsa -o /tmp/test_msa_cle_u_b +/opt/img/bin/mips-img-linux-gnu-gcc int-compare/test_msa_cle_u_h.c \ +-EL -static -mabi=64 -march=mips64r6 -mmsa -o /tmp/test_msa_cle_u_h +/opt/img/bin/mips-img-linux-gnu-gcc int-compare/test_msa_cle_u_w.c \ +-EL -static -mabi=64 -march=mips64r6 -mmsa -o /tmp/test_msa_cle_u_w +/opt/img/bin/mips-img-linux-gnu-gcc int-compare/test_msa_cle_u_d.c \ +-EL -static -mabi=64 -march=mips64r6 -mmsa -o /tmp/test_msa_cle_u_d +/opt/img/bin/mips-img-linux-gnu-gcc int-compare/test_msa_clt_s_b.c \ +-EL -static -mabi=64 -march=mips64r6 -mmsa -o /tmp/test_msa_clt_s_b +/opt/img/bin/mips-img-linux-gnu-gcc int-compare/test_msa_clt_s_h.c \ +-EL -static -mabi=64 -march=mips64r6 -mmsa -o /tmp/test_msa_clt_s_h +/opt/img/bin/mips-img-linux-gnu-gcc int-compare/test_msa_clt_s_w.c \ +-EL -static -mabi=64 -march=mips64r6 -mmsa -o /tmp/test_msa_clt_s_w +/opt/img/bin/mips-img-linux-gnu-gcc int-compare/test_msa_clt_s_d.c \ +-EL -static -mabi=64 -march=mips64r6 -mmsa -o /tmp/test_msa_clt_s_d +/opt/img/bin/mips-img-linux-gnu-gcc int-compare/test_msa_clt_u_b.c \ +-EL -static -mabi=64 -march=mips64r6 -mmsa -o /tmp/test_msa_clt_u_b +/opt/img/bin/mips-img-linux-gnu-gcc int-compare/test_msa_clt_u_h.c \ +-EL -static -mabi=64 -march=mips64r6 -mmsa -o /tmp/test_msa_clt_u_h +/opt/img/bin/mips-img-linux-gnu-gcc int-compare/test_msa_clt_u_w.c \ +-EL -static -mabi=64 -march=mips64r6 -mmsa -o /tmp/test_msa_clt_u_w +/opt/img/bin/mips-img-linux-gnu-gcc int-compare/test_msa_clt_u_d.c \ +-EL -static -mabi=64 -march=mips64r6 -mmsa -o /tmp/test_msa_clt_u_d + +# +# Int Divide +# ---------- +# +/opt/img/bin/mips-img-linux-gnu-gcc int-divide/test_msa_div_s_b.c \ +-EL -static -mabi=64 -march=mips64r6 -mmsa -o /tmp/test_msa_div_s_b +/opt/img/bin/mips-img-linux-gnu-gcc int-divide/test_msa_div_s_h.c \ +-EL -static -mabi=64 -march=mips64r6 -mmsa -o /tmp/test_msa_div_s_h +/opt/img/bin/mips-img-linux-gnu-gcc int-divide/test_msa_div_s_w.c \ +-EL -static -mabi=64 -march=mips64r6 -mmsa -o /tmp/test_msa_div_s_w +/opt/img/bin/mips-img-linux-gnu-gcc int-divide/test_msa_div_s_d.c \ +-EL -static -mabi=64 -march=mips64r6 -mmsa -o /tmp/test_msa_div_s_d +/opt/img/bin/mips-img-linux-gnu-gcc int-divide/test_msa_div_u_b.c \ +-EL -static -mabi=64 -march=mips64r6 -mmsa -o /tmp/test_msa_div_u_b +/opt/img/bin/mips-img-linux-gnu-gcc int-divide/test_msa_div_u_h.c \ +-EL -static -mabi=64 -march=mips64r6 -mmsa -o /tmp/test_msa_div_u_h +/opt/img/bin/mips-img-linux-gnu-gcc int-divide/test_msa_div_u_w.c \ +-EL -static -mabi=64 -march=mips64r6 -mmsa -o /tmp/test_msa_div_u_w +/opt/img/bin/mips-img-linux-gnu-gcc int-divide/test_msa_div_u_d.c \ +-EL -static -mabi=64 -march=mips64r6 -mmsa -o /tmp/test_msa_div_u_d + +# +# Int Dot Product +# --------------- +# +/opt/img/bin/mips-img-linux-gnu-gcc int-dot-product/test_msa_dotp_s_h.c \ +-EL -static -mabi=64 -march=mips64r6 -mmsa -o /tmp/test_msa_dotp_s_h +/opt/img/bin/mips-img-linux-gnu-gcc int-dot-product/test_msa_dotp_s_w.c \ +-EL -static -mabi=64 -march=mips64r6 -mmsa -o /tmp/test_msa_dotp_s_w +/opt/img/bin/mips-img-linux-gnu-gcc int-dot-product/test_msa_dotp_s_d.c \ +-EL -static -mabi=64 -march=mips64r6 -mmsa -o /tmp/test_msa_dotp_s_d +/opt/img/bin/mips-img-linux-gnu-gcc int-dot-product/test_msa_dotp_u_h.c \ +-EL -static -mabi=64 -march=mips64r6 -mmsa -o /tmp/test_msa_dotp_u_h +/opt/img/bin/mips-img-linux-gnu-gcc int-dot-product/test_msa_dotp_u_w.c \ +-EL -static -mabi=64 -march=mips64r6 -mmsa -o /tmp/test_msa_dotp_u_w +/opt/img/bin/mips-img-linux-gnu-gcc int-dot-product/test_msa_dotp_u_d.c \ +-EL -static -mabi=64 -march=mips64r6 -mmsa -o /tmp/test_msa_dotp_u_d + +# +# Int Max Min +# ----------- +# +/opt/img/bin/mips-img-linux-gnu-gcc int-max-min/test_msa_max_a_b.c \ +-EL -static -mabi=64 -march=mips64r6 -mmsa -o /tmp/test_msa_max_a_b +/opt/img/bin/mips-img-linux-gnu-gcc int-max-min/test_msa_max_a_h.c \ +-EL -static -mabi=64 -march=mips64r6 -mmsa -o /tmp/test_msa_max_a_h +/opt/img/bin/mips-img-linux-gnu-gcc int-max-min/test_msa_max_a_w.c \ +-EL -static -mabi=64 -march=mips64r6 -mmsa -o /tmp/test_msa_max_a_w +/opt/img/bin/mips-img-linux-gnu-gcc int-max-min/test_msa_max_a_d.c \ +-EL -static -mabi=64 -march=mips64r6 -mmsa -o /tmp/test_msa_max_a_d +/opt/img/bin/mips-img-linux-gnu-gcc int-max-min/test_msa_max_s_b.c \ +-EL -static -mabi=64 -march=mips64r6 -mmsa -o /tmp/test_msa_max_s_b +/opt/img/bin/mips-img-linux-gnu-gcc int-max-min/test_msa_max_s_h.c \ +-EL -static -mabi=64 -march=mips64r6 -mmsa -o /tmp/test_msa_max_s_h +/opt/img/bin/mips-img-linux-gnu-gcc int-max-min/test_msa_max_s_w.c \ +-EL -static -mabi=64 -march=mips64r6 -mmsa -o /tmp/test_msa_max_s_w +/opt/img/bin/mips-img-linux-gnu-gcc int-max-min/test_msa_max_s_d.c \ +-EL -static -mabi=64 -march=mips64r6 -mmsa -o /tmp/test_msa_max_s_d +/opt/img/bin/mips-img-linux-gnu-gcc int-max-min/test_msa_max_u_b.c \ +-EL -static -mabi=64 -march=mips64r6 -mmsa -o /tmp/test_msa_max_u_b +/opt/img/bin/mips-img-linux-gnu-gcc int-max-min/test_msa_max_u_h.c \ +-EL -static -mabi=64 -march=mips64r6 -mmsa -o /tmp/test_msa_max_u_h +/opt/img/bin/mips-img-linux-gnu-gcc int-max-min/test_msa_max_u_w.c \ +-EL -static -mabi=64 -march=mips64r6 -mmsa -o /tmp/test_msa_max_u_w +/opt/img/bin/mips-img-linux-gnu-gcc int-max-min/test_msa_max_u_d.c \ +-EL -static -mabi=64 -march=mips64r6 -mmsa -o /tmp/test_msa_max_u_d +/opt/img/bin/mips-img-linux-gnu-gcc int-max-min/test_msa_min_a_b.c \ +-EL -static -mabi=64 -march=mips64r6 -mmsa -o /tmp/test_msa_min_a_b +/opt/img/bin/mips-img-linux-gnu-gcc int-max-min/test_msa_min_a_h.c \ +-EL -static -mabi=64 -march=mips64r6 -mmsa -o /tmp/test_msa_min_a_h +/opt/img/bin/mips-img-linux-gnu-gcc int-max-min/test_msa_min_a_w.c \ +-EL -static -mabi=64 -march=mips64r6 -mmsa -o /tmp/test_msa_min_a_w +/opt/img/bin/mips-img-linux-gnu-gcc int-max-min/test_msa_min_a_d.c \ +-EL -static -mabi=64 -march=mips64r6 -mmsa -o /tmp/test_msa_min_a_d +/opt/img/bin/mips-img-linux-gnu-gcc int-max-min/test_msa_min_s_b.c \ +-EL -static -mabi=64 -march=mips64r6 -mmsa -o /tmp/test_msa_min_s_b +/opt/img/bin/mips-img-linux-gnu-gcc int-max-min/test_msa_min_s_h.c \ +-EL -static -mabi=64 -march=mips64r6 -mmsa -o /tmp/test_msa_min_s_h +/opt/img/bin/mips-img-linux-gnu-gcc int-max-min/test_msa_min_s_w.c \ +-EL -static -mabi=64 -march=mips64r6 -mmsa -o /tmp/test_msa_min_s_w +/opt/img/bin/mips-img-linux-gnu-gcc int-max-min/test_msa_min_s_d.c \ +-EL -static -mabi=64 -march=mips64r6 -mmsa -o /tmp/test_msa_min_s_d +/opt/img/bin/mips-img-linux-gnu-gcc int-max-min/test_msa_min_u_b.c \ +-EL -static -mabi=64 -march=mips64r6 -mmsa -o /tmp/test_msa_min_u_b +/opt/img/bin/mips-img-linux-gnu-gcc int-max-min/test_msa_min_u_h.c \ +-EL -static -mabi=64 -march=mips64r6 -mmsa -o /tmp/test_msa_min_u_h +/opt/img/bin/mips-img-linux-gnu-gcc int-max-min/test_msa_min_u_w.c \ +-EL -static -mabi=64 -march=mips64r6 -mmsa -o /tmp/test_msa_min_u_w +/opt/img/bin/mips-img-linux-gnu-gcc int-max-min/test_msa_min_u_d.c \ +-EL -static -mabi=64 -march=mips64r6 -mmsa -o /tmp/test_msa_min_u_d + +# +# Int Modulo +# ---------- +# +/opt/img/bin/mips-img-linux-gnu-gcc int-modulo/test_msa_mod_s_b.c \ +-EL -static -mabi=64 -march=mips64r6 -mmsa -o /tmp/test_msa_mod_s_b +/opt/img/bin/mips-img-linux-gnu-gcc int-modulo/test_msa_mod_s_h.c \ +-EL -static -mabi=64 -march=mips64r6 -mmsa -o /tmp/test_msa_mod_s_h +/opt/img/bin/mips-img-linux-gnu-gcc int-modulo/test_msa_mod_s_w.c \ +-EL -static -mabi=64 -march=mips64r6 -mmsa -o /tmp/test_msa_mod_s_w +/opt/img/bin/mips-img-linux-gnu-gcc int-modulo/test_msa_mod_s_d.c \ +-EL -static -mabi=64 -march=mips64r6 -mmsa -o /tmp/test_msa_mod_s_d +/opt/img/bin/mips-img-linux-gnu-gcc int-modulo/test_msa_mod_u_b.c \ +-EL -static -mabi=64 -march=mips64r6 -mmsa -o /tmp/test_msa_mod_u_b +/opt/img/bin/mips-img-linux-gnu-gcc int-modulo/test_msa_mod_u_h.c \ +-EL -static -mabi=64 -march=mips64r6 -mmsa -o /tmp/test_msa_mod_u_h +/opt/img/bin/mips-img-linux-gnu-gcc int-modulo/test_msa_mod_u_w.c \ +-EL -static -mabi=64 -march=mips64r6 -mmsa -o /tmp/test_msa_mod_u_w +/opt/img/bin/mips-img-linux-gnu-gcc int-modulo/test_msa_mod_u_d.c \ +-EL -static -mabi=64 -march=mips64r6 -mmsa -o /tmp/test_msa_mod_u_d + +# +# Int Multiply +# ------------ +# +/opt/img/bin/mips-img-linux-gnu-gcc int-multiply/test_msa_mulv_b.c \ +-EL -static -mabi=64 -march=mips64r6 -mmsa -o /tmp/test_msa_mulv_b +/opt/img/bin/mips-img-linux-gnu-gcc int-multiply/test_msa_mulv_h.c \ +-EL -static -mabi=64 -march=mips64r6 -mmsa -o /tmp/test_msa_mulv_h +/opt/img/bin/mips-img-linux-gnu-gcc int-multiply/test_msa_mulv_w.c \ +-EL -static -mabi=64 -march=mips64r6 -mmsa -o /tmp/test_msa_mulv_w +/opt/img/bin/mips-img-linux-gnu-gcc int-multiply/test_msa_mulv_d.c \ +-EL -static -mabi=64 -march=mips64r6 -mmsa -o /tmp/test_msa_mulv_d + +# +# Int Subtract +# ------------ +# +/opt/img/bin/mips-img-linux-gnu-gcc int-subtract/test_msa_asub_s_b.c \ +-EL -static -mabi=64 -march=mips64r6 -mmsa -o /tmp/test_msa_asub_s_b +/opt/img/bin/mips-img-linux-gnu-gcc int-subtract/test_msa_asub_s_h.c \ +-EL -static -mabi=64 -march=mips64r6 -mmsa -o /tmp/test_msa_asub_s_h +/opt/img/bin/mips-img-linux-gnu-gcc int-subtract/test_msa_asub_s_w.c \ +-EL -static -mabi=64 -march=mips64r6 -mmsa -o /tmp/test_msa_asub_s_w +/opt/img/bin/mips-img-linux-gnu-gcc int-subtract/test_msa_asub_s_d.c \ +-EL -static -mabi=64 -march=mips64r6 -mmsa -o /tmp/test_msa_asub_s_d +/opt/img/bin/mips-img-linux-gnu-gcc int-subtract/test_msa_asub_u_b.c \ +-EL -static -mabi=64 -march=mips64r6 -mmsa -o /tmp/test_msa_asub_u_b +/opt/img/bin/mips-img-linux-gnu-gcc int-subtract/test_msa_asub_u_h.c \ +-EL -static -mabi=64 -march=mips64r6 -mmsa -o /tmp/test_msa_asub_u_h +/opt/img/bin/mips-img-linux-gnu-gcc int-subtract/test_msa_asub_u_w.c \ +-EL -static -mabi=64 -march=mips64r6 -mmsa -o /tmp/test_msa_asub_u_w +/opt/img/bin/mips-img-linux-gnu-gcc int-subtract/test_msa_asub_u_d.c \ +-EL -static -mabi=64 -march=mips64r6 -mmsa -o /tmp/test_msa_asub_u_d +/opt/img/bin/mips-img-linux-gnu-gcc int-subtract/test_msa_hsub_s_h.c \ +-EL -static -mabi=64 -march=mips64r6 -mmsa -o /tmp/test_msa_hsub_s_h +/opt/img/bin/mips-img-linux-gnu-gcc int-subtract/test_msa_hsub_s_w.c \ +-EL -static -mabi=64 -march=mips64r6 -mmsa -o /tmp/test_msa_hsub_s_w +/opt/img/bin/mips-img-linux-gnu-gcc int-subtract/test_msa_hsub_s_d.c \ +-EL -static -mabi=64 -march=mips64r6 -mmsa -o /tmp/test_msa_hsub_s_d +/opt/img/bin/mips-img-linux-gnu-gcc int-subtract/test_msa_hsub_u_h.c \ +-EL -static -mabi=64 -march=mips64r6 -mmsa -o /tmp/test_msa_hsub_u_h +/opt/img/bin/mips-img-linux-gnu-gcc int-subtract/test_msa_hsub_u_w.c \ +-EL -static -mabi=64 -march=mips64r6 -mmsa -o /tmp/test_msa_hsub_u_w +/opt/img/bin/mips-img-linux-gnu-gcc int-subtract/test_msa_hsub_u_d.c \ +-EL -static -mabi=64 -march=mips64r6 -mmsa -o /tmp/test_msa_hsub_u_d +/opt/img/bin/mips-img-linux-gnu-gcc int-subtract/test_msa_subs_s_b.c \ +-EL -static -mabi=64 -march=mips64r6 -mmsa -o /tmp/test_msa_subs_s_b +/opt/img/bin/mips-img-linux-gnu-gcc int-subtract/test_msa_subs_s_h.c \ +-EL -static -mabi=64 -march=mips64r6 -mmsa -o /tmp/test_msa_subs_s_h +/opt/img/bin/mips-img-linux-gnu-gcc int-subtract/test_msa_subs_s_w.c \ +-EL -static -mabi=64 -march=mips64r6 -mmsa -o /tmp/test_msa_subs_s_w +/opt/img/bin/mips-img-linux-gnu-gcc int-subtract/test_msa_subs_s_d.c \ +-EL -static -mabi=64 -march=mips64r6 -mmsa -o /tmp/test_msa_subs_s_d +/opt/img/bin/mips-img-linux-gnu-gcc int-subtract/test_msa_subs_u_b.c \ +-EL -static -mabi=64 -march=mips64r6 -mmsa -o /tmp/test_msa_subs_u_b +/opt/img/bin/mips-img-linux-gnu-gcc int-subtract/test_msa_subs_u_h.c \ +-EL -static -mabi=64 -march=mips64r6 -mmsa -o /tmp/test_msa_subs_u_h +/opt/img/bin/mips-img-linux-gnu-gcc int-subtract/test_msa_subs_u_w.c \ +-EL -static -mabi=64 -march=mips64r6 -mmsa -o /tmp/test_msa_subs_u_w +/opt/img/bin/mips-img-linux-gnu-gcc int-subtract/test_msa_subs_u_d.c \ +-EL -static -mabi=64 -march=mips64r6 -mmsa -o /tmp/test_msa_subs_u_d +/opt/img/bin/mips-img-linux-gnu-gcc int-subtract/test_msa_subsuu_s_b.c \ +-EL -static -mabi=64 -march=mips64r6 -mmsa -o /tmp/test_msa_subsuu_s_b +/opt/img/bin/mips-img-linux-gnu-gcc int-subtract/test_msa_subsuu_s_h.c \ +-EL -static -mabi=64 -march=mips64r6 -mmsa -o /tmp/test_msa_subsuu_s_h +/opt/img/bin/mips-img-linux-gnu-gcc int-subtract/test_msa_subsuu_s_w.c \ +-EL -static -mabi=64 -march=mips64r6 -mmsa -o /tmp/test_msa_subsuu_s_w +/opt/img/bin/mips-img-linux-gnu-gcc int-subtract/test_msa_subsuu_s_d.c \ +-EL -static -mabi=64 -march=mips64r6 -mmsa -o /tmp/test_msa_subsuu_s_d +/opt/img/bin/mips-img-linux-gnu-gcc int-subtract/test_msa_subsus_u_b.c \ +-EL -static -mabi=64 -march=mips64r6 -mmsa -o /tmp/test_msa_subsus_u_b +/opt/img/bin/mips-img-linux-gnu-gcc int-subtract/test_msa_subsus_u_h.c \ +-EL -static -mabi=64 -march=mips64r6 -mmsa -o /tmp/test_msa_subsus_u_h +/opt/img/bin/mips-img-linux-gnu-gcc int-subtract/test_msa_subsus_u_w.c \ +-EL -static -mabi=64 -march=mips64r6 -mmsa -o /tmp/test_msa_subsus_u_w +/opt/img/bin/mips-img-linux-gnu-gcc int-subtract/test_msa_subsus_u_d.c \ +-EL -static -mabi=64 -march=mips64r6 -mmsa -o /tmp/test_msa_subsus_u_d +/opt/img/bin/mips-img-linux-gnu-gcc int-subtract/test_msa_subv_b.c \ +-EL -static -mabi=64 -march=mips64r6 -mmsa -o /tmp/test_msa_subv_b +/opt/img/bin/mips-img-linux-gnu-gcc int-subtract/test_msa_subv_h.c \ +-EL -static -mabi=64 -march=mips64r6 -mmsa -o /tmp/test_msa_subv_h +/opt/img/bin/mips-img-linux-gnu-gcc int-subtract/test_msa_subv_w.c \ +-EL -static -mabi=64 -march=mips64r6 -mmsa -o /tmp/test_msa_subv_w +/opt/img/bin/mips-img-linux-gnu-gcc int-subtract/test_msa_subv_d.c \ +-EL -static -mabi=64 -march=mips64r6 -mmsa -o /tmp/test_msa_subv_d + +# +# Interleave +# ---------- +# +/opt/img/bin/mips-img-linux-gnu-gcc interleave/test_msa_ilvev_b.c \ +-EL -static -mabi=64 -march=mips64r6 -mmsa -o /tmp/test_msa_ilvev_b +/opt/img/bin/mips-img-linux-gnu-gcc interleave/test_msa_ilvev_h.c \ +-EL -static -mabi=64 -march=mips64r6 -mmsa -o /tmp/test_msa_ilvev_h +/opt/img/bin/mips-img-linux-gnu-gcc interleave/test_msa_ilvev_w.c \ +-EL -static -mabi=64 -march=mips64r6 -mmsa -o /tmp/test_msa_ilvev_w +/opt/img/bin/mips-img-linux-gnu-gcc interleave/test_msa_ilvev_d.c \ +-EL -static -mabi=64 -march=mips64r6 -mmsa -o /tmp/test_msa_ilvev_d +/opt/img/bin/mips-img-linux-gnu-gcc interleave/test_msa_ilvod_b.c \ +-EL -static -mabi=64 -march=mips64r6 -mmsa -o /tmp/test_msa_ilvod_b +/opt/img/bin/mips-img-linux-gnu-gcc interleave/test_msa_ilvod_h.c \ +-EL -static -mabi=64 -march=mips64r6 -mmsa -o /tmp/test_msa_ilvod_h +/opt/img/bin/mips-img-linux-gnu-gcc interleave/test_msa_ilvod_w.c \ +-EL -static -mabi=64 -march=mips64r6 -mmsa -o /tmp/test_msa_ilvod_w +/opt/img/bin/mips-img-linux-gnu-gcc interleave/test_msa_ilvod_d.c \ +-EL -static -mabi=64 -march=mips64r6 -mmsa -o /tmp/test_msa_ilvod_d +/opt/img/bin/mips-img-linux-gnu-gcc interleave/test_msa_ilvl_b.c \ +-EL -static -mabi=64 -march=mips64r6 -mmsa -o /tmp/test_msa_ilvl_b +/opt/img/bin/mips-img-linux-gnu-gcc interleave/test_msa_ilvl_h.c \ +-EL -static -mabi=64 -march=mips64r6 -mmsa -o /tmp/test_msa_ilvl_h +/opt/img/bin/mips-img-linux-gnu-gcc interleave/test_msa_ilvl_w.c \ +-EL -static -mabi=64 -march=mips64r6 -mmsa -o /tmp/test_msa_ilvl_w +/opt/img/bin/mips-img-linux-gnu-gcc interleave/test_msa_ilvl_d.c \ +-EL -static -mabi=64 -march=mips64r6 -mmsa -o /tmp/test_msa_ilvl_d +/opt/img/bin/mips-img-linux-gnu-gcc interleave/test_msa_ilvr_b.c \ +-EL -static -mabi=64 -march=mips64r6 -mmsa -o /tmp/test_msa_ilvr_b +/opt/img/bin/mips-img-linux-gnu-gcc interleave/test_msa_ilvr_h.c \ +-EL -static -mabi=64 -march=mips64r6 -mmsa -o /tmp/test_msa_ilvr_h +/opt/img/bin/mips-img-linux-gnu-gcc interleave/test_msa_ilvr_w.c \ +-EL -static -mabi=64 -march=mips64r6 -mmsa -o /tmp/test_msa_ilvr_w +/opt/img/bin/mips-img-linux-gnu-gcc interleave/test_msa_ilvr_d.c \ +-EL -static -mabi=64 -march=mips64r6 -mmsa -o /tmp/test_msa_ilvr_d + +# +# Logic +# ----- +# +/opt/img/bin/mips-img-linux-gnu-gcc logic/test_msa_and_v.c \ +-EL -static -mabi=64 -march=mips64r6 -mmsa -o /tmp/test_msa_and_v +/opt/img/bin/mips-img-linux-gnu-gcc logic/test_msa_nor_v.c \ +-EL -static -mabi=64 -march=mips64r6 -mmsa -o /tmp/test_msa_nor_v +/opt/img/bin/mips-img-linux-gnu-gcc logic/test_msa_or_v.c \ +-EL -static -mabi=64 -march=mips64r6 -mmsa -o /tmp/test_msa_or_v +/opt/img/bin/mips-img-linux-gnu-gcc logic/test_msa_xor_v.c \ +-EL -static -mabi=64 -march=mips64r6 -mmsa -o /tmp/test_msa_xor_v + +# +# Pack +# ---- +# +/opt/img/bin/mips-img-linux-gnu-gcc pack/test_msa_pckev_b.c \ +-EL -static -mabi=64 -march=mips64r6 -mmsa -o /tmp/test_msa_pckev_b +/opt/img/bin/mips-img-linux-gnu-gcc pack/test_msa_pckev_h.c \ +-EL -static -mabi=64 -march=mips64r6 -mmsa -o /tmp/test_msa_pckev_h +/opt/img/bin/mips-img-linux-gnu-gcc pack/test_msa_pckev_w.c \ +-EL -static -mabi=64 -march=mips64r6 -mmsa -o /tmp/test_msa_pckev_w +/opt/img/bin/mips-img-linux-gnu-gcc pack/test_msa_pckev_d.c \ +-EL -static -mabi=64 -march=mips64r6 -mmsa -o /tmp/test_msa_pckev_d +/opt/img/bin/mips-img-linux-gnu-gcc pack/test_msa_pckod_b.c \ +-EL -static -mabi=64 -march=mips64r6 -mmsa -o /tmp/test_msa_pckod_b +/opt/img/bin/mips-img-linux-gnu-gcc pack/test_msa_pckod_h.c \ +-EL -static -mabi=64 -march=mips64r6 -mmsa -o /tmp/test_msa_pckod_h +/opt/img/bin/mips-img-linux-gnu-gcc pack/test_msa_pckod_w.c \ +-EL -static -mabi=64 -march=mips64r6 -mmsa -o /tmp/test_msa_pckod_w +/opt/img/bin/mips-img-linux-gnu-gcc pack/test_msa_pckod_d.c \ +-EL -static -mabi=64 -march=mips64r6 -mmsa -o /tmp/test_msa_pckod_d +/opt/img/bin/mips-img-linux-gnu-gcc pack/test_msa_vshf_b.c \ +-EL -static -mabi=64 -march=mips64r6 -mmsa -o /tmp/test_msa_vshf_b +/opt/img/bin/mips-img-linux-gnu-gcc pack/test_msa_vshf_h.c \ +-EL -static -mabi=64 -march=mips64r6 -mmsa -o /tmp/test_msa_vshf_h +/opt/img/bin/mips-img-linux-gnu-gcc pack/test_msa_vshf_w.c \ +-EL -static -mabi=64 -march=mips64r6 -mmsa -o /tmp/test_msa_vshf_w +/opt/img/bin/mips-img-linux-gnu-gcc pack/test_msa_vshf_d.c \ +-EL -static -mabi=64 -march=mips64r6 -mmsa -o /tmp/test_msa_vshf_d + +# +# Shift +# ----- +# +/opt/img/bin/mips-img-linux-gnu-gcc shift/test_msa_sll_b.c \ +-EL -static -mabi=64 -march=mips64r6 -mmsa -o /tmp/test_msa_sll_b +/opt/img/bin/mips-img-linux-gnu-gcc shift/test_msa_sll_h.c \ +-EL -static -mabi=64 -march=mips64r6 -mmsa -o /tmp/test_msa_sll_h +/opt/img/bin/mips-img-linux-gnu-gcc shift/test_msa_sll_w.c \ +-EL -static -mabi=64 -march=mips64r6 -mmsa -o /tmp/test_msa_sll_w +/opt/img/bin/mips-img-linux-gnu-gcc shift/test_msa_sll_d.c \ +-EL -static -mabi=64 -march=mips64r6 -mmsa -o /tmp/test_msa_sll_d +/opt/img/bin/mips-img-linux-gnu-gcc shift/test_msa_sra_b.c \ +-EL -static -mabi=64 -march=mips64r6 -mmsa -o /tmp/test_msa_sra_b +/opt/img/bin/mips-img-linux-gnu-gcc shift/test_msa_sra_h.c \ +-EL -static -mabi=64 -march=mips64r6 -mmsa -o /tmp/test_msa_sra_h +/opt/img/bin/mips-img-linux-gnu-gcc shift/test_msa_sra_w.c \ +-EL -static -mabi=64 -march=mips64r6 -mmsa -o /tmp/test_msa_sra_w +/opt/img/bin/mips-img-linux-gnu-gcc shift/test_msa_sra_d.c \ +-EL -static -mabi=64 -march=mips64r6 -mmsa -o /tmp/test_msa_sra_d +/opt/img/bin/mips-img-linux-gnu-gcc shift/test_msa_srar_b.c \ +-EL -static -mabi=64 -march=mips64r6 -mmsa -o /tmp/test_msa_srar_b +/opt/img/bin/mips-img-linux-gnu-gcc shift/test_msa_srar_h.c \ +-EL -static -mabi=64 -march=mips64r6 -mmsa -o /tmp/test_msa_srar_h +/opt/img/bin/mips-img-linux-gnu-gcc shift/test_msa_srar_w.c \ +-EL -static -mabi=64 -march=mips64r6 -mmsa -o /tmp/test_msa_srar_w +/opt/img/bin/mips-img-linux-gnu-gcc shift/test_msa_srar_d.c \ +-EL -static -mabi=64 -march=mips64r6 -mmsa -o /tmp/test_msa_srar_d +/opt/img/bin/mips-img-linux-gnu-gcc shift/test_msa_srl_b.c \ +-EL -static -mabi=64 -march=mips64r6 -mmsa -o /tmp/test_msa_srl_b +/opt/img/bin/mips-img-linux-gnu-gcc shift/test_msa_srl_h.c \ +-EL -static -mabi=64 -march=mips64r6 -mmsa -o /tmp/test_msa_srl_h +/opt/img/bin/mips-img-linux-gnu-gcc shift/test_msa_srl_w.c \ +-EL -static -mabi=64 -march=mips64r6 -mmsa -o /tmp/test_msa_srl_w +/opt/img/bin/mips-img-linux-gnu-gcc shift/test_msa_srl_d.c \ +-EL -static -mabi=64 -march=mips64r6 -mmsa -o /tmp/test_msa_srl_d +/opt/img/bin/mips-img-linux-gnu-gcc shift/test_msa_srlr_b.c \ +-EL -static -mabi=64 -march=mips64r6 -mmsa -o /tmp/test_msa_srlr_b +/opt/img/bin/mips-img-linux-gnu-gcc shift/test_msa_srlr_h.c \ +-EL -static -mabi=64 -march=mips64r6 -mmsa -o /tmp/test_msa_srlr_h +/opt/img/bin/mips-img-linux-gnu-gcc shift/test_msa_srlr_w.c \ +-EL -static -mabi=64 -march=mips64r6 -mmsa -o /tmp/test_msa_srlr_w +/opt/img/bin/mips-img-linux-gnu-gcc shift/test_msa_srlr_d.c \ +-EL -static -mabi=64 -march=mips64r6 -mmsa -o /tmp/test_msa_srlr_d diff --git a/tests/tcg/mips/user/ase/msa/test_msa_run.sh b/tests/tcg/mips/user/ase/msa/test_msa_run.sh new file mode 100755 index 0000000000..278d93b614 --- /dev/null +++ b/tests/tcg/mips/user/ase/msa/test_msa_run.sh @@ -0,0 +1,326 @@ +PATH_TO_QEMU="../../../../../../mips64el-linux-user/qemu-mips64el" + + +# +# Bit Count +# --------- +# +$PATH_TO_QEMU -cpu I6400 /tmp/test_msa_nloc_b +$PATH_TO_QEMU -cpu I6400 /tmp/test_msa_nloc_h +$PATH_TO_QEMU -cpu I6400 /tmp/test_msa_nloc_w +$PATH_TO_QEMU -cpu I6400 /tmp/test_msa_nloc_d +$PATH_TO_QEMU -cpu I6400 /tmp/test_msa_nlzc_b +$PATH_TO_QEMU -cpu I6400 /tmp/test_msa_nlzc_h +$PATH_TO_QEMU -cpu I6400 /tmp/test_msa_nlzc_w +$PATH_TO_QEMU -cpu I6400 /tmp/test_msa_nlzc_d +$PATH_TO_QEMU -cpu I6400 /tmp/test_msa_pcnt_b +$PATH_TO_QEMU -cpu I6400 /tmp/test_msa_pcnt_h +$PATH_TO_QEMU -cpu I6400 /tmp/test_msa_pcnt_w +$PATH_TO_QEMU -cpu I6400 /tmp/test_msa_pcnt_d + +# +# Bit move +# -------- +# + +# +# Bit Set +# ------- +# +$PATH_TO_QEMU -cpu I6400 /tmp/test_msa_bclr_b +$PATH_TO_QEMU -cpu I6400 /tmp/test_msa_bclr_h +$PATH_TO_QEMU -cpu I6400 /tmp/test_msa_bclr_w +$PATH_TO_QEMU -cpu I6400 /tmp/test_msa_bclr_d +$PATH_TO_QEMU -cpu I6400 /tmp/test_msa_bneg_b +$PATH_TO_QEMU -cpu I6400 /tmp/test_msa_bneg_h +$PATH_TO_QEMU -cpu I6400 /tmp/test_msa_bneg_w +$PATH_TO_QEMU -cpu I6400 /tmp/test_msa_bneg_d +$PATH_TO_QEMU -cpu I6400 /tmp/test_msa_bset_b +$PATH_TO_QEMU -cpu I6400 /tmp/test_msa_bset_h +$PATH_TO_QEMU -cpu I6400 /tmp/test_msa_bset_w +$PATH_TO_QEMU -cpu I6400 /tmp/test_msa_bset_d + +# +# Fixed Multiply +# -------------- +# +$PATH_TO_QEMU -cpu I6400 /tmp/test_msa_mul_q_h +$PATH_TO_QEMU -cpu I6400 /tmp/test_msa_mul_q_w +$PATH_TO_QEMU -cpu I6400 /tmp/test_msa_mulr_q_h +$PATH_TO_QEMU -cpu I6400 /tmp/test_msa_mulr_q_w + +# +# Float Max Min +# ------------- +# +$PATH_TO_QEMU -cpu I6400 /tmp/test_msa_fmax_a_w +$PATH_TO_QEMU -cpu I6400 /tmp/test_msa_fmax_a_d +$PATH_TO_QEMU -cpu I6400 /tmp/test_msa_fmax_w +$PATH_TO_QEMU -cpu I6400 /tmp/test_msa_fmax_d +$PATH_TO_QEMU -cpu I6400 /tmp/test_msa_fmin_a_w +$PATH_TO_QEMU -cpu I6400 /tmp/test_msa_fmin_a_d +$PATH_TO_QEMU -cpu I6400 /tmp/test_msa_fmin_w +$PATH_TO_QEMU -cpu I6400 /tmp/test_msa_fmin_d + +# +# Int Add +# ------- +# +$PATH_TO_QEMU -cpu I6400 /tmp/test_msa_add_a_b +$PATH_TO_QEMU -cpu I6400 /tmp/test_msa_add_a_h +$PATH_TO_QEMU -cpu I6400 /tmp/test_msa_add_a_w +$PATH_TO_QEMU -cpu I6400 /tmp/test_msa_add_a_d +$PATH_TO_QEMU -cpu I6400 /tmp/test_msa_adds_a_b +$PATH_TO_QEMU -cpu I6400 /tmp/test_msa_adds_a_h +$PATH_TO_QEMU -cpu I6400 /tmp/test_msa_adds_a_w +$PATH_TO_QEMU -cpu I6400 /tmp/test_msa_adds_a_d +$PATH_TO_QEMU -cpu I6400 /tmp/test_msa_adds_s_b +$PATH_TO_QEMU -cpu I6400 /tmp/test_msa_adds_s_h +$PATH_TO_QEMU -cpu I6400 /tmp/test_msa_adds_s_w +$PATH_TO_QEMU -cpu I6400 /tmp/test_msa_adds_s_d +$PATH_TO_QEMU -cpu I6400 /tmp/test_msa_adds_u_b +$PATH_TO_QEMU -cpu I6400 /tmp/test_msa_adds_u_h +$PATH_TO_QEMU -cpu I6400 /tmp/test_msa_adds_u_w +$PATH_TO_QEMU -cpu I6400 /tmp/test_msa_adds_u_d +$PATH_TO_QEMU -cpu I6400 /tmp/test_msa_addv_b +$PATH_TO_QEMU -cpu I6400 /tmp/test_msa_addv_h +$PATH_TO_QEMU -cpu I6400 /tmp/test_msa_addv_w +$PATH_TO_QEMU -cpu I6400 /tmp/test_msa_addv_d +$PATH_TO_QEMU -cpu I6400 /tmp/test_msa_hadd_s_h +$PATH_TO_QEMU -cpu I6400 /tmp/test_msa_hadd_s_w +$PATH_TO_QEMU -cpu I6400 /tmp/test_msa_hadd_s_d +$PATH_TO_QEMU -cpu I6400 /tmp/test_msa_hadd_u_h +$PATH_TO_QEMU -cpu I6400 /tmp/test_msa_hadd_u_w +$PATH_TO_QEMU -cpu I6400 /tmp/test_msa_hadd_u_d + +# +# Int Average +# ----------- +# +$PATH_TO_QEMU -cpu I6400 /tmp/test_msa_ave_s_b +$PATH_TO_QEMU -cpu I6400 /tmp/test_msa_ave_s_h +$PATH_TO_QEMU -cpu I6400 /tmp/test_msa_ave_s_w +$PATH_TO_QEMU -cpu I6400 /tmp/test_msa_ave_s_d +$PATH_TO_QEMU -cpu I6400 /tmp/test_msa_ave_u_b +$PATH_TO_QEMU -cpu I6400 /tmp/test_msa_ave_u_h +$PATH_TO_QEMU -cpu I6400 /tmp/test_msa_ave_u_w +$PATH_TO_QEMU -cpu I6400 /tmp/test_msa_ave_u_d +$PATH_TO_QEMU -cpu I6400 /tmp/test_msa_aver_s_b +$PATH_TO_QEMU -cpu I6400 /tmp/test_msa_aver_s_h +$PATH_TO_QEMU -cpu I6400 /tmp/test_msa_aver_s_w +$PATH_TO_QEMU -cpu I6400 /tmp/test_msa_aver_s_d +$PATH_TO_QEMU -cpu I6400 /tmp/test_msa_aver_u_b +$PATH_TO_QEMU -cpu I6400 /tmp/test_msa_aver_u_h +$PATH_TO_QEMU -cpu I6400 /tmp/test_msa_aver_u_w +$PATH_TO_QEMU -cpu I6400 /tmp/test_msa_aver_u_d + +# +# Int Compare +# ----------- +# +$PATH_TO_QEMU -cpu I6400 /tmp/test_msa_ceq_b +$PATH_TO_QEMU -cpu I6400 /tmp/test_msa_ceq_h +$PATH_TO_QEMU -cpu I6400 /tmp/test_msa_ceq_w +$PATH_TO_QEMU -cpu I6400 /tmp/test_msa_ceq_d +$PATH_TO_QEMU -cpu I6400 /tmp/test_msa_cle_s_b +$PATH_TO_QEMU -cpu I6400 /tmp/test_msa_cle_s_h +$PATH_TO_QEMU -cpu I6400 /tmp/test_msa_cle_s_w +$PATH_TO_QEMU -cpu I6400 /tmp/test_msa_cle_s_d +$PATH_TO_QEMU -cpu I6400 /tmp/test_msa_cle_u_b +$PATH_TO_QEMU -cpu I6400 /tmp/test_msa_cle_u_h +$PATH_TO_QEMU -cpu I6400 /tmp/test_msa_cle_u_w +$PATH_TO_QEMU -cpu I6400 /tmp/test_msa_cle_u_d +$PATH_TO_QEMU -cpu I6400 /tmp/test_msa_clt_s_b +$PATH_TO_QEMU -cpu I6400 /tmp/test_msa_clt_s_h +$PATH_TO_QEMU -cpu I6400 /tmp/test_msa_clt_s_w +$PATH_TO_QEMU -cpu I6400 /tmp/test_msa_clt_s_d +$PATH_TO_QEMU -cpu I6400 /tmp/test_msa_clt_u_b +$PATH_TO_QEMU -cpu I6400 /tmp/test_msa_clt_u_h +$PATH_TO_QEMU -cpu I6400 /tmp/test_msa_clt_u_w +$PATH_TO_QEMU -cpu I6400 /tmp/test_msa_clt_u_d + +# +# Int Divide +# ---------- +# +$PATH_TO_QEMU -cpu I6400 /tmp/test_msa_div_s_b +$PATH_TO_QEMU -cpu I6400 /tmp/test_msa_div_s_h +$PATH_TO_QEMU -cpu I6400 /tmp/test_msa_div_s_w +$PATH_TO_QEMU -cpu I6400 /tmp/test_msa_div_s_d +$PATH_TO_QEMU -cpu I6400 /tmp/test_msa_div_u_b +$PATH_TO_QEMU -cpu I6400 /tmp/test_msa_div_u_h +$PATH_TO_QEMU -cpu I6400 /tmp/test_msa_div_u_w +$PATH_TO_QEMU -cpu I6400 /tmp/test_msa_div_u_d + +# +# Int Dot Product +# --------------- +# +$PATH_TO_QEMU -cpu I6400 /tmp/test_msa_dotp_s_h +$PATH_TO_QEMU -cpu I6400 /tmp/test_msa_dotp_s_w +$PATH_TO_QEMU -cpu I6400 /tmp/test_msa_dotp_s_d +$PATH_TO_QEMU -cpu I6400 /tmp/test_msa_dotp_u_h +$PATH_TO_QEMU -cpu I6400 /tmp/test_msa_dotp_u_w +$PATH_TO_QEMU -cpu I6400 /tmp/test_msa_dotp_u_d + +# +# Int Max Min +# ----------- +# +$PATH_TO_QEMU -cpu I6400 /tmp/test_msa_max_a_b +$PATH_TO_QEMU -cpu I6400 /tmp/test_msa_max_a_h +$PATH_TO_QEMU -cpu I6400 /tmp/test_msa_max_a_w +$PATH_TO_QEMU -cpu I6400 /tmp/test_msa_max_a_d +$PATH_TO_QEMU -cpu I6400 /tmp/test_msa_max_s_b +$PATH_TO_QEMU -cpu I6400 /tmp/test_msa_max_s_h +$PATH_TO_QEMU -cpu I6400 /tmp/test_msa_max_s_w +$PATH_TO_QEMU -cpu I6400 /tmp/test_msa_max_s_d +$PATH_TO_QEMU -cpu I6400 /tmp/test_msa_max_u_b +$PATH_TO_QEMU -cpu I6400 /tmp/test_msa_max_u_h +$PATH_TO_QEMU -cpu I6400 /tmp/test_msa_max_u_w +$PATH_TO_QEMU -cpu I6400 /tmp/test_msa_max_u_d +$PATH_TO_QEMU -cpu I6400 /tmp/test_msa_min_a_b +$PATH_TO_QEMU -cpu I6400 /tmp/test_msa_min_a_h +$PATH_TO_QEMU -cpu I6400 /tmp/test_msa_min_a_w +$PATH_TO_QEMU -cpu I6400 /tmp/test_msa_min_a_d +$PATH_TO_QEMU -cpu I6400 /tmp/test_msa_min_s_b +$PATH_TO_QEMU -cpu I6400 /tmp/test_msa_min_s_h +$PATH_TO_QEMU -cpu I6400 /tmp/test_msa_min_s_w +$PATH_TO_QEMU -cpu I6400 /tmp/test_msa_min_s_d +$PATH_TO_QEMU -cpu I6400 /tmp/test_msa_min_u_b +$PATH_TO_QEMU -cpu I6400 /tmp/test_msa_min_u_h +$PATH_TO_QEMU -cpu I6400 /tmp/test_msa_min_u_w +$PATH_TO_QEMU -cpu I6400 /tmp/test_msa_min_u_d + +# +# Int Modulo +# ---------- +# +$PATH_TO_QEMU -cpu I6400 /tmp/test_msa_mod_s_b +$PATH_TO_QEMU -cpu I6400 /tmp/test_msa_mod_s_h +$PATH_TO_QEMU -cpu I6400 /tmp/test_msa_mod_s_w +$PATH_TO_QEMU -cpu I6400 /tmp/test_msa_mod_s_d +$PATH_TO_QEMU -cpu I6400 /tmp/test_msa_mod_u_b +$PATH_TO_QEMU -cpu I6400 /tmp/test_msa_mod_u_h +$PATH_TO_QEMU -cpu I6400 /tmp/test_msa_mod_u_w +$PATH_TO_QEMU -cpu I6400 /tmp/test_msa_mod_u_d + +# +# Int Multiply +# ------------ +# +$PATH_TO_QEMU -cpu I6400 /tmp/test_msa_mulv_b +$PATH_TO_QEMU -cpu I6400 /tmp/test_msa_mulv_h +$PATH_TO_QEMU -cpu I6400 /tmp/test_msa_mulv_w +$PATH_TO_QEMU -cpu I6400 /tmp/test_msa_mulv_d + +# +# Int Subtract +# ------------ +# +$PATH_TO_QEMU -cpu I6400 /tmp/test_msa_asub_s_b +$PATH_TO_QEMU -cpu I6400 /tmp/test_msa_asub_s_h +$PATH_TO_QEMU -cpu I6400 /tmp/test_msa_asub_s_w +$PATH_TO_QEMU -cpu I6400 /tmp/test_msa_asub_s_d +$PATH_TO_QEMU -cpu I6400 /tmp/test_msa_asub_u_b +$PATH_TO_QEMU -cpu I6400 /tmp/test_msa_asub_u_h +$PATH_TO_QEMU -cpu I6400 /tmp/test_msa_asub_u_w +$PATH_TO_QEMU -cpu I6400 /tmp/test_msa_asub_u_d +$PATH_TO_QEMU -cpu I6400 /tmp/test_msa_hsub_s_h +$PATH_TO_QEMU -cpu I6400 /tmp/test_msa_hsub_s_w +$PATH_TO_QEMU -cpu I6400 /tmp/test_msa_hsub_s_d +$PATH_TO_QEMU -cpu I6400 /tmp/test_msa_hsub_u_h +$PATH_TO_QEMU -cpu I6400 /tmp/test_msa_hsub_u_w +$PATH_TO_QEMU -cpu I6400 /tmp/test_msa_hsub_u_d +$PATH_TO_QEMU -cpu I6400 /tmp/test_msa_subs_s_b +$PATH_TO_QEMU -cpu I6400 /tmp/test_msa_subs_s_h +$PATH_TO_QEMU -cpu I6400 /tmp/test_msa_subs_s_w +$PATH_TO_QEMU -cpu I6400 /tmp/test_msa_subs_s_d +$PATH_TO_QEMU -cpu I6400 /tmp/test_msa_subs_u_b +$PATH_TO_QEMU -cpu I6400 /tmp/test_msa_subs_u_h +$PATH_TO_QEMU -cpu I6400 /tmp/test_msa_subs_u_w +$PATH_TO_QEMU -cpu I6400 /tmp/test_msa_subs_u_d +$PATH_TO_QEMU -cpu I6400 /tmp/test_msa_subsuu_s_b +$PATH_TO_QEMU -cpu I6400 /tmp/test_msa_subsuu_s_h +$PATH_TO_QEMU -cpu I6400 /tmp/test_msa_subsuu_s_w +$PATH_TO_QEMU -cpu I6400 /tmp/test_msa_subsuu_s_d +$PATH_TO_QEMU -cpu I6400 /tmp/test_msa_subsus_u_b +$PATH_TO_QEMU -cpu I6400 /tmp/test_msa_subsus_u_h +$PATH_TO_QEMU -cpu I6400 /tmp/test_msa_subsus_u_w +$PATH_TO_QEMU -cpu I6400 /tmp/test_msa_subsus_u_d +$PATH_TO_QEMU -cpu I6400 /tmp/test_msa_subv_b +$PATH_TO_QEMU -cpu I6400 /tmp/test_msa_subv_h +$PATH_TO_QEMU -cpu I6400 /tmp/test_msa_subv_w +$PATH_TO_QEMU -cpu I6400 /tmp/test_msa_subv_d + +# +# Interleave +# ---------- +# +$PATH_TO_QEMU -cpu I6400 /tmp/test_msa_ilvev_b +$PATH_TO_QEMU -cpu I6400 /tmp/test_msa_ilvev_h +$PATH_TO_QEMU -cpu I6400 /tmp/test_msa_ilvev_w +$PATH_TO_QEMU -cpu I6400 /tmp/test_msa_ilvev_d +$PATH_TO_QEMU -cpu I6400 /tmp/test_msa_ilvod_b +$PATH_TO_QEMU -cpu I6400 /tmp/test_msa_ilvod_h +$PATH_TO_QEMU -cpu I6400 /tmp/test_msa_ilvod_w +$PATH_TO_QEMU -cpu I6400 /tmp/test_msa_ilvod_d +$PATH_TO_QEMU -cpu I6400 /tmp/test_msa_ilvl_b +$PATH_TO_QEMU -cpu I6400 /tmp/test_msa_ilvl_h +$PATH_TO_QEMU -cpu I6400 /tmp/test_msa_ilvl_w +$PATH_TO_QEMU -cpu I6400 /tmp/test_msa_ilvl_d +$PATH_TO_QEMU -cpu I6400 /tmp/test_msa_ilvr_b +$PATH_TO_QEMU -cpu I6400 /tmp/test_msa_ilvr_h +$PATH_TO_QEMU -cpu I6400 /tmp/test_msa_ilvr_w +$PATH_TO_QEMU -cpu I6400 /tmp/test_msa_ilvr_d + +# +# Logic +# ----- +# +$PATH_TO_QEMU -cpu I6400 /tmp/test_msa_and_v +$PATH_TO_QEMU -cpu I6400 /tmp/test_msa_nor_v +$PATH_TO_QEMU -cpu I6400 /tmp/test_msa_or_v +$PATH_TO_QEMU -cpu I6400 /tmp/test_msa_xor_v + +# +# Pack +# ---- +# +$PATH_TO_QEMU -cpu I6400 /tmp/test_msa_pckev_b +$PATH_TO_QEMU -cpu I6400 /tmp/test_msa_pckev_h +$PATH_TO_QEMU -cpu I6400 /tmp/test_msa_pckev_w +$PATH_TO_QEMU -cpu I6400 /tmp/test_msa_pckev_d +$PATH_TO_QEMU -cpu I6400 /tmp/test_msa_pckod_b +$PATH_TO_QEMU -cpu I6400 /tmp/test_msa_pckod_h +$PATH_TO_QEMU -cpu I6400 /tmp/test_msa_pckod_w +$PATH_TO_QEMU -cpu I6400 /tmp/test_msa_pckod_d +$PATH_TO_QEMU -cpu I6400 /tmp/test_msa_vshf_b +$PATH_TO_QEMU -cpu I6400 /tmp/test_msa_vshf_h +$PATH_TO_QEMU -cpu I6400 /tmp/test_msa_vshf_w +$PATH_TO_QEMU -cpu I6400 /tmp/test_msa_vshf_d + +# +# Shift +# ----- +# +$PATH_TO_QEMU -cpu I6400 /tmp/test_msa_sll_b +$PATH_TO_QEMU -cpu I6400 /tmp/test_msa_sll_h +$PATH_TO_QEMU -cpu I6400 /tmp/test_msa_sll_w +$PATH_TO_QEMU -cpu I6400 /tmp/test_msa_sll_d +$PATH_TO_QEMU -cpu I6400 /tmp/test_msa_sra_b +$PATH_TO_QEMU -cpu I6400 /tmp/test_msa_sra_h +$PATH_TO_QEMU -cpu I6400 /tmp/test_msa_sra_w +$PATH_TO_QEMU -cpu I6400 /tmp/test_msa_sra_d +$PATH_TO_QEMU -cpu I6400 /tmp/test_msa_srar_b +$PATH_TO_QEMU -cpu I6400 /tmp/test_msa_srar_h +$PATH_TO_QEMU -cpu I6400 /tmp/test_msa_srar_w +$PATH_TO_QEMU -cpu I6400 /tmp/test_msa_srar_d +$PATH_TO_QEMU -cpu I6400 /tmp/test_msa_srl_b +$PATH_TO_QEMU -cpu I6400 /tmp/test_msa_srl_h +$PATH_TO_QEMU -cpu I6400 /tmp/test_msa_srl_w +$PATH_TO_QEMU -cpu I6400 /tmp/test_msa_srl_d +$PATH_TO_QEMU -cpu I6400 /tmp/test_msa_srlr_b +$PATH_TO_QEMU -cpu I6400 /tmp/test_msa_srlr_h +$PATH_TO_QEMU -cpu I6400 /tmp/test_msa_srlr_w +$PATH_TO_QEMU -cpu I6400 /tmp/test_msa_srlr_d 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; +} diff --git a/tests/tcg/ppc/Makefile.include b/tests/tcg/ppc/Makefile.include index b062c30dd3..ae01fb8fad 100644 --- a/tests/tcg/ppc/Makefile.include +++ b/tests/tcg/ppc/Makefile.include @@ -1,6 +1,9 @@ ifeq ($(TARGET_NAME),ppc) DOCKER_IMAGE=debian-powerpc-cross DOCKER_CROSS_COMPILER=powerpc-linux-gnu-gcc +else ifeq ($(TARGET_NAME),ppc64) +DOCKER_IMAGE=debian-ppc64-cross +DOCKER_CROSS_COMPILER=powerpc64-linux-gnu-gcc else ifeq ($(TARGET_NAME),ppc64le) DOCKER_IMAGE=debian-ppc64el-cross DOCKER_CROSS_COMPILER=powerpc64le-linux-gnu-gcc diff --git a/tests/test-bdrv-drain.c b/tests/test-bdrv-drain.c index eda90750eb..12e2ecf517 100644 --- a/tests/test-bdrv-drain.c +++ b/tests/test-bdrv-drain.c @@ -206,7 +206,7 @@ static void test_drv_cb_common(enum drain_type drain_type, bool recursive) QEMUIOVector qiov = QEMU_IOVEC_INIT_BUF(qiov, NULL, 0); - blk = blk_new(BLK_PERM_ALL, BLK_PERM_ALL); + blk = blk_new(qemu_get_aio_context(), BLK_PERM_ALL, BLK_PERM_ALL); bs = bdrv_new_open_driver(&bdrv_test, "test-node", BDRV_O_RDWR, &error_abort); s = bs->opaque; @@ -290,7 +290,7 @@ static void test_quiesce_common(enum drain_type drain_type, bool recursive) BlockBackend *blk; BlockDriverState *bs, *backing; - blk = blk_new(BLK_PERM_ALL, BLK_PERM_ALL); + blk = blk_new(qemu_get_aio_context(), BLK_PERM_ALL, BLK_PERM_ALL); bs = bdrv_new_open_driver(&bdrv_test, "test-node", BDRV_O_RDWR, &error_abort); blk_insert_bs(blk, bs, &error_abort); @@ -353,7 +353,7 @@ static void test_nested(void) BDRVTestState *s, *backing_s; enum drain_type outer, inner; - blk = blk_new(BLK_PERM_ALL, BLK_PERM_ALL); + blk = blk_new(qemu_get_aio_context(), BLK_PERM_ALL, BLK_PERM_ALL); bs = bdrv_new_open_driver(&bdrv_test, "test-node", BDRV_O_RDWR, &error_abort); s = bs->opaque; @@ -402,13 +402,13 @@ static void test_multiparent(void) BlockDriverState *bs_a, *bs_b, *backing; BDRVTestState *a_s, *b_s, *backing_s; - blk_a = blk_new(BLK_PERM_ALL, BLK_PERM_ALL); + blk_a = blk_new(qemu_get_aio_context(), BLK_PERM_ALL, BLK_PERM_ALL); bs_a = bdrv_new_open_driver(&bdrv_test, "test-node-a", BDRV_O_RDWR, &error_abort); a_s = bs_a->opaque; blk_insert_bs(blk_a, bs_a, &error_abort); - blk_b = blk_new(BLK_PERM_ALL, BLK_PERM_ALL); + blk_b = blk_new(qemu_get_aio_context(), BLK_PERM_ALL, BLK_PERM_ALL); bs_b = bdrv_new_open_driver(&bdrv_test, "test-node-b", BDRV_O_RDWR, &error_abort); b_s = bs_b->opaque; @@ -475,13 +475,13 @@ static void test_graph_change_drain_subtree(void) BlockDriverState *bs_a, *bs_b, *backing; BDRVTestState *a_s, *b_s, *backing_s; - blk_a = blk_new(BLK_PERM_ALL, BLK_PERM_ALL); + blk_a = blk_new(qemu_get_aio_context(), BLK_PERM_ALL, BLK_PERM_ALL); bs_a = bdrv_new_open_driver(&bdrv_test, "test-node-a", BDRV_O_RDWR, &error_abort); a_s = bs_a->opaque; blk_insert_bs(blk_a, bs_a, &error_abort); - blk_b = blk_new(BLK_PERM_ALL, BLK_PERM_ALL); + blk_b = blk_new(qemu_get_aio_context(), BLK_PERM_ALL, BLK_PERM_ALL); bs_b = bdrv_new_open_driver(&bdrv_test, "test-node-b", BDRV_O_RDWR, &error_abort); b_s = bs_b->opaque; @@ -555,7 +555,7 @@ static void test_graph_change_drain_all(void) BDRVTestState *a_s, *b_s; /* Create node A with a BlockBackend */ - blk_a = blk_new(BLK_PERM_ALL, BLK_PERM_ALL); + blk_a = blk_new(qemu_get_aio_context(), BLK_PERM_ALL, BLK_PERM_ALL); bs_a = bdrv_new_open_driver(&bdrv_test, "test-node-a", BDRV_O_RDWR, &error_abort); a_s = bs_a->opaque; @@ -571,7 +571,7 @@ static void test_graph_change_drain_all(void) g_assert_cmpint(a_s->drain_count, ==, 1); /* Create node B with a BlockBackend */ - blk_b = blk_new(BLK_PERM_ALL, BLK_PERM_ALL); + blk_b = blk_new(qemu_get_aio_context(), BLK_PERM_ALL, BLK_PERM_ALL); bs_b = bdrv_new_open_driver(&bdrv_test, "test-node-b", BDRV_O_RDWR, &error_abort); b_s = bs_b->opaque; @@ -672,13 +672,13 @@ static void test_iothread_common(enum drain_type drain_type, int drain_thread) goto out; } - blk = blk_new(BLK_PERM_ALL, BLK_PERM_ALL); + blk = blk_new(qemu_get_aio_context(), BLK_PERM_ALL, BLK_PERM_ALL); bs = bdrv_new_open_driver(&bdrv_test, "test-node", BDRV_O_RDWR, &error_abort); s = bs->opaque; blk_insert_bs(blk, bs, &error_abort); - blk_set_aio_context(blk, ctx_a); + blk_set_aio_context(blk, ctx_a, &error_abort); aio_context_acquire(ctx_a); s->bh_indirection_ctx = ctx_b; @@ -742,7 +742,7 @@ static void test_iothread_common(enum drain_type drain_type, int drain_thread) } aio_context_acquire(ctx_a); - blk_set_aio_context(blk, qemu_get_aio_context()); + blk_set_aio_context(blk, qemu_get_aio_context(), &error_abort); aio_context_release(ctx_a); bdrv_unref(bs); @@ -883,7 +883,7 @@ static void test_blockjob_common_drain_node(enum drain_type drain_type, bdrv_set_backing_hd(src, src_backing, &error_abort); bdrv_unref(src_backing); - blk_src = blk_new(BLK_PERM_ALL, BLK_PERM_ALL); + blk_src = blk_new(qemu_get_aio_context(), BLK_PERM_ALL, BLK_PERM_ALL); blk_insert_bs(blk_src, src_overlay, &error_abort); switch (drain_node) { @@ -903,15 +903,16 @@ static void test_blockjob_common_drain_node(enum drain_type drain_type, if (use_iothread) { iothread = iothread_new(); ctx = iothread_get_aio_context(iothread); - blk_set_aio_context(blk_src, ctx); + blk_set_aio_context(blk_src, ctx, &error_abort); } else { ctx = qemu_get_aio_context(); } target = bdrv_new_open_driver(&bdrv_test, "target", BDRV_O_RDWR, &error_abort); - blk_target = blk_new(BLK_PERM_ALL, BLK_PERM_ALL); + blk_target = blk_new(qemu_get_aio_context(), BLK_PERM_ALL, BLK_PERM_ALL); blk_insert_bs(blk_target, target, &error_abort); + blk_set_allow_aio_context_change(blk_target, true); aio_context_acquire(ctx); tjob = block_job_create("job0", &test_job_driver, NULL, src, @@ -972,7 +973,7 @@ static void test_blockjob_common_drain_node(enum drain_type drain_type, g_assert_false(job->job.paused); g_assert_true(job->job.busy); /* We're in qemu_co_sleep_ns() */ - do_drain_begin(drain_type, target); + do_drain_begin_unlocked(drain_type, target); if (drain_type == BDRV_DRAIN_ALL) { /* bdrv_drain_all() drains both src and target */ @@ -983,7 +984,7 @@ static void test_blockjob_common_drain_node(enum drain_type drain_type, g_assert_true(job->job.paused); g_assert_false(job->job.busy); /* The job is paused */ - do_drain_end(drain_type, target); + do_drain_end_unlocked(drain_type, target); if (use_iothread) { /* paused is reset in the I/O thread, wait for it */ @@ -1001,7 +1002,8 @@ static void test_blockjob_common_drain_node(enum drain_type drain_type, g_assert_cmpint(ret, ==, (result == TEST_JOB_SUCCESS ? 0 : -EIO)); if (use_iothread) { - blk_set_aio_context(blk_src, qemu_get_aio_context()); + blk_set_aio_context(blk_src, qemu_get_aio_context(), &error_abort); + assert(blk_get_aio_context(blk_target) == qemu_get_aio_context()); } aio_context_release(ctx); @@ -1205,7 +1207,7 @@ static void do_test_delete_by_drain(bool detach_instead_of_delete, &error_abort); bdrv_attach_child(bs, null_bs, "null-child", &child_file, &error_abort); - blk = blk_new(BLK_PERM_ALL, BLK_PERM_ALL); + blk = blk_new(qemu_get_aio_context(), BLK_PERM_ALL, BLK_PERM_ALL); blk_insert_bs(blk, bs, &error_abort); /* Referenced by blk now */ @@ -1368,7 +1370,7 @@ static void test_detach_indirect(bool by_parent_cb) c = bdrv_new_open_driver(&bdrv_test, "c", BDRV_O_RDWR, &error_abort); /* blk is a BB for parent-a */ - blk = blk_new(BLK_PERM_ALL, BLK_PERM_ALL); + blk = blk_new(qemu_get_aio_context(), BLK_PERM_ALL, BLK_PERM_ALL); blk_insert_bs(blk, parent_a, &error_abort); bdrv_unref(parent_a); @@ -1436,12 +1438,6 @@ static void test_detach_indirect(bool by_parent_cb) bdrv_unref(parent_b); blk_unref(blk); - /* XXX Once bdrv_close() unref's children instead of just detaching them, - * this won't be necessary any more. */ - bdrv_unref(a); - bdrv_unref(a); - bdrv_unref(c); - g_assert_cmpint(a->refcnt, ==, 1); g_assert_cmpint(b->refcnt, ==, 1); g_assert_cmpint(c->refcnt, ==, 1); @@ -1466,7 +1462,7 @@ static void test_append_to_drained(void) BlockDriverState *base, *overlay; BDRVTestState *base_s, *overlay_s; - blk = blk_new(BLK_PERM_ALL, BLK_PERM_ALL); + blk = blk_new(qemu_get_aio_context(), BLK_PERM_ALL, BLK_PERM_ALL); base = bdrv_new_open_driver(&bdrv_test, "base", BDRV_O_RDWR, &error_abort); base_s = base->opaque; blk_insert_bs(blk, base, &error_abort); @@ -1513,16 +1509,16 @@ static void test_set_aio_context(void) &error_abort); bdrv_drained_begin(bs); - bdrv_set_aio_context(bs, ctx_a); + bdrv_try_set_aio_context(bs, ctx_a, &error_abort); aio_context_acquire(ctx_a); bdrv_drained_end(bs); bdrv_drained_begin(bs); - bdrv_set_aio_context(bs, ctx_b); + bdrv_try_set_aio_context(bs, ctx_b, &error_abort); aio_context_release(ctx_a); aio_context_acquire(ctx_b); - bdrv_set_aio_context(bs, qemu_get_aio_context()); + bdrv_try_set_aio_context(bs, qemu_get_aio_context(), &error_abort); aio_context_release(ctx_b); bdrv_drained_end(bs); diff --git a/tests/test-bdrv-graph-mod.c b/tests/test-bdrv-graph-mod.c index 283dc84869..cfeec36566 100644 --- a/tests/test-bdrv-graph-mod.c +++ b/tests/test-bdrv-graph-mod.c @@ -102,7 +102,8 @@ static void test_update_perm_tree(void) { Error *local_err = NULL; - BlockBackend *root = blk_new(BLK_PERM_WRITE | BLK_PERM_CONSISTENT_READ, + BlockBackend *root = blk_new(qemu_get_aio_context(), + BLK_PERM_WRITE | BLK_PERM_CONSISTENT_READ, BLK_PERM_ALL & ~BLK_PERM_WRITE); BlockDriverState *bs = no_perm_node("node"); BlockDriverState *filter = pass_through_node("filter"); @@ -116,7 +117,6 @@ static void test_update_perm_tree(void) g_assert_nonnull(local_err); error_free(local_err); - bdrv_unref(bs); blk_unref(root); } @@ -166,7 +166,7 @@ static void test_update_perm_tree(void) */ static void test_should_update_child(void) { - BlockBackend *root = blk_new(0, BLK_PERM_ALL); + BlockBackend *root = blk_new(qemu_get_aio_context(), 0, BLK_PERM_ALL); BlockDriverState *bs = no_perm_node("node"); BlockDriverState *filter = no_perm_node("filter"); BlockDriverState *target = no_perm_node("target"); diff --git a/tests/test-block-backend.c b/tests/test-block-backend.c index fd59f02bd0..5b5d6845c0 100644 --- a/tests/test-block-backend.c +++ b/tests/test-block-backend.c @@ -37,7 +37,8 @@ static void test_drain_aio_error_flush_cb(void *opaque, int ret) static void test_drain_aio_error(void) { - BlockBackend *blk = blk_new(BLK_PERM_ALL, BLK_PERM_ALL); + BlockBackend *blk = blk_new(qemu_get_aio_context(), + BLK_PERM_ALL, BLK_PERM_ALL); BlockAIOCB *acb; bool completed = false; @@ -53,7 +54,8 @@ static void test_drain_aio_error(void) static void test_drain_all_aio_error(void) { - BlockBackend *blk = blk_new(BLK_PERM_ALL, BLK_PERM_ALL); + BlockBackend *blk = blk_new(qemu_get_aio_context(), + BLK_PERM_ALL, BLK_PERM_ALL); BlockAIOCB *acb; bool completed = false; diff --git a/tests/test-block-iothread.c b/tests/test-block-iothread.c index 59f692892e..79d9cf8a57 100644 --- a/tests/test-block-iothread.c +++ b/tests/test-block-iothread.c @@ -336,20 +336,20 @@ static void test_sync_op(const void *opaque) BlockDriverState *bs; BdrvChild *c; - blk = blk_new(BLK_PERM_ALL, BLK_PERM_ALL); + blk = blk_new(qemu_get_aio_context(), BLK_PERM_ALL, BLK_PERM_ALL); bs = bdrv_new_open_driver(&bdrv_test, "base", BDRV_O_RDWR, &error_abort); bs->total_sectors = 65536 / BDRV_SECTOR_SIZE; blk_insert_bs(blk, bs, &error_abort); c = QLIST_FIRST(&bs->parents); - blk_set_aio_context(blk, ctx); + blk_set_aio_context(blk, ctx, &error_abort); aio_context_acquire(ctx); t->fn(c); if (t->blkfn) { t->blkfn(blk); } aio_context_release(ctx); - blk_set_aio_context(blk, qemu_get_aio_context()); + blk_set_aio_context(blk, qemu_get_aio_context(), &error_abort); bdrv_unref(bs); blk_unref(blk); @@ -415,7 +415,7 @@ static void test_attach_blockjob(void) BlockDriverState *bs; TestBlockJob *tjob; - blk = blk_new(BLK_PERM_ALL, BLK_PERM_ALL); + blk = blk_new(qemu_get_aio_context(), BLK_PERM_ALL, BLK_PERM_ALL); bs = bdrv_new_open_driver(&bdrv_test, "base", BDRV_O_RDWR, &error_abort); blk_insert_bs(blk, bs, &error_abort); @@ -428,7 +428,7 @@ static void test_attach_blockjob(void) aio_poll(qemu_get_aio_context(), false); } - blk_set_aio_context(blk, ctx); + blk_set_aio_context(blk, ctx, &error_abort); tjob->n = 0; while (tjob->n == 0) { @@ -436,7 +436,7 @@ static void test_attach_blockjob(void) } aio_context_acquire(ctx); - blk_set_aio_context(blk, qemu_get_aio_context()); + blk_set_aio_context(blk, qemu_get_aio_context(), &error_abort); aio_context_release(ctx); tjob->n = 0; @@ -444,7 +444,7 @@ static void test_attach_blockjob(void) aio_poll(qemu_get_aio_context(), false); } - blk_set_aio_context(blk, ctx); + blk_set_aio_context(blk, ctx, &error_abort); tjob->n = 0; while (tjob->n == 0) { @@ -453,7 +453,7 @@ static void test_attach_blockjob(void) aio_context_acquire(ctx); job_complete_sync(&tjob->common.job, &error_abort); - blk_set_aio_context(blk, qemu_get_aio_context()); + blk_set_aio_context(blk, qemu_get_aio_context(), &error_abort); aio_context_release(ctx); bdrv_unref(bs); @@ -481,7 +481,7 @@ static void test_propagate_basic(void) QDict *options; /* Create bs_a and its BlockBackend */ - blk = blk_new(BLK_PERM_ALL, BLK_PERM_ALL); + blk = blk_new(qemu_get_aio_context(), BLK_PERM_ALL, BLK_PERM_ALL); bs_a = bdrv_new_open_driver(&bdrv_test, "bs_a", BDRV_O_RDWR, &error_abort); blk_insert_bs(blk, bs_a, &error_abort); @@ -497,7 +497,7 @@ static void test_propagate_basic(void) bs_verify = bdrv_open(NULL, NULL, options, BDRV_O_RDWR, &error_abort); /* Switch the AioContext */ - blk_set_aio_context(blk, ctx); + blk_set_aio_context(blk, ctx, &error_abort); g_assert(blk_get_aio_context(blk) == ctx); g_assert(bdrv_get_aio_context(bs_a) == ctx); g_assert(bdrv_get_aio_context(bs_verify) == ctx); @@ -505,7 +505,7 @@ static void test_propagate_basic(void) /* Switch the AioContext back */ ctx = qemu_get_aio_context(); - blk_set_aio_context(blk, ctx); + blk_set_aio_context(blk, ctx, &error_abort); g_assert(blk_get_aio_context(blk) == ctx); g_assert(bdrv_get_aio_context(bs_a) == ctx); g_assert(bdrv_get_aio_context(bs_verify) == ctx); @@ -561,11 +561,11 @@ static void test_propagate_diamond(void) qdict_put_str(options, "raw", "bs_c"); bs_verify = bdrv_open(NULL, NULL, options, BDRV_O_RDWR, &error_abort); - blk = blk_new(BLK_PERM_ALL, BLK_PERM_ALL); + blk = blk_new(qemu_get_aio_context(), BLK_PERM_ALL, BLK_PERM_ALL); blk_insert_bs(blk, bs_verify, &error_abort); /* Switch the AioContext */ - blk_set_aio_context(blk, ctx); + blk_set_aio_context(blk, ctx, &error_abort); g_assert(blk_get_aio_context(blk) == ctx); g_assert(bdrv_get_aio_context(bs_verify) == ctx); g_assert(bdrv_get_aio_context(bs_a) == ctx); @@ -574,7 +574,7 @@ static void test_propagate_diamond(void) /* Switch the AioContext back */ ctx = qemu_get_aio_context(); - blk_set_aio_context(blk, ctx); + blk_set_aio_context(blk, ctx, &error_abort); g_assert(blk_get_aio_context(blk) == ctx); g_assert(bdrv_get_aio_context(bs_verify) == ctx); g_assert(bdrv_get_aio_context(bs_a) == ctx); @@ -593,7 +593,7 @@ static void test_propagate_mirror(void) IOThread *iothread = iothread_new(); AioContext *ctx = iothread_get_aio_context(iothread); AioContext *main_ctx = qemu_get_aio_context(); - BlockDriverState *src, *target; + BlockDriverState *src, *target, *filter; BlockBackend *blk; Job *job; Error *local_err = NULL; @@ -610,11 +610,13 @@ static void test_propagate_mirror(void) false, "filter_node", MIRROR_COPY_MODE_BACKGROUND, &error_abort); job = job_get("job0"); + filter = bdrv_find_node("filter_node"); /* Change the AioContext of src */ bdrv_try_set_aio_context(src, ctx, &error_abort); g_assert(bdrv_get_aio_context(src) == ctx); g_assert(bdrv_get_aio_context(target) == ctx); + g_assert(bdrv_get_aio_context(filter) == ctx); g_assert(job->aio_context == ctx); /* Change the AioContext of target */ @@ -623,9 +625,10 @@ static void test_propagate_mirror(void) aio_context_release(ctx); g_assert(bdrv_get_aio_context(src) == main_ctx); g_assert(bdrv_get_aio_context(target) == main_ctx); + g_assert(bdrv_get_aio_context(filter) == main_ctx); /* With a BlockBackend on src, changing target must fail */ - blk = blk_new(0, BLK_PERM_ALL); + blk = blk_new(qemu_get_aio_context(), 0, BLK_PERM_ALL); blk_insert_bs(blk, src, &error_abort); bdrv_try_set_aio_context(target, ctx, &local_err); @@ -635,6 +638,7 @@ static void test_propagate_mirror(void) g_assert(blk_get_aio_context(blk) == main_ctx); g_assert(bdrv_get_aio_context(src) == main_ctx); g_assert(bdrv_get_aio_context(target) == main_ctx); + g_assert(bdrv_get_aio_context(filter) == main_ctx); /* ...unless we explicitly allow it */ aio_context_acquire(ctx); @@ -645,11 +649,12 @@ static void test_propagate_mirror(void) g_assert(blk_get_aio_context(blk) == ctx); g_assert(bdrv_get_aio_context(src) == ctx); g_assert(bdrv_get_aio_context(target) == ctx); + g_assert(bdrv_get_aio_context(filter) == ctx); job_cancel_sync_all(); aio_context_acquire(ctx); - blk_set_aio_context(blk, main_ctx); + blk_set_aio_context(blk, main_ctx, &error_abort); bdrv_try_set_aio_context(target, main_ctx, &error_abort); aio_context_release(ctx); @@ -658,6 +663,69 @@ static void test_propagate_mirror(void) bdrv_unref(target); } +static void test_attach_second_node(void) +{ + IOThread *iothread = iothread_new(); + AioContext *ctx = iothread_get_aio_context(iothread); + AioContext *main_ctx = qemu_get_aio_context(); + BlockBackend *blk; + BlockDriverState *bs, *filter; + QDict *options; + + blk = blk_new(ctx, BLK_PERM_ALL, BLK_PERM_ALL); + bs = bdrv_new_open_driver(&bdrv_test, "base", BDRV_O_RDWR, &error_abort); + blk_insert_bs(blk, bs, &error_abort); + + options = qdict_new(); + qdict_put_str(options, "driver", "raw"); + qdict_put_str(options, "file", "base"); + + filter = bdrv_open(NULL, NULL, options, BDRV_O_RDWR, &error_abort); + g_assert(blk_get_aio_context(blk) == ctx); + g_assert(bdrv_get_aio_context(bs) == ctx); + g_assert(bdrv_get_aio_context(filter) == ctx); + + blk_set_aio_context(blk, main_ctx, &error_abort); + g_assert(blk_get_aio_context(blk) == main_ctx); + g_assert(bdrv_get_aio_context(bs) == main_ctx); + g_assert(bdrv_get_aio_context(filter) == main_ctx); + + bdrv_unref(filter); + bdrv_unref(bs); + blk_unref(blk); +} + +static void test_attach_preserve_blk_ctx(void) +{ + IOThread *iothread = iothread_new(); + AioContext *ctx = iothread_get_aio_context(iothread); + BlockBackend *blk; + BlockDriverState *bs; + + blk = blk_new(ctx, BLK_PERM_ALL, BLK_PERM_ALL); + bs = bdrv_new_open_driver(&bdrv_test, "base", BDRV_O_RDWR, &error_abort); + bs->total_sectors = 65536 / BDRV_SECTOR_SIZE; + + /* Add node to BlockBackend that has an iothread context assigned */ + blk_insert_bs(blk, bs, &error_abort); + g_assert(blk_get_aio_context(blk) == ctx); + g_assert(bdrv_get_aio_context(bs) == ctx); + + /* Remove the node again */ + blk_remove_bs(blk); + g_assert(blk_get_aio_context(blk) == ctx); + g_assert(bdrv_get_aio_context(bs) == qemu_get_aio_context()); + + /* Re-attach the node */ + blk_insert_bs(blk, bs, &error_abort); + g_assert(blk_get_aio_context(blk) == ctx); + g_assert(bdrv_get_aio_context(bs) == ctx); + + blk_set_aio_context(blk, qemu_get_aio_context(), &error_abort); + bdrv_unref(bs); + blk_unref(blk); +} + int main(int argc, char **argv) { int i; @@ -673,6 +741,8 @@ int main(int argc, char **argv) } g_test_add_func("/attach/blockjob", test_attach_blockjob); + g_test_add_func("/attach/second_node", test_attach_second_node); + g_test_add_func("/attach/preserve_blk_ctx", test_attach_preserve_blk_ctx); g_test_add_func("/propagate/basic", test_propagate_basic); g_test_add_func("/propagate/diamond", test_propagate_diamond); g_test_add_func("/propagate/mirror", test_propagate_mirror); diff --git a/tests/test-blockjob.c b/tests/test-blockjob.c index 652d1e8359..8c91980c70 100644 --- a/tests/test-blockjob.c +++ b/tests/test-blockjob.c @@ -68,7 +68,7 @@ static BlockJob *do_test_id(BlockBackend *blk, const char *id, static BlockBackend *create_blk(const char *name) { /* No I/O is performed on this device */ - BlockBackend *blk = blk_new(0, BLK_PERM_ALL); + BlockBackend *blk = blk_new(qemu_get_aio_context(), 0, BLK_PERM_ALL); BlockDriverState *bs; bs = bdrv_open("null-co://", NULL, NULL, 0, &error_abort); diff --git a/tests/test-thread-pool.c b/tests/test-thread-pool.c index 9cdccb3a47..0b675923f6 100644 --- a/tests/test-thread-pool.c +++ b/tests/test-thread-pool.c @@ -27,9 +27,10 @@ static int worker_cb(void *opaque) static int long_cb(void *opaque) { WorkerTestData *data = opaque; - atomic_inc(&data->n); - g_usleep(2000000); - atomic_inc(&data->n); + if (atomic_cmpxchg(&data->n, 0, 1) == 0) { + g_usleep(2000000); + atomic_or(&data->n, 2); + } return 0; } @@ -171,7 +172,7 @@ static void do_test_cancel(bool sync) /* Cancel the jobs that haven't been started yet. */ num_canceled = 0; for (i = 0; i < 100; i++) { - if (atomic_cmpxchg(&data[i].n, 0, 3) == 0) { + if (atomic_cmpxchg(&data[i].n, 0, 4) == 0) { data[i].ret = -ECANCELED; if (sync) { bdrv_aio_cancel(data[i].aiocb); @@ -185,7 +186,7 @@ static void do_test_cancel(bool sync) g_assert_cmpint(num_canceled, <, 100); for (i = 0; i < 100; i++) { - if (data[i].aiocb && data[i].n != 3) { + if (data[i].aiocb && atomic_read(&data[i].n) < 4) { if (sync) { /* Canceling the others will be a blocking operation. */ bdrv_aio_cancel(data[i].aiocb); @@ -201,13 +202,22 @@ static void do_test_cancel(bool sync) } g_assert_cmpint(active, ==, 0); for (i = 0; i < 100; i++) { - if (data[i].n == 3) { + g_assert(data[i].aiocb == NULL); + switch (data[i].n) { + case 0: + fprintf(stderr, "Callback not canceled but never started?\n"); + abort(); + case 3: + /* Couldn't be canceled asynchronously, must have completed. */ + g_assert_cmpint(data[i].ret, ==, 0); + break; + case 4: + /* Could be canceled asynchronously, never started. */ g_assert_cmpint(data[i].ret, ==, -ECANCELED); - g_assert(data[i].aiocb == NULL); - } else { - g_assert_cmpint(data[i].n, ==, 2); - g_assert(data[i].ret == 0 || data[i].ret == -ECANCELED); - g_assert(data[i].aiocb == NULL); + break; + default: + fprintf(stderr, "Callback aborted while running?\n"); + abort(); } } } diff --git a/tests/test-throttle.c b/tests/test-throttle.c index 948a42c991..5644cf95ca 100644 --- a/tests/test-throttle.c +++ b/tests/test-throttle.c @@ -675,9 +675,9 @@ static void test_groups(void) ThrottleGroupMember *tgm1, *tgm2, *tgm3; /* No actual I/O is performed on these devices */ - blk1 = blk_new(0, BLK_PERM_ALL); - blk2 = blk_new(0, BLK_PERM_ALL); - blk3 = blk_new(0, BLK_PERM_ALL); + blk1 = blk_new(qemu_get_aio_context(), 0, BLK_PERM_ALL); + blk2 = blk_new(qemu_get_aio_context(), 0, BLK_PERM_ALL); + blk3 = blk_new(qemu_get_aio_context(), 0, BLK_PERM_ALL); blkp1 = blk_get_public(blk1); blkp2 = blk_get_public(blk2); diff --git a/tests/tmp105-test.c b/tests/tmp105-test.c index 34cae7a582..f599309a4a 100644 --- a/tests/tmp105-test.c +++ b/tests/tmp105-test.c @@ -10,6 +10,7 @@ #include "qemu/osdep.h" #include "libqtest.h" +#include "libqos/qgraph.h" #include "libqos/i2c.h" #include "qapi/qmp/qdict.h" #include "hw/misc/tmp105_regs.h" @@ -17,52 +18,6 @@ #define TMP105_TEST_ID "tmp105-test" #define TMP105_TEST_ADDR 0x49 -static I2CAdapter *i2c; - -static uint16_t tmp105_get8(I2CAdapter *i2c, uint8_t addr, uint8_t reg) -{ - uint8_t resp[1]; - i2c_send(i2c, addr, ®, 1); - i2c_recv(i2c, addr, resp, 1); - return resp[0]; -} - -static uint16_t tmp105_get16(I2CAdapter *i2c, uint8_t addr, uint8_t reg) -{ - uint8_t resp[2]; - i2c_send(i2c, addr, ®, 1); - i2c_recv(i2c, addr, resp, 2); - return (resp[0] << 8) | resp[1]; -} - -static void tmp105_set8(I2CAdapter *i2c, uint8_t addr, uint8_t reg, - uint8_t value) -{ - uint8_t cmd[2]; - uint8_t resp[1]; - - cmd[0] = reg; - cmd[1] = value; - i2c_send(i2c, addr, cmd, 2); - i2c_recv(i2c, addr, resp, 1); - g_assert_cmphex(resp[0], ==, cmd[1]); -} - -static void tmp105_set16(I2CAdapter *i2c, uint8_t addr, uint8_t reg, - uint16_t value) -{ - uint8_t cmd[3]; - uint8_t resp[2]; - - cmd[0] = reg; - cmd[1] = value >> 8; - cmd[2] = value & 255; - i2c_send(i2c, addr, cmd, 3); - i2c_recv(i2c, addr, resp, 2); - g_assert_cmphex(resp[0], ==, cmd[1]); - g_assert_cmphex(resp[1], ==, cmd[2]); -} - static int qmp_tmp105_get_temperature(const char *id) { QDict *response; @@ -87,21 +42,22 @@ static void qmp_tmp105_set_temperature(const char *id, int value) } #define TMP105_PRECISION (1000/16) -static void send_and_receive(void) +static void send_and_receive(void *obj, void *data, QGuestAllocator *alloc) { uint16_t value; + QI2CDevice *i2cdev = (QI2CDevice *)obj; value = qmp_tmp105_get_temperature(TMP105_TEST_ID); g_assert_cmpuint(value, ==, 0); - value = tmp105_get16(i2c, TMP105_TEST_ADDR, TMP105_REG_TEMPERATURE); + value = i2c_get16(i2cdev, TMP105_REG_TEMPERATURE); g_assert_cmphex(value, ==, 0); qmp_tmp105_set_temperature(TMP105_TEST_ID, 20000); value = qmp_tmp105_get_temperature(TMP105_TEST_ID); g_assert_cmpuint(value, ==, 20000); - value = tmp105_get16(i2c, TMP105_TEST_ADDR, TMP105_REG_TEMPERATURE); + value = i2c_get16(i2cdev, TMP105_REG_TEMPERATURE); g_assert_cmphex(value, ==, 0x1400); qmp_tmp105_set_temperature(TMP105_TEST_ID, 20938); /* 20 + 15/16 */ @@ -110,24 +66,27 @@ static void send_and_receive(void) g_assert_cmpuint(value, <, 20938 + TMP105_PRECISION/2); /* Set config */ - tmp105_set8(i2c, TMP105_TEST_ADDR, TMP105_REG_CONFIG, 0x60); - value = tmp105_get8(i2c, TMP105_TEST_ADDR, TMP105_REG_CONFIG); + i2c_set8(i2cdev, TMP105_REG_CONFIG, 0x60); + value = i2c_get8(i2cdev, TMP105_REG_CONFIG); g_assert_cmphex(value, ==, 0x60); - value = tmp105_get16(i2c, TMP105_TEST_ADDR, TMP105_REG_TEMPERATURE); + value = i2c_get16(i2cdev, TMP105_REG_TEMPERATURE); g_assert_cmphex(value, ==, 0x14f0); /* Set precision to 9, 10, 11 bits. */ - tmp105_set8(i2c, TMP105_TEST_ADDR, TMP105_REG_CONFIG, 0x00); - value = tmp105_get16(i2c, TMP105_TEST_ADDR, TMP105_REG_TEMPERATURE); + i2c_set8(i2cdev, TMP105_REG_CONFIG, 0x00); + g_assert_cmphex(i2c_get8(i2cdev, TMP105_REG_CONFIG), ==, 0x00); + value = i2c_get16(i2cdev, TMP105_REG_TEMPERATURE); g_assert_cmphex(value, ==, 0x1480); - tmp105_set8(i2c, TMP105_TEST_ADDR, TMP105_REG_CONFIG, 0x20); - value = tmp105_get16(i2c, TMP105_TEST_ADDR, TMP105_REG_TEMPERATURE); + i2c_set8(i2cdev, TMP105_REG_CONFIG, 0x20); + g_assert_cmphex(i2c_get8(i2cdev, TMP105_REG_CONFIG), ==, 0x20); + value = i2c_get16(i2cdev, TMP105_REG_TEMPERATURE); g_assert_cmphex(value, ==, 0x14c0); - tmp105_set8(i2c, TMP105_TEST_ADDR, TMP105_REG_CONFIG, 0x40); - value = tmp105_get16(i2c, TMP105_TEST_ADDR, TMP105_REG_TEMPERATURE); + i2c_set8(i2cdev, TMP105_REG_CONFIG, 0x40); + g_assert_cmphex(i2c_get8(i2cdev, TMP105_REG_CONFIG), ==, 0x40); + value = i2c_get16(i2cdev, TMP105_REG_TEMPERATURE); g_assert_cmphex(value, ==, 0x14e0); /* stored precision remains the same */ @@ -135,32 +94,27 @@ static void send_and_receive(void) g_assert_cmpuint(value, >=, 20938 - TMP105_PRECISION/2); g_assert_cmpuint(value, <, 20938 + TMP105_PRECISION/2); - tmp105_set8(i2c, TMP105_TEST_ADDR, TMP105_REG_CONFIG, 0x60); - value = tmp105_get16(i2c, TMP105_TEST_ADDR, TMP105_REG_TEMPERATURE); + i2c_set8(i2cdev, TMP105_REG_CONFIG, 0x60); + g_assert_cmphex(i2c_get8(i2cdev, TMP105_REG_CONFIG), ==, 0x60); + value = i2c_get16(i2cdev, TMP105_REG_TEMPERATURE); g_assert_cmphex(value, ==, 0x14f0); - tmp105_set16(i2c, TMP105_TEST_ADDR, TMP105_REG_T_LOW, 0x1234); - tmp105_set16(i2c, TMP105_TEST_ADDR, TMP105_REG_T_HIGH, 0x4231); + i2c_set16(i2cdev, TMP105_REG_T_LOW, 0x1234); + g_assert_cmphex(i2c_get16(i2cdev, TMP105_REG_T_LOW), ==, 0x1234); + i2c_set16(i2cdev, TMP105_REG_T_HIGH, 0x4231); + g_assert_cmphex(i2c_get16(i2cdev, TMP105_REG_T_HIGH), ==, 0x4231); } -int main(int argc, char **argv) +static void tmp105_register_nodes(void) { - QTestState *s = NULL; - int ret; - - g_test_init(&argc, &argv, NULL); + QOSGraphEdgeOptions opts = { + .extra_device_opts = "id=" TMP105_TEST_ID ",address=0x49" + }; + add_qi2c_address(&opts, &(QI2CAddress) { 0x49 }); - s = qtest_start("-machine n800 " - "-device tmp105,bus=i2c-bus.0,id=" TMP105_TEST_ID - ",address=0x49"); - i2c = omap_i2c_create(s, OMAP2_I2C_1_BASE); + qos_node_create_driver("tmp105", i2c_device_create); + qos_node_consumes("tmp105", "i2c-bus", &opts); - qtest_add_func("/tmp105/tx-rx", send_and_receive); - - ret = g_test_run(); - - qtest_quit(s); - g_free(i2c); - - return ret; + qos_add_test("tx-rx", "tmp105", send_and_receive, NULL); } +libqos_init(tmp105_register_nodes); diff --git a/tests/virtio-scsi-test.c b/tests/virtio-scsi-test.c index 162b31c88d..1e535cb178 100644 --- a/tests/virtio-scsi-test.c +++ b/tests/virtio-scsi-test.c @@ -188,6 +188,53 @@ static void test_unaligned_write_same(void *obj, void *data, qvirtio_scsi_pci_free(vs); } +static void test_iothread_attach_node(void *obj, void *data, + QGuestAllocator *t_alloc) +{ + QVirtioSCSIPCI *scsi_pci = obj; + QVirtioSCSI *scsi = &scsi_pci->scsi; + QVirtioSCSIQueues *vs; + char tmp_path[] = "/tmp/qtest.XXXXXX"; + int fd; + int ret; + + uint8_t buf[512] = { 0 }; + const uint8_t write_cdb[VIRTIO_SCSI_CDB_SIZE] = { + /* WRITE(10) to LBA 0, transfer length 1 */ + 0x2a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00 + }; + + alloc = t_alloc; + vs = qvirtio_scsi_init(scsi->vdev); + + /* Create a temporary qcow2 overlay*/ + fd = mkstemp(tmp_path); + g_assert(fd >= 0); + close(fd); + + if (!have_qemu_img()) { + g_test_message("QTEST_QEMU_IMG not set or qemu-img missing; " + "skipping snapshot test"); + goto fail; + } + + mkqcow2(tmp_path, 64); + + /* Attach the overlay to the null0 node */ + qmp_assert_success("{'execute': 'blockdev-add', 'arguments': {" + " 'driver': 'qcow2', 'node-name': 'overlay'," + " 'backing': 'null0', 'file': {" + " 'driver': 'file', 'filename': %s}}}", tmp_path); + + /* Send a request to see if the AioContext is still right */ + ret = virtio_scsi_do_command(vs, write_cdb, NULL, 0, buf, 512, NULL); + g_assert_cmphex(ret, ==, 0); + +fail: + qvirtio_scsi_pci_free(vs); + unlink(tmp_path); +} + static void *virtio_scsi_hotplug_setup(GString *cmd_line, void *arg) { g_string_append(cmd_line, @@ -204,6 +251,15 @@ static void *virtio_scsi_setup(GString *cmd_line, void *arg) return arg; } +static void *virtio_scsi_setup_iothread(GString *cmd_line, void *arg) +{ + g_string_append(cmd_line, + " -object iothread,id=thread0" + " -blockdev driver=null-co,node-name=null0" + " -device scsi-hd,drive=null0"); + return arg; +} + static void register_virtio_scsi_test(void) { QOSGraphTestOptions opts = { }; @@ -214,6 +270,13 @@ static void register_virtio_scsi_test(void) opts.before = virtio_scsi_setup; qos_add_test("unaligned-write-same", "virtio-scsi", test_unaligned_write_same, &opts); + + opts.before = virtio_scsi_setup_iothread; + opts.edge = (QOSGraphEdgeOptions) { + .extra_device_opts = "iothread=thread0", + }; + qos_add_test("iothread-attach-node", "virtio-scsi-pci", + test_iothread_attach_node, &opts); } libqos_init(register_virtio_scsi_test); diff --git a/ui/curses.c b/ui/curses.c index 1f3fcabb00..e9319eb8ae 100644 --- a/ui/curses.c +++ b/ui/curses.c @@ -489,9 +489,9 @@ static uint16_t get_ucs(wchar_t wch, iconv_t conv) memset(&ps, 0, sizeof(ps)); ret = wcrtomb(mbch, wch, &ps); if (ret == -1) { - fprintf(stderr, "Could not convert 0x%04x " + fprintf(stderr, "Could not convert 0x%04lx " "from wchar_t to a multibyte character: %s\n", - wch, strerror(errno)); + (unsigned long)wch, strerror(errno)); return 0xFFFD; } @@ -501,9 +501,9 @@ static uint16_t get_ucs(wchar_t wch, iconv_t conv) such = sizeof(uch); if (iconv(conv, &pmbch, &smbch, &puch, &such) == (size_t) -1) { - fprintf(stderr, "Could not convert 0x%04x " + fprintf(stderr, "Could not convert 0x%04lx " "from a multibyte character to UCS-2 : %s\n", - wch, strerror(errno)); + (unsigned long)wch, strerror(errno)); return 0xFFFD; } diff --git a/ui/egl-helpers.c b/ui/egl-helpers.c index e90eef8c9c..edc53f6d34 100644 --- a/ui/egl-helpers.c +++ b/ui/egl-helpers.c @@ -200,7 +200,8 @@ err: return -1; } -int egl_get_fd_for_texture(uint32_t tex_id, EGLint *stride, EGLint *fourcc) +int egl_get_fd_for_texture(uint32_t tex_id, EGLint *stride, EGLint *fourcc, + EGLuint64KHR *modifier) { EGLImageKHR image; EGLint num_planes, fd; @@ -214,7 +215,7 @@ int egl_get_fd_for_texture(uint32_t tex_id, EGLint *stride, EGLint *fourcc) } eglExportDMABUFImageQueryMESA(qemu_egl_display, image, fourcc, - &num_planes, NULL); + &num_planes, modifier); if (num_planes != 1) { eglDestroyImageKHR(qemu_egl_display, image); return -1; @@ -228,20 +229,36 @@ int egl_get_fd_for_texture(uint32_t tex_id, EGLint *stride, EGLint *fourcc) void egl_dmabuf_import_texture(QemuDmaBuf *dmabuf) { EGLImageKHR image = EGL_NO_IMAGE_KHR; - EGLint attrs[] = { - EGL_DMA_BUF_PLANE0_FD_EXT, dmabuf->fd, - EGL_DMA_BUF_PLANE0_PITCH_EXT, dmabuf->stride, - EGL_DMA_BUF_PLANE0_OFFSET_EXT, 0, - EGL_WIDTH, dmabuf->width, - EGL_HEIGHT, dmabuf->height, - EGL_LINUX_DRM_FOURCC_EXT, dmabuf->fourcc, - EGL_NONE, /* end of list */ - }; + EGLint attrs[64]; + int i = 0; if (dmabuf->texture != 0) { return; } + attrs[i++] = EGL_WIDTH; + attrs[i++] = dmabuf->width; + attrs[i++] = EGL_HEIGHT; + attrs[i++] = dmabuf->height; + attrs[i++] = EGL_LINUX_DRM_FOURCC_EXT; + attrs[i++] = dmabuf->fourcc; + + attrs[i++] = EGL_DMA_BUF_PLANE0_FD_EXT; + attrs[i++] = dmabuf->fd; + attrs[i++] = EGL_DMA_BUF_PLANE0_PITCH_EXT; + attrs[i++] = dmabuf->stride; + attrs[i++] = EGL_DMA_BUF_PLANE0_OFFSET_EXT; + attrs[i++] = 0; +#ifdef EGL_DMA_BUF_PLANE0_MODIFIER_LO_EXT + if (dmabuf->modifier) { + attrs[i++] = EGL_DMA_BUF_PLANE0_MODIFIER_LO_EXT; + attrs[i++] = (dmabuf->modifier >> 0) & 0xffffffff; + attrs[i++] = EGL_DMA_BUF_PLANE0_MODIFIER_HI_EXT; + attrs[i++] = (dmabuf->modifier >> 32) & 0xffffffff; + } +#endif + attrs[i++] = EGL_NONE; + image = eglCreateImageKHR(qemu_egl_display, EGL_NO_CONTEXT, EGL_LINUX_DMA_BUF_EXT, diff --git a/ui/spice-app.c b/ui/spice-app.c index 925b27b708..30541b1022 100644 --- a/ui/spice-app.c +++ b/ui/spice-app.c @@ -157,9 +157,10 @@ static void spice_app_display_early_init(DisplayOptions *opts) qemu_opt_set(qopts, "addr", sock_path, &error_abort); qemu_opt_set(qopts, "image-compression", "off", &error_abort); qemu_opt_set(qopts, "streaming-video", "off", &error_abort); +#ifdef CONFIG_OPENGL qemu_opt_set(qopts, "gl", opts->has_gl ? "on" : "off", &error_abort); display_opengl = opts->has_gl; - +#endif be->u.spiceport.data->fqdn = g_strdup("org.qemu.monitor.qmp.0"); qemu_chardev_new("org.qemu.monitor.qmp", TYPE_CHARDEV_SPICEPORT, be, NULL, &error_abort); diff --git a/ui/spice-display.c b/ui/spice-display.c index a5e26479a8..104df23025 100644 --- a/ui/spice-display.c +++ b/ui/spice-display.c @@ -888,7 +888,8 @@ static void spice_gl_switch(DisplayChangeListener *dcl, if (ssd->ds) { surface_gl_create_texture(ssd->gls, ssd->ds); fd = egl_get_fd_for_texture(ssd->ds->texture, - &stride, &fourcc); + &stride, &fourcc, + NULL); if (fd < 0) { surface_gl_destroy_texture(ssd->gls, ssd->ds); return; @@ -945,7 +946,7 @@ static void qemu_spice_gl_scanout_texture(DisplayChangeListener *dcl, int fd = -1; assert(tex_id); - fd = egl_get_fd_for_texture(tex_id, &stride, &fourcc); + fd = egl_get_fd_for_texture(tex_id, &stride, &fourcc, NULL); if (fd < 0) { fprintf(stderr, "%s: failed to get fd for texture\n", __func__); return; @@ -1063,7 +1064,7 @@ static void qemu_spice_gl_update(DisplayChangeListener *dcl, egl_fb_setup_new_tex(&ssd->blit_fb, dmabuf->width, dmabuf->height); fd = egl_get_fd_for_texture(ssd->blit_fb.texture, - &stride, &fourcc); + &stride, &fourcc, NULL); spice_qxl_gl_scanout(&ssd->qxl, fd, dmabuf->width, dmabuf->height, stride, fourcc, false); diff --git a/util/Makefile.objs b/util/Makefile.objs index c27a923dbe..38178201ff 100644 --- a/util/Makefile.objs +++ b/util/Makefile.objs @@ -53,7 +53,7 @@ util-obj-y += systemd.o util-obj-y += iova-tree.o util-obj-$(CONFIG_INOTIFY1) += filemonitor-inotify.o util-obj-$(CONFIG_LINUX) += vfio-helpers.o -util-obj-$(CONFIG_OPENGL) += drm.o +util-obj-$(CONFIG_POSIX) += drm.o util-obj-y += guest-random.o stub-obj-y += filemonitor-stub.o diff --git a/util/guest-random.c b/util/guest-random.c index e8124a3cad..00a08fd981 100644 --- a/util/guest-random.c +++ b/util/guest-random.c @@ -56,7 +56,7 @@ int qemu_guest_getrandom(void *buf, size_t len, Error **errp) void qemu_guest_getrandom_nofail(void *buf, size_t len) { - qemu_guest_getrandom(buf, len, &error_fatal); + (void)qemu_guest_getrandom(buf, len, &error_fatal); } uint64_t qemu_guest_random_seed_thread_part1(void) @@ -116,7 +116,7 @@ int main(int argc, char **argv) #include "qapi/opts-visitor.h" #include "qapi/clone-visitor.h" #include "qom/object_interfaces.h" -#include "exec/semihost.h" +#include "hw/semihosting/semihost.h" #include "crypto/init.h" #include "sysemu/replay.h" #include "qapi/qapi-events-run-state.h" @@ -239,6 +239,7 @@ static struct { { .driver = "qxl-vga", .flag = &default_vga }, { .driver = "virtio-vga", .flag = &default_vga }, { .driver = "ati-vga", .flag = &default_vga }, + { .driver = "vhost-user-vga", .flag = &default_vga }, }; static QemuOptsList qemu_rtc_opts = { @@ -501,25 +502,6 @@ static QemuOptsList qemu_icount_opts = { }, }; -static QemuOptsList qemu_semihosting_config_opts = { - .name = "semihosting-config", - .implied_opt_name = "enable", - .head = QTAILQ_HEAD_INITIALIZER(qemu_semihosting_config_opts.head), - .desc = { - { - .name = "enable", - .type = QEMU_OPT_BOOL, - }, { - .name = "target", - .type = QEMU_OPT_STRING, - }, { - .name = "arg", - .type = QEMU_OPT_STRING, - }, - { /* end of list */ } - }, -}; - static QemuOptsList qemu_fw_cfg_opts = { .name = "fw_cfg", .implied_opt_name = "name", @@ -1351,80 +1333,6 @@ static void configure_msg(QemuOpts *opts) enable_timestamp_msg = qemu_opt_get_bool(opts, "timestamp", true); } -/***********************************************************/ -/* Semihosting */ - -typedef struct SemihostingConfig { - bool enabled; - SemihostingTarget target; - const char **argv; - int argc; - const char *cmdline; /* concatenated argv */ -} SemihostingConfig; - -static SemihostingConfig semihosting; - -bool semihosting_enabled(void) -{ - return semihosting.enabled; -} - -SemihostingTarget semihosting_get_target(void) -{ - return semihosting.target; -} - -const char *semihosting_get_arg(int i) -{ - if (i >= semihosting.argc) { - return NULL; - } - return semihosting.argv[i]; -} - -int semihosting_get_argc(void) -{ - return semihosting.argc; -} - -const char *semihosting_get_cmdline(void) -{ - if (semihosting.cmdline == NULL && semihosting.argc > 0) { - semihosting.cmdline = g_strjoinv(" ", (gchar **)semihosting.argv); - } - return semihosting.cmdline; -} - -static int add_semihosting_arg(void *opaque, - const char *name, const char *val, - Error **errp) -{ - SemihostingConfig *s = opaque; - if (strcmp(name, "arg") == 0) { - s->argc++; - /* one extra element as g_strjoinv() expects NULL-terminated array */ - s->argv = g_realloc(s->argv, (s->argc + 1) * sizeof(void *)); - s->argv[s->argc - 1] = val; - s->argv[s->argc] = NULL; - } - return 0; -} - -/* Use strings passed via -kernel/-append to initialize semihosting.argv[] */ -static inline void semihosting_arg_fallback(const char *file, const char *cmd) -{ - char *cmd_token; - - /* argv[0] */ - add_semihosting_arg(&semihosting, "arg", file, NULL); - - /* split -append and initialize argv[1..n] */ - cmd_token = strtok(g_strdup(cmd), " "); - while (cmd_token) { - add_semihosting_arg(&semihosting, "arg", cmd_token, NULL); - cmd_token = strtok(NULL, " "); - } -} /* Now we still need this for compatibility with XEN. */ bool has_igd_gfx_passthru; @@ -2843,20 +2751,25 @@ static bool object_create_initial(const char *type, QemuOpts *opts) exit(0); } - if (g_str_equal(type, "rng-egd") || - g_str_has_prefix(type, "pr-manager-")) { + /* + * Objects should not be made "delayed" without a reason. If you + * add one, state the reason in a comment! + */ + + /* Reason: rng-egd property "chardev" */ + if (g_str_equal(type, "rng-egd")) { return false; } #if defined(CONFIG_VHOST_USER) && defined(CONFIG_LINUX) + /* Reason: cryptodev-vhost-user property "chardev" */ if (g_str_equal(type, "cryptodev-vhost-user")) { return false; } #endif /* - * return false for concrete netfilters since - * they depend on netdevs already existing + * Reason: filter-* property "netdev" etc. */ if (g_str_equal(type, "filter-buffer") || g_str_equal(type, "filter-dump") || @@ -3668,7 +3581,23 @@ int main(int argc, char **argv, char **envp) optarg, true); optarg = qemu_opt_get(accel_opts, "accel"); if (!optarg || is_help_option(optarg)) { - printf("Possible accelerators: kvm, xen, hax, tcg\n"); + printf("Accelerators supported in QEMU binary:\n"); + GSList *el, *accel_list = object_class_get_list(TYPE_ACCEL, + false); + for (el = accel_list; el; el = el->next) { + gchar *typename = g_strdup(object_class_get_name( + OBJECT_CLASS(el->data))); + /* omit qtest which is used for tests only */ + if (g_strcmp0(typename, ACCEL_CLASS_NAME("qtest")) && + g_str_has_suffix(typename, ACCEL_CLASS_SUFFIX)) { + gchar **optname = g_strsplit(typename, + ACCEL_CLASS_SUFFIX, 0); + printf("%s\n", optname[0]); + g_free(optname); + } + g_free(typename); + } + g_slist_free(accel_list); exit(0); } opts = qemu_opts_create(qemu_find_opts("machine"), NULL, @@ -3743,37 +3672,10 @@ int main(int argc, char **argv, char **envp) nb_option_roms++; break; case QEMU_OPTION_semihosting: - semihosting.enabled = true; - semihosting.target = SEMIHOSTING_TARGET_AUTO; + qemu_semihosting_enable(); break; case QEMU_OPTION_semihosting_config: - semihosting.enabled = true; - opts = qemu_opts_parse_noisily(qemu_find_opts("semihosting-config"), - optarg, false); - if (opts != NULL) { - semihosting.enabled = qemu_opt_get_bool(opts, "enable", - true); - const char *target = qemu_opt_get(opts, "target"); - if (target != NULL) { - if (strcmp("native", target) == 0) { - semihosting.target = SEMIHOSTING_TARGET_NATIVE; - } else if (strcmp("gdb", target) == 0) { - semihosting.target = SEMIHOSTING_TARGET_GDB; - } else if (strcmp("auto", target) == 0) { - semihosting.target = SEMIHOSTING_TARGET_AUTO; - } else { - error_report("unsupported semihosting-config %s", - optarg); - exit(1); - } - } else { - semihosting.target = SEMIHOSTING_TARGET_AUTO; - } - /* Set semihosting argument count and vector */ - qemu_opt_foreach(opts, add_semihosting_arg, - &semihosting, NULL); - } else { - error_report("unsupported semihosting-config %s", optarg); + if (qemu_semihosting_config_options(optarg) != 0) { exit(1); } break; @@ -4290,6 +4192,8 @@ int main(int argc, char **argv, char **envp) qemu_opts_foreach(qemu_find_opts("chardev"), chardev_init_func, NULL, &error_fatal); + /* now chardevs have been created we may have semihosting to connect */ + qemu_semihosting_connect_chardevs(); #ifdef CONFIG_VIRTFS qemu_opts_foreach(qemu_find_opts("fsdev"), |