Merge remote-tracking branch 'remotes/cleber/tags/python-next-pull-request' into staging
Python queue, 2019-02-22
Python:
* introduce "python" directory with module namespace
* log QEMU launch command line on qemu.QEMUMachine
Acceptance Tests:
* initrd 4GiB+ test
* migration test
* multi vm support in test class
* bump Avocado version and drop ":avocado: enable"
# gpg: Signature made Fri 22 Feb 2019 19:37:07 GMT
# gpg: using RSA key 657E8D33A5F209F3
# gpg: Good signature from "Cleber Rosa <crosa@redhat.com>" [marginal]
# gpg: WARNING: This key is not certified with sufficiently trusted signatures!
# gpg: It is not certain that the signature belongs to the owner.
# Primary key fingerprint: 7ABB 96EB 8B46 B94D 5E0F E9BB 657E 8D33 A5F2 09F3
* remotes/cleber/tags/python-next-pull-request:
Acceptance tests: expect boot to extract 2GiB+ initrd with linux-v4.16
Acceptance tests: use linux-3.6 and set vm memory to 4GiB
tests.acceptance: adds simple migration test
tests.acceptance: adds multi vm capability for acceptance tests
scripts/qemu.py: log QEMU launch command line
Introduce a Python module structure
Acceptance tests: drop usage of ":avocado: enable"
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
diff --git a/.gitignore b/.gitignore
index b66b772..7752256 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,3 +1,4 @@
+/.doctrees
/config-devices.*
/config-all-devices.*
/config-all-disas.*
diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
new file mode 100644
index 0000000..79d02cf
--- /dev/null
+++ b/.gitlab-ci.yml
@@ -0,0 +1,73 @@
+before_script:
+ - apt-get update -qq
+ - apt-get install -y -qq flex bison libglib2.0-dev libpixman-1-dev genisoimage
+
+build-system1:
+ script:
+ - apt-get install -y -qq libgtk-3-dev libvte-dev nettle-dev libcacard-dev
+ libusb-dev libvde-dev libspice-protocol-dev libgl1-mesa-dev
+ - ./configure --enable-werror --target-list="aarch64-softmmu alpha-softmmu
+ cris-softmmu hppa-softmmu lm32-softmmu moxie-softmmu microblazeel-softmmu
+ mips64el-softmmu m68k-softmmu ppc-softmmu riscv64-softmmu sparc-softmmu"
+ - make -j2
+ - make -j2 check
+
+build-system2:
+ script:
+ - apt-get install -y -qq libsdl2-dev libgcrypt-dev libbrlapi-dev libaio-dev
+ libfdt-dev liblzo2-dev librdmacm-dev libibverbs-dev libibumad-dev
+ - ./configure --enable-werror --target-list="tricore-softmmu unicore32-softmmu
+ microblaze-softmmu mips-softmmu riscv32-softmmu s390x-softmmu sh4-softmmu
+ sparc64-softmmu x86_64-softmmu xtensa-softmmu nios2-softmmu or1k-softmmu"
+ - make -j2
+ - make -j2 check
+
+build-disabled:
+ script:
+ - ./configure --enable-werror --disable-rdma --disable-slirp --disable-curl
+ --disable-capstone --disable-live-block-migration --disable-glusterfs
+ --disable-replication --disable-coroutine-pool --disable-smartcard
+ --disable-guest-agent --disable-curses --disable-libxml2 --disable-tpm
+ --disable-qom-cast-debug --disable-spice --disable-vhost-vsock
+ --disable-vhost-net --disable-vhost-crypto --disable-vhost-user
+ --target-list="i386-softmmu ppc64-softmmu mips64-softmmu i386-linux-user"
+ - make -j2
+ - make -j2 check-qtest SPEED=slow
+
+build-tcg-disabled:
+ script:
+ - apt-get install -y -qq clang libgtk-3-dev libbluetooth-dev libusb-dev
+ - ./configure --cc=clang --enable-werror --disable-tcg --audio-drv-list=""
+ - make -j2
+ - make check-unit
+ - make check-qapi-schema
+ - cd tests/qemu-iotests/
+ - ./check -raw 001 002 003 004 005 008 009 010 011 012 021 025 032 033 048
+ 052 063 077 086 101 104 106 113 147 148 150 151 152 157 159 160
+ 163 170 171 183 184 192 194 197 205 208 215 221 222 226 227 236
+ - ./check -qcow2 001 002 003 004 005 007 008 009 010 011 012 013 017 018 019
+ 020 021 022 024 025 027 028 029 031 032 033 034 035 036 037 038
+ 039 040 042 043 046 047 048 049 050 051 052 053 054 056 057 058
+ 060 061 062 063 065 066 067 068 069 071 072 073 074 079 080 082
+ 085 086 089 090 091 095 096 097 098 099 102 103 104 105 107 108
+ 110 111 114 117 120 122 124 126 127 129 130 132 133 134 137 138
+ 139 140 141 142 143 144 145 147 150 151 152 154 155 156 157 158
+ 161 165 170 172 174 176 177 179 184 186 187 190 192 194 195 196
+ 197 200 202 203 205 208 209 214 215 216 217 218 222 226 227 229 234
+
+build-user:
+ script:
+ - ./configure --enable-werror --disable-system --disable-guest-agent
+ --disable-capstone --disable-slirp --disable-fdt
+ - make -j2
+ - make run-tcg-tests-i386-linux-user run-tcg-tests-x86_64-linux-user
+
+build-clang:
+ script:
+ - apt-get install -y -qq clang libsdl2-dev
+ xfslibs-dev libiscsi-dev libnfs-dev libseccomp-dev gnutls-dev librbd-dev
+ - ./configure --cc=clang --cxx=clang++ --enable-werror
+ --target-list="alpha-softmmu arm-softmmu m68k-softmmu mips64-softmmu
+ ppc-softmmu s390x-softmmu x86_64-softmmu arm-linux-user"
+ - make -j2
+ - make -j2 check
diff --git a/.gitmodules b/.gitmodules
index 6b91176..ceafb0e 100644
--- a/.gitmodules
+++ b/.gitmodules
@@ -49,3 +49,6 @@
[submodule "tests/fp/berkeley-softfloat-3"]
path = tests/fp/berkeley-softfloat-3
url = https://github.com/cota/berkeley-softfloat-3
+[submodule "roms/edk2"]
+ path = roms/edk2
+ url = https://github.com/tianocore/edk2.git
diff --git a/.travis.yml b/.travis.yml
index baa06b9..cca57f4 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -86,11 +86,16 @@
- env:
- - CONFIG="--enable-debug --enable-debug-tcg"
+ - CONFIG="--enable-debug --enable-debug-tcg --disable-user"
+
+
+ # TCG debug can be run just on it's own and is mostly agnostic to user/softmmu distinctions
+ - env:
+ - CONFIG="--enable-debug-tcg --disable-system"
- env:
- - CONFIG="--disable-linux-aio --disable-cap-ng --disable-attr --disable-brlapi --disable-uuid --disable-libusb --disable-user"
+ - CONFIG="--disable-linux-aio --disable-cap-ng --disable-attr --disable-brlapi --disable-libusb --disable-user --disable-replication"
- env:
@@ -174,13 +179,6 @@
compiler: clang
- - env:
- - CONFIG="--target-list=i386-softmmu,ppc-softmmu,ppc64-softmmu,m68k-softmmu,x86_64-softmmu"
- os: osx
- osx_image: xcode10
- compiler: clang
-
-
# Python builds
- env:
- CONFIG="--target-list=x86_64-softmmu"
diff --git a/MAINTAINERS b/MAINTAINERS
index 6ae55ff..074ad46 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -425,15 +425,20 @@
------
LINUX
-L: qemu-devel@nongnu.org
+M: Michael S. Tsirkin <mst@redhat.com>
+M: Cornelia Huck <cohuck@redhat.com>
+M: Paolo Bonzini <pbonzini@redhat.com>
S: Maintained
-F: linux-*
F: linux-headers/
+F: scripts/update-linux-headers.sh
POSIX
-L: qemu-devel@nongnu.org
+M: Paolo Bonzini <pbonzini@redhat.com>
S: Maintained
-F: *posix*
+F: os-posix.c
+F: include/sysemu/os-posix.h
+F: util/*posix*.c
+F: include/qemu/*posix*.h
NETBSD
L: qemu-devel@nongnu.org
@@ -633,6 +638,8 @@
F: include/hw/misc/iotkit-sysinfo.h
F: hw/misc/armsse-cpuid.c
F: include/hw/misc/armsse-cpuid.h
+F: hw/misc/armsse-mhu.c
+F: include/hw/misc/armsse-mhu.h
Musca
M: Peter Maydell <peter.maydell@linaro.org>
@@ -851,6 +858,15 @@
F: hw/cris/axis_dev88.c
F: hw/*/etraxfs_*.c
+HP-PARISC Machines
+------------------
+Dino
+M: Richard Henderson <rth@twiddle.net>
+R: Helge Deller <deller@gmx.de>
+S: Odd Fixes
+F: hw/hppa/
+F: pc-bios/hppa-firmware.img
+
LM32 Machines
-------------
EVR32 and uclinux BSP
@@ -1089,20 +1105,27 @@
S: Maintained
F: hw/sparc/sun4m.c
F: hw/sparc/sun4m_iommu.c
+F: hw/display/cg3.c
+F: hw/display/tcx.c
F: hw/dma/sparc32_dma.c
F: hw/misc/eccmemctl.c
-F: hw/misc/slavio_misc.c
+F: hw/*/slavio_*.c
+F: include/hw/nvram/sun_nvram.h
F: include/hw/sparc/sparc32_dma.h
-F: pc-bios/openbios-sparc32
F: include/hw/sparc/sun4m_iommu.h
+F: pc-bios/openbios-sparc32
Sun4u
M: Mark Cave-Ayland <mark.cave-ayland@ilande.co.uk>
S: Maintained
F: hw/sparc64/sun4u.c
-F: pc-bios/openbios-sparc64
+F: hw/sparc64/sun4u_iommu.c
+F: include/hw/sparc/sun4u_iommu.h
F: hw/pci-host/sabre.c
F: include/hw/pci-host/sabre.h
+F: hw/pci-bridge/simba.c
+F: include/hw/pci-bridge/simba.h
+F: pc-bios/openbios-sparc64
Sun4v
M: Artyom Tarasenko <atar4qemu@gmail.com>
@@ -1181,6 +1204,10 @@
F: include/hw/acpi/ich9.h
F: include/hw/acpi/piix4.h
F: hw/misc/sga.c
+F: hw/isa/apm.c
+F: include/hw/isa/apm.h
+F: tests/test-x86-cpuid.c
+F: tests/test-x86-cpuid-compat.c
PC Chipset
M: Michael S. Tsirkin <mst@redhat.com>
@@ -1698,7 +1725,7 @@
F: scsi/*
Block Jobs
-M: Jeff Cody <jcody@redhat.com>
+M: John Snow <jsnow@redhat.com>
L: qemu-block@nongnu.org
S: Supported
F: blockjob.c
@@ -1711,7 +1738,7 @@
F: block/stream.c
F: block/mirror.c
F: qapi/job.json
-T: git https://github.com/codyprime/qemu-kvm-jtc.git block
+T: git https://github.com/jnsnow/qemu.git jobs
Block QAPI, monitor, command line
M: Markus Armbruster <armbru@redhat.com>
@@ -1795,8 +1822,7 @@
F: util/qemu-error.c
GDB stub
-L: qemu-devel@nongnu.org
-S: Odd Fixes
+S: Orphan
F: gdbstub*
F: gdb-xml/
@@ -1932,10 +1958,14 @@
X: include/qapi/qmp/dispatch.h
F: scripts/coccinelle/qobject.cocci
F: tests/check-qdict.c
-F: tests/check-qnum.c
F: tests/check-qjson.c
F: tests/check-qlist.c
+F: tests/check-qlit.c
+F: tests/check-qnull.c
+F: tests/check-qnum.c
+F: tests/check-qobject.c
F: tests/check-qstring.c
+F: qdict-test-data.txt
T: git https://repo.or.cz/qemu/armbru.git qapi-next
QEMU Guest Agent
@@ -2057,6 +2087,8 @@
F: include/crypto/
F: tests/test-crypto-*
F: tests/benchmark-crypto-*
+F: tests/crypto-tls-*
+F: tests/pkix_asn1_tab.c
F: qemu.sasl
Coroutines
@@ -2079,6 +2111,14 @@
F: include/io/
F: tests/test-io-*
+User authorization
+M: Daniel P. Berrange <berrange@redhat.com>
+S: Maintained
+F: authz/
+F: qapi/authz.json
+F: include/authz/
+F: tests/test-authz-*
+
Sockets
M: Daniel P. Berrange <berrange@redhat.com>
M: Gerd Hoffmann <kraxel@redhat.com>
@@ -2087,6 +2127,13 @@
F: util/qemu-sockets.c
F: qapi/sockets.json
+File monitor
+M: Daniel P. Berrange <berrange@redhat.com>
+S: Odd fixes
+F: util/filemonitor*.c
+F: include/qemu/filemonitor.h
+F: tests/test-util-filemonitor.c
+
Throttling infrastructure
M: Alberto Garcia <berto@igalia.com>
S: Supported
@@ -2145,6 +2192,18 @@
S: Maintained
F: contrib/elf2dmp/
+I2C and SMBus
+M: Corey Minyard <cminyard@mvista.com>
+S: Maintained
+F: hw/i2c/core.c
+F: hw/i2c/smbus_slave.c
+F: hw/i2c/smbus_master.c
+F: hw/i2c/smbus_eeprom.c
+F: include/hw/i2c/i2c.h
+F: include/hw/i2c/smbus_master.h
+F: include/hw/i2c/smbus_slave.h
+F: include/hw/i2c/smbus_eeprom.h
+
Usermode Emulation
------------------
Overall
@@ -2190,7 +2249,7 @@
F: disas/arm.c
i386 target
-L: qemu-devel@nongnu.org
+M: Richard Henderson <rth@twiddle.net>
S: Maintained
F: tcg/i386/
F: disas/i386.c
@@ -2209,7 +2268,6 @@
F: disas/ppc.c
RISC-V
-M: Michael Clark <mjc@sifive.com>
M: Palmer Dabbelt <palmer@sifive.com>
M: Alistair Francis <Alistair.Francis@wdc.com>
L: qemu-riscv@nongnu.org
@@ -2246,26 +2304,22 @@
RBD
M: Josh Durgin <jdurgin@redhat.com>
-M: Jeff Cody <jcody@redhat.com>
L: qemu-block@nongnu.org
S: Supported
F: block/rbd.c
-T: git https://github.com/codyprime/qemu-kvm-jtc.git block
Sheepdog
M: Liu Yuan <namei.unix@gmail.com>
-M: Jeff Cody <jcody@redhat.com>
L: qemu-block@nongnu.org
-S: Supported
+L: sheepdog@lists.wpkg.org
+S: Odd Fixes
F: block/sheepdog.c
-T: git https://github.com/codyprime/qemu-kvm-jtc.git block
VHDX
-M: Jeff Cody <jcody@redhat.com>
+M: Jeff Cody <codyprime@gmail.com>
L: qemu-block@nongnu.org
S: Supported
F: block/vhdx*
-T: git https://github.com/codyprime/qemu-kvm-jtc.git block
VDI
M: Stefan Weil <sw@weilnetz.de>
@@ -2295,34 +2349,26 @@
T: git https://repo.or.cz/qemu/ericb.git nbd
NFS
-M: Jeff Cody <jcody@redhat.com>
M: Peter Lieven <pl@kamp.de>
L: qemu-block@nongnu.org
S: Maintained
F: block/nfs.c
-T: git https://github.com/codyprime/qemu-kvm-jtc.git block
SSH
M: Richard W.M. Jones <rjones@redhat.com>
-M: Jeff Cody <jcody@redhat.com>
L: qemu-block@nongnu.org
S: Supported
F: block/ssh.c
-T: git https://github.com/codyprime/qemu-kvm-jtc.git block
CURL
-M: Jeff Cody <jcody@redhat.com>
L: qemu-block@nongnu.org
S: Supported
F: block/curl.c
-T: git https://github.com/codyprime/qemu-kvm-jtc.git block
GLUSTER
-M: Jeff Cody <jcody@redhat.com>
L: qemu-block@nongnu.org
S: Supported
F: block/gluster.c
-T: git https://github.com/codyprime/qemu-kvm-jtc.git block
Null Block Driver
M: Fam Zheng <fam@euphon.net>
@@ -2486,6 +2532,11 @@
F: .cirrus.yml
W: https://cirrus-ci.com/github/qemu/qemu
+GitLab Continuous Integration
+M: Thomas Huth <thuth@redhat.com>
+S: Maintained
+F: .gitlab-ci.yml
+
Guest Test Compilation Support
M: Alex Bennée <alex.bennee@linaro.org>
R: Philippe Mathieu-Daudé <f4bug@amsat.org>
@@ -2516,3 +2567,9 @@
M: Daniel P. Berrange <berrange@redhat.com>
S: Odd Fixes
F: scripts/git-submodule.sh
+
+Sphinx documentation configuration and build machinery
+M: Peter Maydell <peter.maydell@linaro.org>
+S: Maintained
+F: docs/conf.py
+F: docs/*/conf.py
diff --git a/Makefile b/Makefile
index a6de286..cad585b 100644
--- a/Makefile
+++ b/Makefile
@@ -87,6 +87,20 @@
include $(SRC_PATH)/rules.mak
+# Create QEMU_PKGVERSION and FULL_VERSION strings
+# If PKGVERSION is set, use that; otherwise get version and -dirty status from git
+QEMU_PKGVERSION := $(if $(PKGVERSION),$(PKGVERSION),$(shell \
+ cd $(SRC_PATH); \
+ if test -e .git; then \
+ git describe --match 'v*' 2>/dev/null | tr -d '\n'; \
+ if ! git diff-index --quiet HEAD &>/dev/null; then \
+ echo "-dirty"; \
+ fi; \
+ fi))
+
+# Either "version (pkgversion)", or just "version" if pkgversion not set
+FULL_VERSION := $(if $(QEMU_PKGVERSION),$(VERSION) ($(QEMU_PKGVERSION)),$(VERSION))
+
GENERATED_FILES = qemu-version.h config-host.h qemu-options.def
GENERATED_QAPI_FILES = qapi/qapi-builtin-types.h qapi/qapi-builtin-types.c
@@ -359,6 +373,7 @@
dummy := $(call unnest-vars,, \
stub-obj-y \
+ authz-obj-y \
chardev-obj-y \
util-obj-y \
qga-obj-y \
@@ -387,27 +402,12 @@
include $(SRC_PATH)/tests/Makefile.include
-all: $(DOCS) $(TOOLS) $(HELPERS-y) recurse-all modules
+all: $(DOCS) $(if $(BUILD_DOCS),sphinxdocs) $(TOOLS) $(HELPERS-y) recurse-all modules
qemu-version.h: FORCE
$(call quiet-command, \
- (cd $(SRC_PATH); \
- if test -n "$(PKGVERSION)"; then \
- pkgvers="$(PKGVERSION)"; \
- else \
- if test -d .git; then \
- pkgvers=$$(git describe --match 'v*' 2>/dev/null | tr -d '\n');\
- if ! git diff-index --quiet HEAD &>/dev/null; then \
- pkgvers="$${pkgvers}-dirty"; \
- fi; \
- fi; \
- fi; \
- printf "#define QEMU_PKGVERSION \"$${pkgvers}\"\n"; \
- if test -n "$${pkgvers}"; then \
- printf '#define QEMU_FULL_VERSION QEMU_VERSION " (" QEMU_PKGVERSION ")"\n'; \
- else \
- printf '#define QEMU_FULL_VERSION QEMU_VERSION\n'; \
- fi; \
+ (printf '#define QEMU_PKGVERSION "$(QEMU_PKGVERSION)"\n'; \
+ printf '#define QEMU_FULL_VERSION "$(FULL_VERSION)"\n'; \
) > $@.tmp)
$(call quiet-command, if ! cmp -s $@ $@.tmp; then \
mv $@.tmp $@; \
@@ -423,6 +423,7 @@
SUBDIR_RULES=$(patsubst %,subdir-%, $(TARGET_DIRS))
SOFTMMU_SUBDIR_RULES=$(filter %-softmmu,$(SUBDIR_RULES))
+$(SOFTMMU_SUBDIR_RULES): $(authz-obj-y)
$(SOFTMMU_SUBDIR_RULES): $(block-obj-y)
$(SOFTMMU_SUBDIR_RULES): $(crypto-obj-y)
$(SOFTMMU_SUBDIR_RULES): $(io-obj-y)
@@ -485,9 +486,9 @@
qemu-img.o: qemu-img-cmds.h
-qemu-img$(EXESUF): qemu-img.o $(block-obj-y) $(crypto-obj-y) $(io-obj-y) $(qom-obj-y) $(COMMON_LDADDS)
-qemu-nbd$(EXESUF): qemu-nbd.o $(block-obj-y) $(crypto-obj-y) $(io-obj-y) $(qom-obj-y) $(COMMON_LDADDS)
-qemu-io$(EXESUF): qemu-io.o $(block-obj-y) $(crypto-obj-y) $(io-obj-y) $(qom-obj-y) $(COMMON_LDADDS)
+qemu-img$(EXESUF): qemu-img.o $(authz-obj-y) $(block-obj-y) $(crypto-obj-y) $(io-obj-y) $(qom-obj-y) $(COMMON_LDADDS)
+qemu-nbd$(EXESUF): qemu-nbd.o $(authz-obj-y) $(block-obj-y) $(crypto-obj-y) $(io-obj-y) $(qom-obj-y) $(COMMON_LDADDS)
+qemu-io$(EXESUF): qemu-io.o $(authz-obj-y) $(block-obj-y) $(crypto-obj-y) $(io-obj-y) $(qom-obj-y) $(COMMON_LDADDS)
qemu-bridge-helper$(EXESUF): qemu-bridge-helper.o $(COMMON_LDADDS)
@@ -498,7 +499,7 @@
fsdev/virtfs-proxy-helper$(EXESUF): fsdev/virtfs-proxy-helper.o fsdev/9p-marshal.o fsdev/9p-iov-marshal.o $(COMMON_LDADDS)
fsdev/virtfs-proxy-helper$(EXESUF): LIBS += -lcap
-scsi/qemu-pr-helper$(EXESUF): scsi/qemu-pr-helper.o scsi/utils.o $(crypto-obj-y) $(io-obj-y) $(qom-obj-y) $(COMMON_LDADDS)
+scsi/qemu-pr-helper$(EXESUF): scsi/qemu-pr-helper.o scsi/utils.o $(authz-obj-y) $(crypto-obj-y) $(io-obj-y) $(qom-obj-y) $(COMMON_LDADDS)
ifdef CONFIG_MPATH
scsi/qemu-pr-helper$(EXESUF): LIBS += -ludev -lmultipath -lmpathpersist
endif
@@ -607,7 +608,11 @@
rm -f config.mak op-i386.h opc-i386.h gen-op-i386.h op-arm.h opc-arm.h gen-op-arm.h
rm -f qemu-options.def
rm -f *.msi
- find . \( -name '*.so' -o -name '*.dll' -o -name '*.mo' -o -name '*.[oda]' \) -type f -exec rm {} +
+ find . \( -name '*.so' -o -name '*.dll' -o -name '*.mo' -o -name '*.[oda]' \) -type f \
+ ! -path ./roms/edk2/ArmPkg/Library/GccLto/liblto-aarch64.a \
+ ! -path ./roms/edk2/ArmPkg/Library/GccLto/liblto-arm.a \
+ ! -path ./roms/edk2/BaseTools/Source/Python/UPT/Dll/sqlite3.dll \
+ -exec rm {} +
rm -f $(filter-out %.tlb,$(TOOLS)) $(HELPERS-y) qemu-ga TAGS cscope.* *.pod *~ */*~
rm -f fsdev/*.pod scsi/*.pod
rm -f qemu-img-cmds.h
@@ -631,6 +636,14 @@
qemu-%.tar.bz2:
$(SRC_PATH)/scripts/make-release "$(SRC_PATH)" "$(patsubst qemu-%.tar.bz2,%,$@)"
+# Note that these commands assume that there are no HTML files in
+# the docs subdir in the source tree! If there are then this will
+# blow them away for an in-source-tree 'make clean'.
+define clean-manual =
+rm -rf docs/$1/_static
+rm -f docs/$1/objects.inv docs/$1/searchindex.js docs/$1/*.html
+endef
+
distclean: clean
rm -f config-host.mak config-host.h* config-host.ld $(DOCS) qemu-options.texi qemu-img-cmds.texi qemu-monitor.texi qemu-monitor-info.texi
rm -f config-all-devices.mak config-all-disas.mak config.status
@@ -651,6 +664,9 @@
rm -f docs/interop/qemu-qmp-ref.html docs/interop/qemu-ga-ref.html
rm -f docs/qemu-block-drivers.7
rm -f docs/qemu-cpu-models.7
+ rm -f .doctrees
+ $(call clean-manual,devel)
+ $(call clean-manual,interop)
for d in $(TARGET_DIRS); do \
rm -rf $$d || exit 1 ; \
done
@@ -684,7 +700,18 @@
BLOBS=
endif
-install-doc: $(DOCS)
+define install-manual =
+for d in $$(cd docs && find $1 -type d); do $(INSTALL_DIR) "$(DESTDIR)$(qemu_docdir)/$$d"; done
+for f in $$(cd docs && find $1 -type f); do $(INSTALL_DATA) "docs/$$f" "$(DESTDIR)$(qemu_docdir)/$$f"; done
+endef
+
+# Note that we deliberately do not install the "devel" manual: it is
+# for QEMU developers, and not interesting to our users.
+.PHONY: install-sphinxdocs
+install-sphinxdocs: sphinxdocs
+ $(call install-manual,interop)
+
+install-doc: $(DOCS) install-sphinxdocs
$(INSTALL_DIR) "$(DESTDIR)$(qemu_docdir)"
$(INSTALL_DATA) qemu-doc.html "$(DESTDIR)$(qemu_docdir)"
$(INSTALL_DATA) qemu-doc.txt "$(DESTDIR)$(qemu_docdir)"
@@ -835,6 +862,23 @@
%.pdf: %.texi docs/version.texi
$(call quiet-command,texi2pdf $(TEXI2PDFFLAGS) $< -o $@,"GEN","$@")
+# Sphinx builds all its documentation at once in one invocation
+# and handles "don't rebuild things unless necessary" itself.
+# The '.doctrees' files are cached information to speed this up.
+.PHONY: sphinxdocs
+sphinxdocs: docs/devel/index.html docs/interop/index.html
+
+# Canned command to build a single manual
+build-manual = $(call quiet-command,sphinx-build $(if $(V),,-q) -b html -D version=$(VERSION) -D release="$(FULL_VERSION)" -d .doctrees/$1 $(SRC_PATH)/docs/$1 docs/$1 ,"SPHINX","docs/$1")
+# We assume all RST files in the manual's directory are used in it
+manual-deps = $(wildcard $(SRC_PATH)/docs/$1/*.rst) $(SRC_PATH)/docs/$1/conf.py $(SRC_PATH)/docs/conf.py
+
+docs/devel/index.html: $(call manual-deps,devel)
+ $(call build-manual,devel)
+
+docs/interop/index.html: $(call manual-deps,interop)
+ $(call build-manual,interop)
+
qemu-options.texi: $(SRC_PATH)/qemu-options.hx $(SRC_PATH)/scripts/hxtool
$(call quiet-command,sh $(SRC_PATH)/scripts/hxtool -t < $< > $@,"GEN","$@")
@@ -863,7 +907,7 @@
docs/qemu-cpu-models.7: docs/qemu-cpu-models.texi
scripts/qemu-trace-stap.1: scripts/qemu-trace-stap.texi
-html: qemu-doc.html docs/interop/qemu-qmp-ref.html docs/interop/qemu-ga-ref.html
+html: qemu-doc.html docs/interop/qemu-qmp-ref.html docs/interop/qemu-ga-ref.html sphinxdocs
info: qemu-doc.info docs/interop/qemu-qmp-ref.info docs/interop/qemu-ga-ref.info
pdf: qemu-doc.pdf docs/interop/qemu-qmp-ref.pdf docs/interop/qemu-ga-ref.pdf
txt: qemu-doc.txt docs/interop/qemu-qmp-ref.txt docs/interop/qemu-ga-ref.txt
diff --git a/Makefile.objs b/Makefile.objs
index 5fb022d..6e91ee5 100644
--- a/Makefile.objs
+++ b/Makefile.objs
@@ -1,12 +1,17 @@
#######################################################################
# Common libraries for tools and emulators
-stub-obj-y = stubs/ crypto/
+stub-obj-y = stubs/ util/ crypto/
util-obj-y = util/ qobject/ qapi/
chardev-obj-y = chardev/
slirp-obj-$(CONFIG_SLIRP) = slirp/
#######################################################################
+# authz-obj-y is code used by both qemu system emulation and qemu-img
+
+authz-obj-y = authz/
+
+#######################################################################
# block-obj-y is code used by both qemu system emulation and qemu-img
block-obj-y += nbd/
@@ -125,6 +130,7 @@
trace-events-subdirs += accel/kvm
trace-events-subdirs += accel/tcg
trace-events-subdirs += audio
+trace-events-subdirs += authz
trace-events-subdirs += block
trace-events-subdirs += chardev
trace-events-subdirs += crypto
diff --git a/Makefile.target b/Makefile.target
index d6ce549..3b79e70 100644
--- a/Makefile.target
+++ b/Makefile.target
@@ -179,6 +179,7 @@
dummy := $(call unnest-vars,,target-obj-y)
target-obj-y-save := $(target-obj-y)
dummy := $(call unnest-vars,.., \
+ authz-obj-y \
block-obj-y \
block-obj-m \
chardev-obj-y \
@@ -193,6 +194,7 @@
all-obj-y += $(common-obj-y)
all-obj-y += $(target-obj-y)
all-obj-y += $(qom-obj-y)
+all-obj-$(CONFIG_SOFTMMU) += $(authz-obj-y)
all-obj-$(CONFIG_SOFTMMU) += $(block-obj-y) $(chardev-obj-y)
all-obj-$(CONFIG_USER_ONLY) += $(crypto-aes-obj-y)
all-obj-$(CONFIG_SOFTMMU) += $(crypto-obj-y)
diff --git a/accel/kvm/kvm-all.c b/accel/kvm/kvm-all.c
index fd92b6f..241db49 100644
--- a/accel/kvm/kvm-all.c
+++ b/accel/kvm/kvm-all.c
@@ -1593,7 +1593,7 @@
kvm_type = qemu_opt_get(qemu_get_machine_opts(), "kvm-type");
if (mc->kvm_type) {
- type = mc->kvm_type(kvm_type);
+ type = mc->kvm_type(ms, kvm_type);
} else if (kvm_type) {
ret = -EINVAL;
fprintf(stderr, "Invalid argument kvm-type=%s\n", kvm_type);
diff --git a/audio/audio.c b/audio/audio.c
index d163ffb..909c817 100644
--- a/audio/audio.c
+++ b/audio/audio.c
@@ -454,9 +454,7 @@
static void audio_process_options (const char *prefix,
struct audio_option *opt)
{
- char *optname;
- const char qemu_prefix[] = "QEMU_";
- size_t preflen, optlen;
+ gchar *prefix_upper;
if (audio_bug(__func__, !prefix)) {
dolog ("prefix = NULL\n");
@@ -468,10 +466,10 @@
return;
}
- preflen = strlen (prefix);
+ prefix_upper = g_utf8_strup(prefix, -1);
for (; opt->name; opt++) {
- size_t len, i;
+ char *optname;
int def;
if (!opt->valp) {
@@ -480,21 +478,7 @@
continue;
}
- len = strlen (opt->name);
- /* len of opt->name + len of prefix + size of qemu_prefix
- * (includes trailing zero) + zero + underscore (on behalf of
- * sizeof) */
- optlen = len + preflen + sizeof (qemu_prefix) + 1;
- optname = g_malloc (optlen);
-
- pstrcpy (optname, optlen, qemu_prefix);
-
- /* copy while upper-casing, including trailing zero */
- for (i = 0; i <= preflen; ++i) {
- optname[i + sizeof (qemu_prefix) - 1] = qemu_toupper(prefix[i]);
- }
- pstrcat (optname, optlen, "_");
- pstrcat (optname, optlen, opt->name);
+ optname = g_strdup_printf("QEMU_%s_%s", prefix_upper, opt->name);
def = 1;
switch (opt->tag) {
@@ -532,6 +516,7 @@
*opt->overriddenp = !def;
g_free (optname);
}
+ g_free(prefix_upper);
}
static void audio_print_settings (struct audsettings *as)
@@ -826,12 +811,7 @@
SWVoiceOut *sw;
HWVoiceOut *hw_cap = &cap->hw;
- sc = audio_calloc(__func__, 1, sizeof(*sc));
- if (!sc) {
- dolog ("Could not allocate soft capture voice (%zu bytes)\n",
- sizeof (*sc));
- return -1;
- }
+ sc = g_malloc0(sizeof(*sc));
sc->cap = cap;
sw = &sc->sw;
@@ -1975,15 +1955,10 @@
if (audio_validate_settings (as)) {
dolog ("Invalid settings were passed when trying to add capture\n");
audio_print_settings (as);
- goto err0;
+ return NULL;
}
- cb = audio_calloc(__func__, 1, sizeof(*cb));
- if (!cb) {
- dolog ("Could not allocate capture callback information, size %zu\n",
- sizeof (*cb));
- goto err0;
- }
+ cb = g_malloc0(sizeof(*cb));
cb->ops = *ops;
cb->opaque = cb_opaque;
@@ -1996,12 +1971,7 @@
HWVoiceOut *hw;
CaptureVoiceOut *cap;
- cap = audio_calloc(__func__, 1, sizeof(*cap));
- if (!cap) {
- dolog ("Could not allocate capture voice, size %zu\n",
- sizeof (*cap));
- goto err1;
- }
+ cap = g_malloc0(sizeof(*cap));
hw = &cap->hw;
QLIST_INIT (&hw->sw_head);
@@ -2009,23 +1979,11 @@
/* XXX find a more elegant way */
hw->samples = 4096 * 4;
- hw->mix_buf = audio_calloc(__func__, hw->samples,
- sizeof(struct st_sample));
- if (!hw->mix_buf) {
- dolog ("Could not allocate capture mix buffer (%d samples)\n",
- hw->samples);
- goto err2;
- }
+ hw->mix_buf = g_new0(struct st_sample, hw->samples);
audio_pcm_init_info (&hw->info, as);
- cap->buf = audio_calloc(__func__, hw->samples, 1 << hw->info.shift);
- if (!cap->buf) {
- dolog ("Could not allocate capture buffer "
- "(%d samples, each %d bytes)\n",
- hw->samples, 1 << hw->info.shift);
- goto err3;
- }
+ cap->buf = g_malloc0_n(hw->samples, 1 << hw->info.shift);
hw->clip = mixeng_clip
[hw->info.nchannels == 2]
@@ -2040,15 +1998,6 @@
audio_attach_capture (hw);
}
return cap;
-
- err3:
- g_free (cap->hw.mix_buf);
- err2:
- g_free (cap);
- err1:
- g_free (cb);
- err0:
- return NULL;
}
}
diff --git a/audio/sdlaudio.c b/audio/sdlaudio.c
index 9db5ac9..f7ee70b 100644
--- a/audio/sdlaudio.c
+++ b/audio/sdlaudio.c
@@ -38,14 +38,9 @@
#define AUDIO_CAP "sdl"
#include "audio_int.h"
-#define USE_SEMAPHORE (SDL_MAJOR_VERSION < 2)
-
typedef struct SDLVoiceOut {
HWVoiceOut hw;
int live;
-#if USE_SEMAPHORE
- int rpos;
-#endif
int decr;
} SDLVoiceOut;
@@ -57,10 +52,6 @@
static struct SDLAudioState {
int exit;
-#if USE_SEMAPHORE
- SDL_mutex *mutex;
- SDL_sem *sem;
-#endif
int initialized;
bool driver_created;
} glob_sdl;
@@ -77,66 +68,6 @@
AUD_log (AUDIO_CAP, "Reason: %s\n", SDL_GetError ());
}
-static int sdl_lock (SDLAudioState *s, const char *forfn)
-{
-#if USE_SEMAPHORE
- if (SDL_LockMutex (s->mutex)) {
- sdl_logerr ("SDL_LockMutex for %s failed\n", forfn);
- return -1;
- }
-#else
- SDL_LockAudio();
-#endif
-
- return 0;
-}
-
-static int sdl_unlock (SDLAudioState *s, const char *forfn)
-{
-#if USE_SEMAPHORE
- if (SDL_UnlockMutex (s->mutex)) {
- sdl_logerr ("SDL_UnlockMutex for %s failed\n", forfn);
- return -1;
- }
-#else
- SDL_UnlockAudio();
-#endif
-
- return 0;
-}
-
-static int sdl_post (SDLAudioState *s, const char *forfn)
-{
-#if USE_SEMAPHORE
- if (SDL_SemPost (s->sem)) {
- sdl_logerr ("SDL_SemPost for %s failed\n", forfn);
- return -1;
- }
-#endif
-
- return 0;
-}
-
-#if USE_SEMAPHORE
-static int sdl_wait (SDLAudioState *s, const char *forfn)
-{
- if (SDL_SemWait (s->sem)) {
- sdl_logerr ("SDL_SemWait for %s failed\n", forfn);
- return -1;
- }
- return 0;
-}
-#endif
-
-static int sdl_unlock_and_post (SDLAudioState *s, const char *forfn)
-{
- if (sdl_unlock (s, forfn)) {
- return -1;
- }
-
- return sdl_post (s, forfn);
-}
-
static int aud_to_sdlfmt (audfmt_e fmt)
{
switch (fmt) {
@@ -243,9 +174,9 @@
static void sdl_close (SDLAudioState *s)
{
if (s->initialized) {
- sdl_lock (s, "sdl_close");
+ SDL_LockAudio();
s->exit = 1;
- sdl_unlock_and_post (s, "sdl_close");
+ SDL_UnlockAudio();
SDL_PauseAudio (1);
SDL_CloseAudio ();
s->initialized = 0;
@@ -258,76 +189,36 @@
SDLAudioState *s = &glob_sdl;
HWVoiceOut *hw = &sdl->hw;
int samples = len >> hw->info.shift;
+ int to_mix, decr;
- if (s->exit) {
+ if (s->exit || !sdl->live) {
return;
}
- while (samples) {
- int to_mix, decr;
+ /* dolog ("in callback samples=%d live=%d\n", samples, sdl->live); */
- /* dolog ("in callback samples=%d\n", samples); */
-#if USE_SEMAPHORE
- sdl_wait (s, "sdl_callback");
- if (s->exit) {
- return;
- }
+ to_mix = audio_MIN(samples, sdl->live);
+ decr = to_mix;
+ while (to_mix) {
+ int chunk = audio_MIN(to_mix, hw->samples - hw->rpos);
+ struct st_sample *src = hw->mix_buf + hw->rpos;
- if (sdl_lock (s, "sdl_callback")) {
- return;
- }
-
- if (audio_bug(__func__, sdl->live < 0 || sdl->live > hw->samples)) {
- dolog ("sdl->live=%d hw->samples=%d\n",
- sdl->live, hw->samples);
- return;
- }
-
- if (!sdl->live) {
- goto again;
- }
-#else
- if (s->exit || !sdl->live) {
- break;
- }
-#endif
-
- /* dolog ("in callback live=%d\n", live); */
- to_mix = audio_MIN (samples, sdl->live);
- decr = to_mix;
- while (to_mix) {
- int chunk = audio_MIN (to_mix, hw->samples - hw->rpos);
- struct st_sample *src = hw->mix_buf + hw->rpos;
-
- /* dolog ("in callback to_mix %d, chunk %d\n", to_mix, chunk); */
- hw->clip (buf, src, chunk);
-#if USE_SEMAPHORE
- sdl->rpos = (sdl->rpos + chunk) % hw->samples;
-#else
- hw->rpos = (hw->rpos + chunk) % hw->samples;
-#endif
- to_mix -= chunk;
- buf += chunk << hw->info.shift;
- }
- samples -= decr;
- sdl->live -= decr;
- sdl->decr += decr;
-
-#if USE_SEMAPHORE
- again:
- if (sdl_unlock (s, "sdl_callback")) {
- return;
- }
-#endif
+ /* dolog ("in callback to_mix %d, chunk %d\n", to_mix, chunk); */
+ hw->clip(buf, src, chunk);
+ hw->rpos = (hw->rpos + chunk) % hw->samples;
+ to_mix -= chunk;
+ buf += chunk << hw->info.shift;
}
+ samples -= decr;
+ sdl->live -= decr;
+ sdl->decr += decr;
+
/* dolog ("done len=%d\n", len); */
-#if (SDL_MAJOR_VERSION >= 2)
/* SDL2 does not clear the remaining buffer for us, so do it on our own */
if (samples) {
memset(buf, 0, samples << hw->info.shift);
}
-#endif
}
static int sdl_write_out (SWVoiceOut *sw, void *buf, int len)
@@ -339,11 +230,8 @@
{
int decr;
SDLVoiceOut *sdl = (SDLVoiceOut *) hw;
- SDLAudioState *s = &glob_sdl;
- if (sdl_lock (s, "sdl_run_out")) {
- return 0;
- }
+ SDL_LockAudio();
if (sdl->decr > live) {
ldebug ("sdl->decr %d live %d sdl->live %d\n",
@@ -355,19 +243,10 @@
decr = audio_MIN (sdl->decr, live);
sdl->decr -= decr;
-#if USE_SEMAPHORE
- sdl->live = live - decr;
- hw->rpos = sdl->rpos;
-#else
sdl->live = live;
-#endif
- if (sdl->live > 0) {
- sdl_unlock_and_post (s, "sdl_run_out");
- }
- else {
- sdl_unlock (s, "sdl_run_out");
- }
+ SDL_UnlockAudio();
+
return decr;
}
@@ -449,23 +328,6 @@
return NULL;
}
-#if USE_SEMAPHORE
- s->mutex = SDL_CreateMutex ();
- if (!s->mutex) {
- sdl_logerr ("Failed to create SDL mutex\n");
- SDL_QuitSubSystem (SDL_INIT_AUDIO);
- return NULL;
- }
-
- s->sem = SDL_CreateSemaphore (0);
- if (!s->sem) {
- sdl_logerr ("Failed to create SDL semaphore\n");
- SDL_DestroyMutex (s->mutex);
- SDL_QuitSubSystem (SDL_INIT_AUDIO);
- return NULL;
- }
-#endif
-
s->driver_created = true;
return s;
}
@@ -474,10 +336,6 @@
{
SDLAudioState *s = opaque;
sdl_close (s);
-#if USE_SEMAPHORE
- SDL_DestroySemaphore (s->sem);
- SDL_DestroyMutex (s->mutex);
-#endif
SDL_QuitSubSystem (SDL_INIT_AUDIO);
s->driver_created = false;
}
diff --git a/authz/Makefile.objs b/authz/Makefile.objs
new file mode 100644
index 0000000..ed7b273
--- /dev/null
+++ b/authz/Makefile.objs
@@ -0,0 +1,7 @@
+authz-obj-y += base.o
+authz-obj-y += simple.o
+authz-obj-y += list.o
+authz-obj-y += listfile.o
+authz-obj-$(CONFIG_AUTH_PAM) += pamacct.o
+
+pamacct.o-libs = -lpam
diff --git a/authz/base.c b/authz/base.c
new file mode 100644
index 0000000..110dfa4
--- /dev/null
+++ b/authz/base.c
@@ -0,0 +1,82 @@
+/*
+ * QEMU authorization framework base class
+ *
+ * Copyright (c) 2018 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * 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 "authz/base.h"
+#include "authz/trace.h"
+
+bool qauthz_is_allowed(QAuthZ *authz,
+ const char *identity,
+ Error **errp)
+{
+ QAuthZClass *cls = QAUTHZ_GET_CLASS(authz);
+ bool allowed;
+
+ allowed = cls->is_allowed(authz, identity, errp);
+ trace_qauthz_is_allowed(authz, identity, allowed);
+
+ return allowed;
+}
+
+
+bool qauthz_is_allowed_by_id(const char *authzid,
+ const char *identity,
+ Error **errp)
+{
+ QAuthZ *authz;
+ Object *obj;
+ Object *container;
+
+ container = object_get_objects_root();
+ obj = object_resolve_path_component(container,
+ authzid);
+ if (!obj) {
+ error_setg(errp, "Cannot find QAuthZ object ID %s",
+ authzid);
+ return false;
+ }
+
+ if (!object_dynamic_cast(obj, TYPE_QAUTHZ)) {
+ error_setg(errp, "Object '%s' is not a QAuthZ subclass",
+ authzid);
+ return false;
+ }
+
+ authz = QAUTHZ(obj);
+
+ return qauthz_is_allowed(authz, identity, errp);
+}
+
+
+static const TypeInfo authz_info = {
+ .parent = TYPE_OBJECT,
+ .name = TYPE_QAUTHZ,
+ .instance_size = sizeof(QAuthZ),
+ .class_size = sizeof(QAuthZClass),
+ .abstract = true,
+};
+
+static void qauthz_register_types(void)
+{
+ type_register_static(&authz_info);
+}
+
+type_init(qauthz_register_types)
+
diff --git a/authz/list.c b/authz/list.c
new file mode 100644
index 0000000..dc6b0fe
--- /dev/null
+++ b/authz/list.c
@@ -0,0 +1,271 @@
+/*
+ * QEMU access control list authorization driver
+ *
+ * Copyright (c) 2018 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * 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 "authz/list.h"
+#include "authz/trace.h"
+#include "qom/object_interfaces.h"
+#include "qapi/qapi-visit-authz.h"
+
+static bool qauthz_list_is_allowed(QAuthZ *authz,
+ const char *identity,
+ Error **errp)
+{
+ QAuthZList *lauthz = QAUTHZ_LIST(authz);
+ QAuthZListRuleList *rules = lauthz->rules;
+
+ while (rules) {
+ QAuthZListRule *rule = rules->value;
+ QAuthZListFormat format = rule->has_format ? rule->format :
+ QAUTHZ_LIST_FORMAT_EXACT;
+
+ trace_qauthz_list_check_rule(authz, rule->match, identity,
+ format, rule->policy);
+ switch (format) {
+ case QAUTHZ_LIST_FORMAT_EXACT:
+ if (g_str_equal(rule->match, identity)) {
+ return rule->policy == QAUTHZ_LIST_POLICY_ALLOW;
+ }
+ break;
+ case QAUTHZ_LIST_FORMAT_GLOB:
+ if (g_pattern_match_simple(rule->match, identity)) {
+ return rule->policy == QAUTHZ_LIST_POLICY_ALLOW;
+ }
+ break;
+ default:
+ g_warn_if_reached();
+ return false;
+ }
+ rules = rules->next;
+ }
+
+ trace_qauthz_list_default_policy(authz, identity, lauthz->policy);
+ return lauthz->policy == QAUTHZ_LIST_POLICY_ALLOW;
+}
+
+
+static void
+qauthz_list_prop_set_policy(Object *obj,
+ int value,
+ Error **errp G_GNUC_UNUSED)
+{
+ QAuthZList *lauthz = QAUTHZ_LIST(obj);
+
+ lauthz->policy = value;
+}
+
+
+static int
+qauthz_list_prop_get_policy(Object *obj,
+ Error **errp G_GNUC_UNUSED)
+{
+ QAuthZList *lauthz = QAUTHZ_LIST(obj);
+
+ return lauthz->policy;
+}
+
+
+static void
+qauthz_list_prop_get_rules(Object *obj, Visitor *v, const char *name,
+ void *opaque, Error **errp)
+{
+ QAuthZList *lauthz = QAUTHZ_LIST(obj);
+
+ visit_type_QAuthZListRuleList(v, name, &lauthz->rules, errp);
+}
+
+static void
+qauthz_list_prop_set_rules(Object *obj, Visitor *v, const char *name,
+ void *opaque, Error **errp)
+{
+ QAuthZList *lauthz = QAUTHZ_LIST(obj);
+ QAuthZListRuleList *oldrules;
+
+ oldrules = lauthz->rules;
+ visit_type_QAuthZListRuleList(v, name, &lauthz->rules, errp);
+
+ qapi_free_QAuthZListRuleList(oldrules);
+}
+
+
+static void
+qauthz_list_finalize(Object *obj)
+{
+ QAuthZList *lauthz = QAUTHZ_LIST(obj);
+
+ qapi_free_QAuthZListRuleList(lauthz->rules);
+}
+
+
+static void
+qauthz_list_class_init(ObjectClass *oc, void *data)
+{
+ QAuthZClass *authz = QAUTHZ_CLASS(oc);
+
+ object_class_property_add_enum(oc, "policy",
+ "QAuthZListPolicy",
+ &QAuthZListPolicy_lookup,
+ qauthz_list_prop_get_policy,
+ qauthz_list_prop_set_policy,
+ NULL);
+
+ object_class_property_add(oc, "rules", "QAuthZListRule",
+ qauthz_list_prop_get_rules,
+ qauthz_list_prop_set_rules,
+ NULL, NULL, NULL);
+
+ authz->is_allowed = qauthz_list_is_allowed;
+}
+
+
+QAuthZList *qauthz_list_new(const char *id,
+ QAuthZListPolicy policy,
+ Error **errp)
+{
+ return QAUTHZ_LIST(
+ object_new_with_props(TYPE_QAUTHZ_LIST,
+ object_get_objects_root(),
+ id, errp,
+ "policy", QAuthZListPolicy_str(policy),
+ NULL));
+}
+
+ssize_t qauthz_list_append_rule(QAuthZList *auth,
+ const char *match,
+ QAuthZListPolicy policy,
+ QAuthZListFormat format,
+ Error **errp)
+{
+ QAuthZListRule *rule;
+ QAuthZListRuleList *rules, *tmp;
+ size_t i = 0;
+
+ rule = g_new0(QAuthZListRule, 1);
+ rule->policy = policy;
+ rule->match = g_strdup(match);
+ rule->format = format;
+ rule->has_format = true;
+
+ tmp = g_new0(QAuthZListRuleList, 1);
+ tmp->value = rule;
+
+ rules = auth->rules;
+ if (rules) {
+ while (rules->next) {
+ i++;
+ rules = rules->next;
+ }
+ rules->next = tmp;
+ return i + 1;
+ } else {
+ auth->rules = tmp;
+ return 0;
+ }
+}
+
+
+ssize_t qauthz_list_insert_rule(QAuthZList *auth,
+ const char *match,
+ QAuthZListPolicy policy,
+ QAuthZListFormat format,
+ size_t index,
+ Error **errp)
+{
+ QAuthZListRule *rule;
+ QAuthZListRuleList *rules, *tmp;
+ size_t i = 0;
+
+ rule = g_new0(QAuthZListRule, 1);
+ rule->policy = policy;
+ rule->match = g_strdup(match);
+ rule->format = format;
+ rule->has_format = true;
+
+ tmp = g_new0(QAuthZListRuleList, 1);
+ tmp->value = rule;
+
+ rules = auth->rules;
+ if (rules && index > 0) {
+ while (rules->next && i < (index - 1)) {
+ i++;
+ rules = rules->next;
+ }
+ tmp->next = rules->next;
+ rules->next = tmp;
+ return i + 1;
+ } else {
+ tmp->next = auth->rules;
+ auth->rules = tmp;
+ return 0;
+ }
+}
+
+
+ssize_t qauthz_list_delete_rule(QAuthZList *auth, const char *match)
+{
+ QAuthZListRule *rule;
+ QAuthZListRuleList *rules, *prev;
+ size_t i = 0;
+
+ prev = NULL;
+ rules = auth->rules;
+ while (rules) {
+ rule = rules->value;
+ if (g_str_equal(rule->match, match)) {
+ if (prev) {
+ prev->next = rules->next;
+ } else {
+ auth->rules = rules->next;
+ }
+ rules->next = NULL;
+ qapi_free_QAuthZListRuleList(rules);
+ return i;
+ }
+ prev = rules;
+ rules = rules->next;
+ i++;
+ }
+
+ return -1;
+}
+
+
+static const TypeInfo qauthz_list_info = {
+ .parent = TYPE_QAUTHZ,
+ .name = TYPE_QAUTHZ_LIST,
+ .instance_size = sizeof(QAuthZList),
+ .instance_finalize = qauthz_list_finalize,
+ .class_size = sizeof(QAuthZListClass),
+ .class_init = qauthz_list_class_init,
+ .interfaces = (InterfaceInfo[]) {
+ { TYPE_USER_CREATABLE },
+ { }
+ }
+};
+
+
+static void
+qauthz_list_register_types(void)
+{
+ type_register_static(&qauthz_list_info);
+}
+
+
+type_init(qauthz_list_register_types);
diff --git a/authz/listfile.c b/authz/listfile.c
new file mode 100644
index 0000000..d457976
--- /dev/null
+++ b/authz/listfile.c
@@ -0,0 +1,283 @@
+/*
+ * QEMU access control list file authorization driver
+ *
+ * Copyright (c) 2018 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * 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 "authz/listfile.h"
+#include "authz/trace.h"
+#include "qemu/error-report.h"
+#include "qemu/main-loop.h"
+#include "qemu/sockets.h"
+#include "qemu/filemonitor.h"
+#include "qom/object_interfaces.h"
+#include "qapi/qapi-visit-authz.h"
+#include "qapi/qmp/qjson.h"
+#include "qapi/qmp/qobject.h"
+#include "qapi/qmp/qerror.h"
+#include "qapi/qobject-input-visitor.h"
+
+
+static bool
+qauthz_list_file_is_allowed(QAuthZ *authz,
+ const char *identity,
+ Error **errp)
+{
+ QAuthZListFile *fauthz = QAUTHZ_LIST_FILE(authz);
+ if (fauthz->list) {
+ return qauthz_is_allowed(fauthz->list, identity, errp);
+ }
+
+ return false;
+}
+
+
+static QAuthZ *
+qauthz_list_file_load(QAuthZListFile *fauthz, Error **errp)
+{
+ GError *err = NULL;
+ gchar *content = NULL;
+ gsize len;
+ QObject *obj = NULL;
+ QDict *pdict;
+ Visitor *v = NULL;
+ QAuthZ *ret = NULL;
+
+ trace_qauthz_list_file_load(fauthz, fauthz->filename);
+ if (!g_file_get_contents(fauthz->filename, &content, &len, &err)) {
+ error_setg(errp, "Unable to read '%s': %s",
+ fauthz->filename, err->message);
+ goto cleanup;
+ }
+
+ obj = qobject_from_json(content, errp);
+ if (!obj) {
+ goto cleanup;
+ }
+
+ pdict = qobject_to(QDict, obj);
+ if (!pdict) {
+ error_setg(errp, QERR_INVALID_PARAMETER_TYPE, "obj", "dict");
+ goto cleanup;
+ }
+
+ v = qobject_input_visitor_new(obj);
+
+ ret = (QAuthZ *)user_creatable_add_type(TYPE_QAUTHZ_LIST,
+ NULL, pdict, v, errp);
+
+ cleanup:
+ visit_free(v);
+ qobject_unref(obj);
+ if (err) {
+ g_error_free(err);
+ }
+ g_free(content);
+ return ret;
+}
+
+
+static void
+qauthz_list_file_event(int wd G_GNUC_UNUSED,
+ QFileMonitorEvent ev G_GNUC_UNUSED,
+ const char *name G_GNUC_UNUSED,
+ void *opaque)
+{
+ QAuthZListFile *fauthz = opaque;
+ Error *err = NULL;
+
+ if (ev != QFILE_MONITOR_EVENT_MODIFIED &&
+ ev != QFILE_MONITOR_EVENT_CREATED) {
+ return;
+ }
+
+ object_unref(OBJECT(fauthz->list));
+ fauthz->list = qauthz_list_file_load(fauthz, &err);
+ trace_qauthz_list_file_refresh(fauthz,
+ fauthz->filename, fauthz->list ? 1 : 0);
+ if (!fauthz->list) {
+ error_report_err(err);
+ }
+}
+
+static void
+qauthz_list_file_complete(UserCreatable *uc, Error **errp)
+{
+ QAuthZListFile *fauthz = QAUTHZ_LIST_FILE(uc);
+ gchar *dir = NULL, *file = NULL;
+
+ fauthz->list = qauthz_list_file_load(fauthz, errp);
+
+ if (!fauthz->refresh) {
+ return;
+ }
+
+ fauthz->file_monitor = qemu_file_monitor_new(errp);
+ if (!fauthz->file_monitor) {
+ return;
+ }
+
+ dir = g_path_get_dirname(fauthz->filename);
+ if (g_str_equal(dir, ".")) {
+ error_setg(errp, "Filename must be an absolute path");
+ goto cleanup;
+ }
+ file = g_path_get_basename(fauthz->filename);
+ if (g_str_equal(file, ".")) {
+ error_setg(errp, "Path has no trailing filename component");
+ goto cleanup;
+ }
+
+ fauthz->file_watch = qemu_file_monitor_add_watch(
+ fauthz->file_monitor, dir, file,
+ qauthz_list_file_event, fauthz, errp);
+ if (fauthz->file_watch < 0) {
+ goto cleanup;
+ }
+
+ cleanup:
+ g_free(file);
+ g_free(dir);
+}
+
+
+static void
+qauthz_list_file_prop_set_filename(Object *obj,
+ const char *value,
+ Error **errp G_GNUC_UNUSED)
+{
+ QAuthZListFile *fauthz = QAUTHZ_LIST_FILE(obj);
+
+ g_free(fauthz->filename);
+ fauthz->filename = g_strdup(value);
+}
+
+
+static char *
+qauthz_list_file_prop_get_filename(Object *obj,
+ Error **errp G_GNUC_UNUSED)
+{
+ QAuthZListFile *fauthz = QAUTHZ_LIST_FILE(obj);
+
+ return g_strdup(fauthz->filename);
+}
+
+
+static void
+qauthz_list_file_prop_set_refresh(Object *obj,
+ bool value,
+ Error **errp G_GNUC_UNUSED)
+{
+ QAuthZListFile *fauthz = QAUTHZ_LIST_FILE(obj);
+
+ fauthz->refresh = value;
+}
+
+
+static bool
+qauthz_list_file_prop_get_refresh(Object *obj,
+ Error **errp G_GNUC_UNUSED)
+{
+ QAuthZListFile *fauthz = QAUTHZ_LIST_FILE(obj);
+
+ return fauthz->refresh;
+}
+
+
+static void
+qauthz_list_file_finalize(Object *obj)
+{
+ QAuthZListFile *fauthz = QAUTHZ_LIST_FILE(obj);
+
+ object_unref(OBJECT(fauthz->list));
+ g_free(fauthz->filename);
+ qemu_file_monitor_free(fauthz->file_monitor);
+}
+
+
+static void
+qauthz_list_file_class_init(ObjectClass *oc, void *data)
+{
+ UserCreatableClass *ucc = USER_CREATABLE_CLASS(oc);
+ QAuthZClass *authz = QAUTHZ_CLASS(oc);
+
+ ucc->complete = qauthz_list_file_complete;
+
+ object_class_property_add_str(oc, "filename",
+ qauthz_list_file_prop_get_filename,
+ qauthz_list_file_prop_set_filename,
+ NULL);
+ object_class_property_add_bool(oc, "refresh",
+ qauthz_list_file_prop_get_refresh,
+ qauthz_list_file_prop_set_refresh,
+ NULL);
+
+ authz->is_allowed = qauthz_list_file_is_allowed;
+}
+
+
+static void
+qauthz_list_file_init(Object *obj)
+{
+ QAuthZListFile *authz = QAUTHZ_LIST_FILE(obj);
+
+ authz->file_watch = -1;
+#ifdef CONFIG_INOTIFY1
+ authz->refresh = TRUE;
+#endif
+}
+
+
+QAuthZListFile *qauthz_list_file_new(const char *id,
+ const char *filename,
+ bool refresh,
+ Error **errp)
+{
+ return QAUTHZ_LIST_FILE(
+ object_new_with_props(TYPE_QAUTHZ_LIST_FILE,
+ object_get_objects_root(),
+ id, errp,
+ "filename", filename,
+ "refresh", refresh ? "yes" : "no",
+ NULL));
+}
+
+
+static const TypeInfo qauthz_list_file_info = {
+ .parent = TYPE_QAUTHZ,
+ .name = TYPE_QAUTHZ_LIST_FILE,
+ .instance_init = qauthz_list_file_init,
+ .instance_size = sizeof(QAuthZListFile),
+ .instance_finalize = qauthz_list_file_finalize,
+ .class_size = sizeof(QAuthZListFileClass),
+ .class_init = qauthz_list_file_class_init,
+ .interfaces = (InterfaceInfo[]) {
+ { TYPE_USER_CREATABLE },
+ { }
+ }
+};
+
+
+static void
+qauthz_list_file_register_types(void)
+{
+ type_register_static(&qauthz_list_file_info);
+}
+
+
+type_init(qauthz_list_file_register_types);
diff --git a/authz/pamacct.c b/authz/pamacct.c
new file mode 100644
index 0000000..5038358
--- /dev/null
+++ b/authz/pamacct.c
@@ -0,0 +1,148 @@
+/*
+ * QEMU PAM authorization driver
+ *
+ * Copyright (c) 2018 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * 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 "authz/pamacct.h"
+#include "authz/trace.h"
+#include "qom/object_interfaces.h"
+
+#include <security/pam_appl.h>
+
+
+static bool qauthz_pam_is_allowed(QAuthZ *authz,
+ const char *identity,
+ Error **errp)
+{
+ QAuthZPAM *pauthz = QAUTHZ_PAM(authz);
+ const struct pam_conv pam_conversation = { 0 };
+ pam_handle_t *pamh = NULL;
+ int ret;
+
+ trace_qauthz_pam_check(authz, identity, pauthz->service);
+ ret = pam_start(pauthz->service,
+ identity,
+ &pam_conversation,
+ &pamh);
+ if (ret != PAM_SUCCESS) {
+ error_setg(errp, "Unable to start PAM transaction: %s",
+ pam_strerror(NULL, ret));
+ return false;
+ }
+
+ ret = pam_acct_mgmt(pamh, PAM_SILENT);
+ pam_end(pamh, ret);
+ if (ret != PAM_SUCCESS) {
+ error_setg(errp, "Unable to authorize user '%s': %s",
+ identity, pam_strerror(pamh, ret));
+ return false;
+ }
+
+ return true;
+}
+
+
+static void
+qauthz_pam_prop_set_service(Object *obj,
+ const char *service,
+ Error **errp G_GNUC_UNUSED)
+{
+ QAuthZPAM *pauthz = QAUTHZ_PAM(obj);
+
+ g_free(pauthz->service);
+ pauthz->service = g_strdup(service);
+}
+
+
+static char *
+qauthz_pam_prop_get_service(Object *obj,
+ Error **errp G_GNUC_UNUSED)
+{
+ QAuthZPAM *pauthz = QAUTHZ_PAM(obj);
+
+ return g_strdup(pauthz->service);
+}
+
+
+static void
+qauthz_pam_complete(UserCreatable *uc, Error **errp)
+{
+}
+
+
+static void
+qauthz_pam_finalize(Object *obj)
+{
+ QAuthZPAM *pauthz = QAUTHZ_PAM(obj);
+
+ g_free(pauthz->service);
+}
+
+
+static void
+qauthz_pam_class_init(ObjectClass *oc, void *data)
+{
+ UserCreatableClass *ucc = USER_CREATABLE_CLASS(oc);
+ QAuthZClass *authz = QAUTHZ_CLASS(oc);
+
+ ucc->complete = qauthz_pam_complete;
+ authz->is_allowed = qauthz_pam_is_allowed;
+
+ object_class_property_add_str(oc, "service",
+ qauthz_pam_prop_get_service,
+ qauthz_pam_prop_set_service,
+ NULL);
+}
+
+
+QAuthZPAM *qauthz_pam_new(const char *id,
+ const char *service,
+ Error **errp)
+{
+ return QAUTHZ_PAM(
+ object_new_with_props(TYPE_QAUTHZ_PAM,
+ object_get_objects_root(),
+ id, errp,
+ "service", service,
+ NULL));
+}
+
+
+static const TypeInfo qauthz_pam_info = {
+ .parent = TYPE_QAUTHZ,
+ .name = TYPE_QAUTHZ_PAM,
+ .instance_size = sizeof(QAuthZPAM),
+ .instance_finalize = qauthz_pam_finalize,
+ .class_size = sizeof(QAuthZPAMClass),
+ .class_init = qauthz_pam_class_init,
+ .interfaces = (InterfaceInfo[]) {
+ { TYPE_USER_CREATABLE },
+ { }
+ }
+};
+
+
+static void
+qauthz_pam_register_types(void)
+{
+ type_register_static(&qauthz_pam_info);
+}
+
+
+type_init(qauthz_pam_register_types);
diff --git a/authz/simple.c b/authz/simple.c
new file mode 100644
index 0000000..8ab7188
--- /dev/null
+++ b/authz/simple.c
@@ -0,0 +1,115 @@
+/*
+ * QEMU simple authorization driver
+ *
+ * Copyright (c) 2018 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * 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 "authz/simple.h"
+#include "authz/trace.h"
+#include "qom/object_interfaces.h"
+
+static bool qauthz_simple_is_allowed(QAuthZ *authz,
+ const char *identity,
+ Error **errp)
+{
+ QAuthZSimple *sauthz = QAUTHZ_SIMPLE(authz);
+
+ trace_qauthz_simple_is_allowed(authz, sauthz->identity, identity);
+ return g_str_equal(identity, sauthz->identity);
+}
+
+static void
+qauthz_simple_prop_set_identity(Object *obj,
+ const char *value,
+ Error **errp G_GNUC_UNUSED)
+{
+ QAuthZSimple *sauthz = QAUTHZ_SIMPLE(obj);
+
+ g_free(sauthz->identity);
+ sauthz->identity = g_strdup(value);
+}
+
+
+static char *
+qauthz_simple_prop_get_identity(Object *obj,
+ Error **errp G_GNUC_UNUSED)
+{
+ QAuthZSimple *sauthz = QAUTHZ_SIMPLE(obj);
+
+ return g_strdup(sauthz->identity);
+}
+
+
+static void
+qauthz_simple_finalize(Object *obj)
+{
+ QAuthZSimple *sauthz = QAUTHZ_SIMPLE(obj);
+
+ g_free(sauthz->identity);
+}
+
+
+static void
+qauthz_simple_class_init(ObjectClass *oc, void *data)
+{
+ QAuthZClass *authz = QAUTHZ_CLASS(oc);
+
+ authz->is_allowed = qauthz_simple_is_allowed;
+
+ object_class_property_add_str(oc, "identity",
+ qauthz_simple_prop_get_identity,
+ qauthz_simple_prop_set_identity,
+ NULL);
+}
+
+
+QAuthZSimple *qauthz_simple_new(const char *id,
+ const char *identity,
+ Error **errp)
+{
+ return QAUTHZ_SIMPLE(
+ object_new_with_props(TYPE_QAUTHZ_SIMPLE,
+ object_get_objects_root(),
+ id, errp,
+ "identity", identity,
+ NULL));
+}
+
+
+static const TypeInfo qauthz_simple_info = {
+ .parent = TYPE_QAUTHZ,
+ .name = TYPE_QAUTHZ_SIMPLE,
+ .instance_size = sizeof(QAuthZSimple),
+ .instance_finalize = qauthz_simple_finalize,
+ .class_size = sizeof(QAuthZSimpleClass),
+ .class_init = qauthz_simple_class_init,
+ .interfaces = (InterfaceInfo[]) {
+ { TYPE_USER_CREATABLE },
+ { }
+ }
+};
+
+
+static void
+qauthz_simple_register_types(void)
+{
+ type_register_static(&qauthz_simple_info);
+}
+
+
+type_init(qauthz_simple_register_types);
diff --git a/authz/trace-events b/authz/trace-events
new file mode 100644
index 0000000..72c4119
--- /dev/null
+++ b/authz/trace-events
@@ -0,0 +1,18 @@
+# See docs/devel/tracing.txt for syntax documentation.
+
+# authz/base.c
+qauthz_is_allowed(void *authz, const char *identity, bool allowed) "AuthZ %p check identity=%s allowed=%d"
+
+# auth/simple.c
+qauthz_simple_is_allowed(void *authz, const char *wantidentity, const char *gotidentity) "AuthZ simple %p check want identity=%s got identity=%s"
+
+# auth/list.c
+qauthz_list_check_rule(void *authz, const char *identity, const char *rule, int format, int policy) "AuthZ list %p check rule=%s identity=%s format=%d policy=%d"
+qauthz_list_default_policy(void *authz, const char *identity, int policy) "AuthZ list %p default identity=%s policy=%d"
+
+# auth/listfile.c
+qauthz_list_file_load(void *authz, const char *filename) "AuthZ file %p load filename=%s"
+qauthz_list_file_refresh(void *authz, const char *filename, int success) "AuthZ file %p load filename=%s success=%d"
+
+# auth/pam.c
+qauthz_pam_check(void *authz, const char *identity, const char *service) "AuthZ PAM %p identity=%s service=%s"
diff --git a/backends/Makefile.objs b/backends/Makefile.objs
index 717fcbd..ff619d3 100644
--- a/backends/Makefile.objs
+++ b/backends/Makefile.objs
@@ -9,10 +9,9 @@
common-obj-y += cryptodev.o
common-obj-y += cryptodev-builtin.o
-ifeq ($(CONFIG_VIRTIO),y)
+ifeq ($(CONFIG_VIRTIO_CRYPTO),y)
common-obj-y += cryptodev-vhost.o
-common-obj-$(call land,$(CONFIG_VHOST_USER),$(CONFIG_LINUX)) += \
- cryptodev-vhost-user.o
+common-obj-$(CONFIG_VHOST_CRYPTO) += cryptodev-vhost-user.o
endif
common-obj-$(CONFIG_LINUX) += hostmem-memfd.o
diff --git a/backends/hostmem-file.c b/backends/hostmem-file.c
index ba601ce..ce54788 100644
--- a/backends/hostmem-file.c
+++ b/backends/hostmem-file.c
@@ -41,10 +41,12 @@
static void
file_backend_memory_alloc(HostMemoryBackend *backend, Error **errp)
{
+#ifndef CONFIG_POSIX
+ error_setg(errp, "backend '%s' not supported on this host",
+ object_get_typename(OBJECT(backend)));
+#else
HostMemoryBackendFile *fb = MEMORY_BACKEND_FILE(backend);
-#ifdef CONFIG_POSIX
gchar *name;
-#endif
if (!backend->size) {
error_setg(errp, "can't create backend with size 0");
@@ -54,9 +56,6 @@
error_setg(errp, "mem-path property not set");
return;
}
-#ifndef CONFIG_POSIX
- error_setg(errp, "-mem-path not supported on this host");
-#else
backend->force_prealloc = mem_prealloc;
name = host_memory_backend_get_name(backend);
memory_region_init_ram_from_file(&backend->mr, OBJECT(backend),
diff --git a/backends/hostmem.c b/backends/hostmem.c
index 87b19d2..04baf47 100644
--- a/backends/hostmem.c
+++ b/backends/hostmem.c
@@ -88,7 +88,7 @@
value = find_first_bit(backend->host_nodes, MAX_NODES);
if (value == MAX_NODES) {
- return;
+ goto ret;
}
*node = g_malloc0(sizeof(**node));
@@ -106,6 +106,7 @@
node = &(*node)->next;
} while (true);
+ret:
visit_type_uint16List(v, name, &host_nodes, errp);
}
diff --git a/block.c b/block.c
index 4ad0e90..35e78e2 100644
--- a/block.c
+++ b/block.c
@@ -152,53 +152,53 @@
#endif
}
-/* if filename is absolute, just copy it to dest. Otherwise, build a
+/* if filename is absolute, just return its duplicate. Otherwise, build a
path to it by considering it is relative to base_path. URL are
supported. */
-void path_combine(char *dest, int dest_size,
- const char *base_path,
- const char *filename)
+char *path_combine(const char *base_path, const char *filename)
{
+ const char *protocol_stripped = NULL;
const char *p, *p1;
+ char *result;
int len;
- if (dest_size <= 0)
- return;
if (path_is_absolute(filename)) {
- pstrcpy(dest, dest_size, filename);
- } else {
- const char *protocol_stripped = NULL;
-
- if (path_has_protocol(base_path)) {
- protocol_stripped = strchr(base_path, ':');
- if (protocol_stripped) {
- protocol_stripped++;
- }
- }
- p = protocol_stripped ?: base_path;
-
- p1 = strrchr(base_path, '/');
-#ifdef _WIN32
- {
- const char *p2;
- p2 = strrchr(base_path, '\\');
- if (!p1 || p2 > p1)
- p1 = p2;
- }
-#endif
- if (p1)
- p1++;
- else
- p1 = base_path;
- if (p1 > p)
- p = p1;
- len = p - base_path;
- if (len > dest_size - 1)
- len = dest_size - 1;
- memcpy(dest, base_path, len);
- dest[len] = '\0';
- pstrcat(dest, dest_size, filename);
+ return g_strdup(filename);
}
+
+ if (path_has_protocol(base_path)) {
+ protocol_stripped = strchr(base_path, ':');
+ if (protocol_stripped) {
+ protocol_stripped++;
+ }
+ }
+ p = protocol_stripped ?: base_path;
+
+ p1 = strrchr(base_path, '/');
+#ifdef _WIN32
+ {
+ const char *p2;
+ p2 = strrchr(base_path, '\\');
+ if (!p1 || p2 > p1) {
+ p1 = p2;
+ }
+ }
+#endif
+ if (p1) {
+ p1++;
+ } else {
+ p1 = base_path;
+ }
+ if (p1 > p) {
+ p = p1;
+ }
+ len = p - base_path;
+
+ result = g_malloc(len + strlen(filename) + 1);
+ memcpy(result, base_path, len);
+ strcpy(result + len, filename);
+
+ return result;
}
/*
@@ -303,30 +303,61 @@
return -EACCES;
}
-void bdrv_get_full_backing_filename_from_filename(const char *backed,
- const char *backing,
- char *dest, size_t sz,
- Error **errp)
+/*
+ * If @backing is empty, this function returns NULL without setting
+ * @errp. In all other cases, NULL will only be returned with @errp
+ * set.
+ *
+ * Therefore, a return value of NULL without @errp set means that
+ * there is no backing file; if @errp is set, there is one but its
+ * absolute filename cannot be generated.
+ */
+char *bdrv_get_full_backing_filename_from_filename(const char *backed,
+ const char *backing,
+ Error **errp)
{
- if (backing[0] == '\0' || path_has_protocol(backing) ||
- path_is_absolute(backing))
- {
- pstrcpy(dest, sz, backing);
+ if (backing[0] == '\0') {
+ return NULL;
+ } else if (path_has_protocol(backing) || path_is_absolute(backing)) {
+ return g_strdup(backing);
} else if (backed[0] == '\0' || strstart(backed, "json:", NULL)) {
error_setg(errp, "Cannot use relative backing file names for '%s'",
backed);
+ return NULL;
} else {
- path_combine(dest, sz, backed, backing);
+ return path_combine(backed, backing);
}
}
-void bdrv_get_full_backing_filename(BlockDriverState *bs, char *dest, size_t sz,
- Error **errp)
+/*
+ * If @filename is empty or NULL, this function returns NULL without
+ * setting @errp. In all other cases, NULL will only be returned with
+ * @errp set.
+ */
+static char *bdrv_make_absolute_filename(BlockDriverState *relative_to,
+ const char *filename, Error **errp)
{
- char *backed = bs->exact_filename[0] ? bs->exact_filename : bs->filename;
+ char *dir, *full_name;
- bdrv_get_full_backing_filename_from_filename(backed, bs->backing_file,
- dest, sz, errp);
+ if (!filename || filename[0] == '\0') {
+ return NULL;
+ } else if (path_has_protocol(filename) || path_is_absolute(filename)) {
+ return g_strdup(filename);
+ }
+
+ dir = bdrv_dirname(relative_to, errp);
+ if (!dir) {
+ return NULL;
+ }
+
+ full_name = g_strconcat(dir, filename, NULL);
+ g_free(dir);
+ return full_name;
+}
+
+char *bdrv_get_full_backing_filename(BlockDriverState *bs, Error **errp)
+{
+ return bdrv_make_absolute_filename(bs, bs->backing_file, errp);
}
void bdrv_register(BlockDriver *bdrv)
@@ -1004,6 +1035,8 @@
"node is used as backing hd of '%s'",
bdrv_get_device_or_node_name(parent));
+ bdrv_refresh_filename(backing_hd);
+
parent->open_flags &= ~BDRV_O_NO_BACKING;
pstrcpy(parent->backing_file, sizeof(parent->backing_file),
backing_hd->filename);
@@ -1413,6 +1446,7 @@
}
if (file != NULL) {
+ bdrv_refresh_filename(blk_bs(file));
filename = blk_bs(file)->filename;
} else {
/*
@@ -1954,13 +1988,32 @@
ret = bdrv_check_update_perm(c->bs, q, perm, shared, ignore_children, errp);
g_slist_free(ignore_children);
- return ret;
+ if (ret < 0) {
+ return ret;
+ }
+
+ if (!c->has_backup_perm) {
+ c->has_backup_perm = true;
+ c->backup_perm = c->perm;
+ c->backup_shared_perm = c->shared_perm;
+ }
+ /*
+ * Note: it's OK if c->has_backup_perm was already set, as we can find the
+ * same child twice during check_perm procedure
+ */
+
+ c->perm = perm;
+ c->shared_perm = shared;
+
+ return 0;
}
static void bdrv_child_set_perm(BdrvChild *c, uint64_t perm, uint64_t shared)
{
uint64_t cumulative_perms, cumulative_shared_perms;
+ c->has_backup_perm = false;
+
c->perm = perm;
c->shared_perm = shared;
@@ -1971,6 +2024,12 @@
static void bdrv_child_abort_perm_update(BdrvChild *c)
{
+ if (c->has_backup_perm) {
+ c->perm = c->backup_perm;
+ c->shared_perm = c->backup_shared_perm;
+ c->has_backup_perm = false;
+ }
+
bdrv_abort_perm_update(c->bs);
}
@@ -2309,8 +2368,6 @@
bdrv_unref(backing_hd);
}
- bdrv_refresh_filename(bs);
-
out:
bdrv_refresh_limits(bs, NULL);
}
@@ -2328,10 +2385,11 @@
int bdrv_open_backing_file(BlockDriverState *bs, QDict *parent_options,
const char *bdref_key, Error **errp)
{
- char *backing_filename = g_malloc0(PATH_MAX);
+ char *backing_filename = NULL;
char *bdref_key_dot;
const char *reference = NULL;
int ret = 0;
+ bool implicit_backing = false;
BlockDriverState *backing_hd;
QDict *options;
QDict *tmp_parent_options = NULL;
@@ -2362,13 +2420,22 @@
*/
reference = qdict_get_try_str(parent_options, bdref_key);
if (reference || qdict_haskey(options, "file.filename")) {
- backing_filename[0] = '\0';
+ /* keep backing_filename NULL */
} else if (bs->backing_file[0] == '\0' && qdict_size(options) == 0) {
qobject_unref(options);
goto free_exit;
} else {
- bdrv_get_full_backing_filename(bs, backing_filename, PATH_MAX,
- &local_err);
+ if (qdict_size(options) == 0) {
+ /* If the user specifies options that do not modify the
+ * backing file's behavior, we might still consider it the
+ * implicit backing file. But it's easier this way, and
+ * just specifying some of the backing BDS's options is
+ * only possible with -drive anyway (otherwise the QAPI
+ * schema forces the user to specify everything). */
+ implicit_backing = !strcmp(bs->auto_backing_file, bs->backing_file);
+ }
+
+ backing_filename = bdrv_get_full_backing_filename(bs, &local_err);
if (local_err) {
ret = -EINVAL;
error_propagate(errp, local_err);
@@ -2389,9 +2456,8 @@
qdict_put_str(options, "driver", bs->backing_format);
}
- backing_hd = bdrv_open_inherit(*backing_filename ? backing_filename : NULL,
- reference, options, 0, bs, &child_backing,
- errp);
+ backing_hd = bdrv_open_inherit(backing_filename, reference, options, 0, bs,
+ &child_backing, errp);
if (!backing_hd) {
bs->open_flags |= BDRV_O_NO_BACKING;
error_prepend(errp, "Could not open backing file: ");
@@ -2400,6 +2466,12 @@
}
bdrv_set_aio_context(backing_hd, bdrv_get_aio_context(bs));
+ if (implicit_backing) {
+ bdrv_refresh_filename(backing_hd);
+ pstrcpy(bs->auto_backing_file, sizeof(bs->auto_backing_file),
+ backing_hd->filename);
+ }
+
/* Hook up the backing file link; drop our reference, bs owns the
* backing_hd reference now */
bdrv_set_backing_hd(bs, backing_hd, &local_err);
@@ -2839,8 +2911,6 @@
g_free(child_key_dot);
}
- bdrv_refresh_filename(bs);
-
/* Check if any unknown options were used */
if (qdict_size(options) != 0) {
const QDictEntry *entry = qdict_first(options);
@@ -3285,6 +3355,7 @@
if (local_err != NULL) {
error_propagate(errp, local_err);
} else {
+ bdrv_refresh_filename(reopen_state->bs);
error_setg(errp, "failed while preparing to reopen image '%s'",
reopen_state->bs->filename);
}
@@ -3542,7 +3613,9 @@
static bool should_update_child(BdrvChild *c, BlockDriverState *to)
{
- BdrvChild *to_c;
+ GQueue *queue;
+ GHashTable *found;
+ bool ret;
if (c->role->stay_at_node) {
return false;
@@ -3578,14 +3651,43 @@
* if A is a child of B, that means we cannot replace A by B there
* because that would create a loop. Silently detaching A from B
* is also not really an option. So overall just leaving A in
- * place there is the most sensible choice. */
- QLIST_FOREACH(to_c, &to->children, next) {
- if (to_c == c) {
- return false;
+ * place there is the most sensible choice.
+ *
+ * We would also create a loop in any cases where @c is only
+ * indirectly referenced by @to. Prevent this by returning false
+ * if @c is found (by breadth-first search) anywhere in the whole
+ * subtree of @to.
+ */
+
+ ret = true;
+ found = g_hash_table_new(NULL, NULL);
+ g_hash_table_add(found, to);
+ queue = g_queue_new();
+ g_queue_push_tail(queue, to);
+
+ while (!g_queue_is_empty(queue)) {
+ BlockDriverState *v = g_queue_pop_head(queue);
+ BdrvChild *c2;
+
+ QLIST_FOREACH(c2, &v->children, next) {
+ if (c2 == c) {
+ ret = false;
+ break;
+ }
+
+ if (g_hash_table_contains(found, c2->bs)) {
+ continue;
+ }
+
+ g_queue_push_tail(queue, c2->bs);
+ g_hash_table_add(found, c2->bs);
}
}
- return true;
+ g_queue_free(queue);
+ g_hash_table_destroy(found);
+
+ return ret;
}
void bdrv_replace_node(BlockDriverState *from, BlockDriverState *to,
@@ -3789,6 +3891,8 @@
if (ret == 0) {
pstrcpy(bs->backing_file, sizeof(bs->backing_file), backing_file ?: "");
pstrcpy(bs->backing_format, sizeof(bs->backing_format), backing_fmt ?: "");
+ pstrcpy(bs->auto_backing_file, sizeof(bs->auto_backing_file),
+ backing_file ?: "");
}
return ret;
}
@@ -3881,7 +3985,10 @@
/* success - we can delete the intermediate states, and link top->base */
/* TODO Check graph modification op blockers (BLK_PERM_GRAPH_MOD) once
* we've figured out how they should work. */
- backing_file_str = backing_file_str ? backing_file_str : base->filename;
+ if (!backing_file_str) {
+ bdrv_refresh_filename(base);
+ backing_file_str = base->filename;
+ }
QLIST_FOREACH_SAFE(c, &top->parents, next_parent, next) {
/* Check whether we are allowed to switch c from top to base */
@@ -4429,16 +4536,6 @@
return bs->supported_zero_flags & BDRV_REQ_MAY_UNMAP;
}
-const char *bdrv_get_encrypted_filename(BlockDriverState *bs)
-{
- if (bs->backing && bs->backing->bs->encrypted)
- return bs->backing_file;
- else if (bs->encrypted)
- return bs->filename;
- else
- return NULL;
-}
-
void bdrv_get_backing_filename(BlockDriverState *bs,
char *filename, int filename_size)
{
@@ -4547,7 +4644,6 @@
int is_protocol = 0;
BlockDriverState *curr_bs = NULL;
BlockDriverState *retval = NULL;
- Error *local_error = NULL;
if (!bs || !bs->drv || !backing_file) {
return NULL;
@@ -4555,7 +4651,6 @@
filename_full = g_malloc(PATH_MAX);
backing_file_full = g_malloc(PATH_MAX);
- filename_tmp = g_malloc(PATH_MAX);
is_protocol = path_has_protocol(backing_file);
@@ -4564,41 +4659,43 @@
/* If either of the filename paths is actually a protocol, then
* compare unmodified paths; otherwise make paths relative */
if (is_protocol || path_has_protocol(curr_bs->backing_file)) {
+ char *backing_file_full_ret;
+
if (strcmp(backing_file, curr_bs->backing_file) == 0) {
retval = curr_bs->backing->bs;
break;
}
/* Also check against the full backing filename for the image */
- bdrv_get_full_backing_filename(curr_bs, backing_file_full, PATH_MAX,
- &local_error);
- if (local_error == NULL) {
- if (strcmp(backing_file, backing_file_full) == 0) {
+ backing_file_full_ret = bdrv_get_full_backing_filename(curr_bs,
+ NULL);
+ if (backing_file_full_ret) {
+ bool equal = strcmp(backing_file, backing_file_full_ret) == 0;
+ g_free(backing_file_full_ret);
+ if (equal) {
retval = curr_bs->backing->bs;
break;
}
- } else {
- error_free(local_error);
- local_error = NULL;
}
} else {
/* If not an absolute filename path, make it relative to the current
* image's filename path */
- path_combine(filename_tmp, PATH_MAX, curr_bs->filename,
- backing_file);
-
- /* We are going to compare absolute pathnames */
- if (!realpath(filename_tmp, filename_full)) {
+ filename_tmp = bdrv_make_absolute_filename(curr_bs, backing_file,
+ NULL);
+ /* We are going to compare canonicalized absolute pathnames */
+ if (!filename_tmp || !realpath(filename_tmp, filename_full)) {
+ g_free(filename_tmp);
continue;
}
+ g_free(filename_tmp);
/* We need to make sure the backing filename we are comparing against
* is relative to the current image filename (or absolute) */
- path_combine(filename_tmp, PATH_MAX, curr_bs->filename,
- curr_bs->backing_file);
-
- if (!realpath(filename_tmp, backing_file_full)) {
+ filename_tmp = bdrv_get_full_backing_filename(curr_bs, NULL);
+ if (!filename_tmp || !realpath(filename_tmp, backing_file_full)) {
+ g_free(filename_tmp);
continue;
}
+ g_free(filename_tmp);
if (strcmp(backing_file_full, filename_full) == 0) {
retval = curr_bs->backing->bs;
@@ -4609,7 +4706,6 @@
g_free(filename_full);
g_free(backing_file_full);
- g_free(filename_tmp);
return retval;
}
@@ -5096,17 +5192,17 @@
size = qemu_opt_get_size(opts, BLOCK_OPT_SIZE, img_size);
if (backing_file && !(flags & BDRV_O_NO_BACKING)) {
BlockDriverState *bs;
- char *full_backing = g_new0(char, PATH_MAX);
+ char *full_backing;
int back_flags;
QDict *backing_options = NULL;
- bdrv_get_full_backing_filename_from_filename(filename, backing_file,
- full_backing, PATH_MAX,
- &local_err);
+ full_backing =
+ bdrv_get_full_backing_filename_from_filename(filename, backing_file,
+ &local_err);
if (local_err) {
- g_free(full_backing);
goto out;
}
+ assert(full_backing);
/* backing files always opened read-only */
back_flags = flags;
@@ -5227,6 +5323,9 @@
bdrv_detach_aio_context(child->bs);
}
+ if (bs->quiesce_counter) {
+ aio_enable_external(bs->aio_context);
+ }
bs->aio_context = NULL;
}
@@ -5240,6 +5339,10 @@
return;
}
+ if (bs->quiesce_counter) {
+ aio_disable_external(new_context);
+ }
+
bs->aio_context = new_context;
QLIST_FOREACH(child, &bs->children, next) {
@@ -5261,18 +5364,16 @@
bs->walking_aio_notifiers = false;
}
+/* 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)
{
- AioContext *ctx = bdrv_get_aio_context(bs);
-
- aio_disable_external(ctx);
- bdrv_parent_drained_begin(bs, NULL, false);
- bdrv_drain(bs); /* ensure there are no in-flight requests */
-
- while (aio_poll(ctx, false)) {
- /* wait for all bottom halves to execute */
+ if (bdrv_get_aio_context(bs) == new_context) {
+ return;
}
+ bdrv_drained_begin(bs);
bdrv_detach_aio_context(bs);
/* This function executes in the old AioContext so acquire the new one in
@@ -5280,8 +5381,7 @@
*/
aio_context_acquire(new_context);
bdrv_attach_aio_context(bs, new_context);
- bdrv_parent_drained_end(bs, NULL, false);
- aio_enable_external(ctx);
+ bdrv_drained_end(bs);
aio_context_release(new_context);
}
@@ -5435,33 +5535,113 @@
return to_replace_bs;
}
-static bool append_open_options(QDict *d, BlockDriverState *bs)
+/**
+ * Iterates through the list of runtime option keys that are said to
+ * be "strong" for a BDS. An option is called "strong" if it changes
+ * a BDS's data. For example, the null block driver's "size" and
+ * "read-zeroes" options are strong, but its "latency-ns" option is
+ * not.
+ *
+ * If a key returned by this function ends with a dot, all options
+ * starting with that prefix are strong.
+ */
+static const char *const *strong_options(BlockDriverState *bs,
+ const char *const *curopt)
{
- const QDictEntry *entry;
- QemuOptDesc *desc;
- bool found_any = false;
+ static const char *const global_options[] = {
+ "driver", "filename", NULL
+ };
- for (entry = qdict_first(bs->options); entry;
- entry = qdict_next(bs->options, entry))
- {
- /* Exclude all non-driver-specific options */
- for (desc = bdrv_runtime_opts.desc; desc->name; desc++) {
- if (!strcmp(qdict_entry_key(entry), desc->name)) {
- break;
+ if (!curopt) {
+ return &global_options[0];
+ }
+
+ curopt++;
+ if (curopt == &global_options[ARRAY_SIZE(global_options) - 1] && bs->drv) {
+ curopt = bs->drv->strong_runtime_opts;
+ }
+
+ return (curopt && *curopt) ? curopt : NULL;
+}
+
+/**
+ * Copies all strong runtime options from bs->options to the given
+ * QDict. The set of strong option keys is determined by invoking
+ * strong_options().
+ *
+ * Returns true iff any strong option was present in bs->options (and
+ * thus copied to the target QDict) with the exception of "filename"
+ * and "driver". The caller is expected to use this value to decide
+ * whether the existence of strong options prevents the generation of
+ * a plain filename.
+ */
+static bool append_strong_runtime_options(QDict *d, BlockDriverState *bs)
+{
+ bool found_any = false;
+ const char *const *option_name = NULL;
+
+ if (!bs->drv) {
+ return false;
+ }
+
+ while ((option_name = strong_options(bs, option_name))) {
+ bool option_given = false;
+
+ assert(strlen(*option_name) > 0);
+ if ((*option_name)[strlen(*option_name) - 1] != '.') {
+ QObject *entry = qdict_get(bs->options, *option_name);
+ if (!entry) {
+ continue;
+ }
+
+ qdict_put_obj(d, *option_name, qobject_ref(entry));
+ option_given = true;
+ } else {
+ const QDictEntry *entry;
+ for (entry = qdict_first(bs->options); entry;
+ entry = qdict_next(bs->options, entry))
+ {
+ if (strstart(qdict_entry_key(entry), *option_name, NULL)) {
+ qdict_put_obj(d, qdict_entry_key(entry),
+ qobject_ref(qdict_entry_value(entry)));
+ option_given = true;
+ }
}
}
- if (desc->name) {
- continue;
- }
- qdict_put_obj(d, qdict_entry_key(entry),
- qobject_ref(qdict_entry_value(entry)));
- found_any = true;
+ /* While "driver" and "filename" need to be included in a JSON filename,
+ * their existence does not prohibit generation of a plain filename. */
+ if (!found_any && option_given &&
+ strcmp(*option_name, "driver") && strcmp(*option_name, "filename"))
+ {
+ found_any = true;
+ }
+ }
+
+ if (!qdict_haskey(d, "driver")) {
+ /* Drivers created with bdrv_new_open_driver() may not have a
+ * @driver option. Add it here. */
+ qdict_put_str(d, "driver", bs->drv->format_name);
}
return found_any;
}
+/* Note: This function may return false positives; it may return true
+ * even if opening the backing file specified by bs's image header
+ * would result in exactly bs->backing. */
+static bool bdrv_backing_overridden(BlockDriverState *bs)
+{
+ if (bs->backing) {
+ return strcmp(bs->auto_backing_file,
+ bs->backing->bs->filename);
+ } else {
+ /* No backing BDS, so if the image header reports any backing
+ * file, it must have been suppressed */
+ return bs->auto_backing_file[0] != '\0';
+ }
+}
+
/* Updates the following BDS fields:
* - exact_filename: A filename which may be used for opening a block device
* which (mostly) equals the given BDS (even without any
@@ -5477,92 +5657,108 @@
void bdrv_refresh_filename(BlockDriverState *bs)
{
BlockDriver *drv = bs->drv;
+ BdrvChild *child;
QDict *opts;
+ bool backing_overridden;
+ bool generate_json_filename; /* Whether our default implementation should
+ fill exact_filename (false) or not (true) */
if (!drv) {
return;
}
- /* This BDS's file name will most probably depend on its file's name, so
- * refresh that first */
- if (bs->file) {
- bdrv_refresh_filename(bs->file->bs);
+ /* This BDS's file name may depend on any of its children's file names, so
+ * refresh those first */
+ QLIST_FOREACH(child, &bs->children, next) {
+ bdrv_refresh_filename(child->bs);
}
+ if (bs->implicit) {
+ /* For implicit nodes, just copy everything from the single child */
+ child = QLIST_FIRST(&bs->children);
+ assert(QLIST_NEXT(child, next) == NULL);
+
+ pstrcpy(bs->exact_filename, sizeof(bs->exact_filename),
+ child->bs->exact_filename);
+ pstrcpy(bs->filename, sizeof(bs->filename), child->bs->filename);
+
+ bs->full_open_options = qobject_ref(child->bs->full_open_options);
+
+ return;
+ }
+
+ backing_overridden = bdrv_backing_overridden(bs);
+
+ if (bs->open_flags & BDRV_O_NO_IO) {
+ /* Without I/O, the backing file does not change anything.
+ * Therefore, in such a case (primarily qemu-img), we can
+ * pretend the backing file has not been overridden even if
+ * it technically has been. */
+ backing_overridden = false;
+ }
+
+ /* Gather the options QDict */
+ opts = qdict_new();
+ generate_json_filename = append_strong_runtime_options(opts, bs);
+ generate_json_filename |= backing_overridden;
+
+ if (drv->bdrv_gather_child_options) {
+ /* Some block drivers may not want to present all of their children's
+ * options, or name them differently from BdrvChild.name */
+ drv->bdrv_gather_child_options(bs, opts, backing_overridden);
+ } else {
+ QLIST_FOREACH(child, &bs->children, next) {
+ if (child->role == &child_backing && !backing_overridden) {
+ /* We can skip the backing BDS if it has not been overridden */
+ continue;
+ }
+
+ qdict_put(opts, child->name,
+ qobject_ref(child->bs->full_open_options));
+ }
+
+ if (backing_overridden && !bs->backing) {
+ /* Force no backing file */
+ qdict_put_null(opts, "backing");
+ }
+ }
+
+ qobject_unref(bs->full_open_options);
+ bs->full_open_options = opts;
+
if (drv->bdrv_refresh_filename) {
/* Obsolete information is of no use here, so drop the old file name
* information before refreshing it */
bs->exact_filename[0] = '\0';
- if (bs->full_open_options) {
- qobject_unref(bs->full_open_options);
- bs->full_open_options = NULL;
- }
- opts = qdict_new();
- append_open_options(opts, bs);
- drv->bdrv_refresh_filename(bs, opts);
- qobject_unref(opts);
+ drv->bdrv_refresh_filename(bs);
} else if (bs->file) {
/* Try to reconstruct valid information from the underlying file */
- bool has_open_options;
bs->exact_filename[0] = '\0';
- if (bs->full_open_options) {
- qobject_unref(bs->full_open_options);
- bs->full_open_options = NULL;
- }
- opts = qdict_new();
- has_open_options = append_open_options(opts, bs);
-
- /* If no specific options have been given for this BDS, the filename of
- * the underlying file should suffice for this one as well */
- if (bs->file->bs->exact_filename[0] && !has_open_options) {
+ /*
+ * We can use the underlying file's filename if:
+ * - it has a filename,
+ * - the file is a protocol BDS, and
+ * - opening that file (as this BDS's format) will automatically create
+ * the BDS tree we have right now, that is:
+ * - the user did not significantly change this BDS's behavior with
+ * some explicit (strong) options
+ * - no non-file child of this BDS has been overridden by the user
+ * Both of these conditions are represented by generate_json_filename.
+ */
+ if (bs->file->bs->exact_filename[0] &&
+ bs->file->bs->drv->bdrv_file_open &&
+ !generate_json_filename)
+ {
strcpy(bs->exact_filename, bs->file->bs->exact_filename);
}
- /* Reconstructing the full options QDict is simple for most format block
- * drivers, as long as the full options are known for the underlying
- * file BDS. The full options QDict of that file BDS should somehow
- * contain a representation of the filename, therefore the following
- * suffices without querying the (exact_)filename of this BDS. */
- if (bs->file->bs->full_open_options) {
- qdict_put_str(opts, "driver", drv->format_name);
- qdict_put(opts, "file",
- qobject_ref(bs->file->bs->full_open_options));
-
- bs->full_open_options = opts;
- } else {
- qobject_unref(opts);
- }
- } else if (!bs->full_open_options && qdict_size(bs->options)) {
- /* There is no underlying file BDS (at least referenced by BDS.file),
- * so the full options QDict should be equal to the options given
- * specifically for this block device when it was opened (plus the
- * driver specification).
- * Because those options don't change, there is no need to update
- * full_open_options when it's already set. */
-
- opts = qdict_new();
- append_open_options(opts, bs);
- qdict_put_str(opts, "driver", drv->format_name);
-
- if (bs->exact_filename[0]) {
- /* This may not work for all block protocol drivers (some may
- * require this filename to be parsed), but we have to find some
- * default solution here, so just include it. If some block driver
- * does not support pure options without any filename at all or
- * needs some special format of the options QDict, it needs to
- * implement the driver-specific bdrv_refresh_filename() function.
- */
- qdict_put_str(opts, "filename", bs->exact_filename);
- }
-
- bs->full_open_options = opts;
}
if (bs->exact_filename[0]) {
pstrcpy(bs->filename, sizeof(bs->filename), bs->exact_filename);
- } else if (bs->full_open_options) {
+ } else {
QString *json = qobject_to_json(QOBJECT(bs->full_open_options));
snprintf(bs->filename, sizeof(bs->filename), "json:%s",
qstring_get_str(json));
@@ -5570,6 +5766,33 @@
}
}
+char *bdrv_dirname(BlockDriverState *bs, Error **errp)
+{
+ BlockDriver *drv = bs->drv;
+
+ if (!drv) {
+ error_setg(errp, "Node '%s' is ejected", bs->node_name);
+ return NULL;
+ }
+
+ if (drv->bdrv_dirname) {
+ return drv->bdrv_dirname(bs, errp);
+ }
+
+ if (bs->file) {
+ return bdrv_dirname(bs->file->bs, errp);
+ }
+
+ bdrv_refresh_filename(bs);
+ if (bs->exact_filename[0] != '\0') {
+ return path_combine(bs->exact_filename, "");
+ }
+
+ error_setg(errp, "Cannot generate a base directory for %s nodes",
+ drv->format_name);
+ return NULL;
+}
+
/*
* Hot add/remove a BDS's child. So the user can take a child offline when
* it is broken and take a new child online
diff --git a/block/backup.c b/block/backup.c
index 435414e..9988753 100644
--- a/block/backup.c
+++ b/block/backup.c
@@ -107,7 +107,6 @@
void **bounce_buffer)
{
int ret;
- struct iovec iov;
QEMUIOVector qiov;
BlockBackend *blk = job->common.blk;
int nbytes;
@@ -119,9 +118,7 @@
if (!*bounce_buffer) {
*bounce_buffer = blk_blockalign(blk, job->cluster_size);
}
- iov.iov_base = *bounce_buffer;
- iov.iov_len = nbytes;
- qemu_iovec_init_external(&qiov, &iov, 1);
+ qemu_iovec_init_buf(&qiov, *bounce_buffer, nbytes);
ret = blk_co_preadv(blk, start, qiov.size, &qiov, read_flags);
if (ret < 0) {
diff --git a/block/blkdebug.c b/block/blkdebug.c
index 0759452..1ea835c 100644
--- a/block/blkdebug.c
+++ b/block/blkdebug.c
@@ -811,51 +811,37 @@
return bdrv_getlength(bs->file->bs);
}
-static void blkdebug_refresh_filename(BlockDriverState *bs, QDict *options)
+static void blkdebug_refresh_filename(BlockDriverState *bs)
{
BDRVBlkdebugState *s = bs->opaque;
- QDict *opts;
const QDictEntry *e;
- bool force_json = false;
+ int ret;
- for (e = qdict_first(options); e; e = qdict_next(options, e)) {
- if (strcmp(qdict_entry_key(e), "config") &&
- strcmp(qdict_entry_key(e), "x-image"))
- {
- force_json = true;
- break;
- }
- }
-
- if (force_json && !bs->file->bs->full_open_options) {
- /* The config file cannot be recreated, so creating a plain filename
- * is impossible */
+ if (!bs->file->bs->exact_filename[0]) {
return;
}
- if (!force_json && bs->file->bs->exact_filename[0]) {
- int ret = snprintf(bs->exact_filename, sizeof(bs->exact_filename),
- "blkdebug:%s:%s", s->config_file ?: "",
- bs->file->bs->exact_filename);
- if (ret >= sizeof(bs->exact_filename)) {
- /* An overflow makes the filename unusable, so do not report any */
- bs->exact_filename[0] = 0;
+ for (e = qdict_first(bs->full_open_options); e;
+ e = qdict_next(bs->full_open_options, e))
+ {
+ /* Real child options are under "image", but "x-image" may
+ * contain a filename */
+ if (strcmp(qdict_entry_key(e), "config") &&
+ strcmp(qdict_entry_key(e), "image") &&
+ strcmp(qdict_entry_key(e), "x-image") &&
+ strcmp(qdict_entry_key(e), "driver"))
+ {
+ return;
}
}
- opts = qdict_new();
- qdict_put_str(opts, "driver", "blkdebug");
-
- qdict_put(opts, "image", qobject_ref(bs->file->bs->full_open_options));
-
- for (e = qdict_first(options); e; e = qdict_next(options, e)) {
- if (strcmp(qdict_entry_key(e), "x-image")) {
- qdict_put_obj(opts, qdict_entry_key(e),
- qobject_ref(qdict_entry_value(e)));
- }
+ ret = snprintf(bs->exact_filename, sizeof(bs->exact_filename),
+ "blkdebug:%s:%s",
+ s->config_file ?: "", bs->file->bs->exact_filename);
+ if (ret >= sizeof(bs->exact_filename)) {
+ /* An overflow makes the filename unusable, so do not report any */
+ bs->exact_filename[0] = 0;
}
-
- bs->full_open_options = opts;
}
static void blkdebug_refresh_limits(BlockDriverState *bs, Error **errp)
@@ -888,6 +874,20 @@
return 0;
}
+static const char *const blkdebug_strong_runtime_opts[] = {
+ "config",
+ "inject-error.",
+ "set-state.",
+ "align",
+ "max-transfer",
+ "opt-write-zero",
+ "max-write-zero",
+ "opt-discard",
+ "max-discard",
+
+ NULL
+};
+
static BlockDriver bdrv_blkdebug = {
.format_name = "blkdebug",
.protocol_name = "blkdebug",
@@ -917,6 +917,8 @@
= blkdebug_debug_remove_breakpoint,
.bdrv_debug_resume = blkdebug_debug_resume,
.bdrv_debug_is_suspended = blkdebug_debug_is_suspended,
+
+ .strong_runtime_opts = blkdebug_strong_runtime_opts,
};
static void bdrv_blkdebug_init(void)
diff --git a/block/blklogwrites.c b/block/blklogwrites.c
index d2e01bd..eb2b490 100644
--- a/block/blklogwrites.c
+++ b/block/blklogwrites.c
@@ -280,30 +280,6 @@
return bdrv_getlength(bs->file->bs);
}
-static void blk_log_writes_refresh_filename(BlockDriverState *bs,
- QDict *options)
-{
- BDRVBlkLogWritesState *s = bs->opaque;
-
- /* bs->file->bs has already been refreshed */
- bdrv_refresh_filename(s->log_file->bs);
-
- if (bs->file->bs->full_open_options
- && s->log_file->bs->full_open_options)
- {
- QDict *opts = qdict_new();
- qdict_put_str(opts, "driver", "blklogwrites");
-
- qobject_ref(bs->file->bs->full_open_options);
- qdict_put(opts, "file", bs->file->bs->full_open_options);
- qobject_ref(s->log_file->bs->full_open_options);
- qdict_put(opts, "log", s->log_file->bs->full_open_options);
- qdict_put_int(opts, "log-sector-size", s->sectorsize);
-
- bs->full_open_options = opts;
- }
-}
-
static void blk_log_writes_child_perm(BlockDriverState *bs, BdrvChild *c,
const BdrvChildRole *role,
BlockReopenQueue *ro_q,
@@ -520,6 +496,13 @@
LOG_DISCARD_FLAG, false);
}
+static const char *const blk_log_writes_strong_runtime_opts[] = {
+ "log-append",
+ "log-sector-size",
+
+ NULL
+};
+
static BlockDriver bdrv_blk_log_writes = {
.format_name = "blklogwrites",
.instance_size = sizeof(BDRVBlkLogWritesState),
@@ -527,7 +510,6 @@
.bdrv_open = blk_log_writes_open,
.bdrv_close = blk_log_writes_close,
.bdrv_getlength = blk_log_writes_getlength,
- .bdrv_refresh_filename = blk_log_writes_refresh_filename,
.bdrv_child_perm = blk_log_writes_child_perm,
.bdrv_refresh_limits = blk_log_writes_refresh_limits,
@@ -539,6 +521,7 @@
.bdrv_co_block_status = bdrv_co_block_status_from_file,
.is_filter = true,
+ .strong_runtime_opts = blk_log_writes_strong_runtime_opts,
};
static void bdrv_blk_log_writes_init(void)
diff --git a/block/blkverify.c b/block/blkverify.c
index 89bf438..3ff77ff 100644
--- a/block/blkverify.c
+++ b/block/blkverify.c
@@ -281,27 +281,10 @@
return bdrv_recurse_is_first_non_filter(s->test_file->bs, candidate);
}
-static void blkverify_refresh_filename(BlockDriverState *bs, QDict *options)
+static void blkverify_refresh_filename(BlockDriverState *bs)
{
BDRVBlkverifyState *s = bs->opaque;
- /* bs->file->bs has already been refreshed */
- bdrv_refresh_filename(s->test_file->bs);
-
- if (bs->file->bs->full_open_options
- && s->test_file->bs->full_open_options)
- {
- QDict *opts = qdict_new();
- qdict_put_str(opts, "driver", "blkverify");
-
- qdict_put(opts, "raw",
- qobject_ref(bs->file->bs->full_open_options));
- qdict_put(opts, "test",
- qobject_ref(s->test_file->bs->full_open_options));
-
- bs->full_open_options = opts;
- }
-
if (bs->file->bs->exact_filename[0]
&& s->test_file->bs->exact_filename[0])
{
@@ -316,6 +299,15 @@
}
}
+static char *blkverify_dirname(BlockDriverState *bs, Error **errp)
+{
+ /* In general, there are two BDSs with different dirnames below this one;
+ * so there is no unique dirname we could return (unless both are equal by
+ * chance). Therefore, to be consistent, just always return NULL. */
+ error_setg(errp, "Cannot generate a base directory for blkverify nodes");
+ return NULL;
+}
+
static BlockDriver bdrv_blkverify = {
.format_name = "blkverify",
.protocol_name = "blkverify",
@@ -327,6 +319,7 @@
.bdrv_child_perm = bdrv_filter_default_perms,
.bdrv_getlength = blkverify_getlength,
.bdrv_refresh_filename = blkverify_refresh_filename,
+ .bdrv_dirname = blkverify_dirname,
.bdrv_co_preadv = blkverify_co_preadv,
.bdrv_co_pwritev = blkverify_co_pwritev,
diff --git a/block/block-backend.c b/block/block-backend.c
index f6ea824..edad02a 100644
--- a/block/block-backend.c
+++ b/block/block-backend.c
@@ -1204,17 +1204,8 @@
int64_t bytes, CoroutineEntry co_entry,
BdrvRequestFlags flags)
{
- QEMUIOVector qiov;
- struct iovec iov;
- BlkRwCo rwco;
-
- iov = (struct iovec) {
- .iov_base = buf,
- .iov_len = bytes,
- };
- qemu_iovec_init_external(&qiov, &iov, 1);
-
- rwco = (BlkRwCo) {
+ QEMUIOVector qiov = QEMU_IOVEC_INIT_BUF(qiov, buf, bytes);
+ BlkRwCo rwco = {
.blk = blk,
.offset = offset,
.iobuf = &qiov,
@@ -1262,12 +1253,12 @@
return bdrv_make_zero(blk->root, flags);
}
-static void blk_inc_in_flight(BlockBackend *blk)
+void blk_inc_in_flight(BlockBackend *blk)
{
atomic_inc(&blk->in_flight);
}
-static void blk_dec_in_flight(BlockBackend *blk)
+void blk_dec_in_flight(BlockBackend *blk)
{
atomic_dec(&blk->in_flight);
aio_wait_kick();
diff --git a/block/commit.c b/block/commit.c
index 53148e6..3b46ca7 100644
--- a/block/commit.c
+++ b/block/commit.c
@@ -47,14 +47,9 @@
void *buf)
{
int ret = 0;
- QEMUIOVector qiov;
- struct iovec iov = {
- .iov_base = buf,
- .iov_len = bytes,
- };
+ QEMUIOVector qiov = QEMU_IOVEC_INIT_BUF(qiov, buf, bytes);
assert(bytes < SIZE_MAX);
- qemu_iovec_init_external(&qiov, &iov, 1);
ret = blk_co_preadv(bs, offset, qiov.size, &qiov, 0);
if (ret < 0) {
@@ -230,9 +225,8 @@
return bdrv_co_preadv(bs->backing, offset, bytes, qiov, flags);
}
-static void bdrv_commit_top_refresh_filename(BlockDriverState *bs, QDict *opts)
+static void bdrv_commit_top_refresh_filename(BlockDriverState *bs)
{
- bdrv_refresh_filename(bs->backing->bs);
pstrcpy(bs->exact_filename, sizeof(bs->exact_filename),
bs->backing->bs->filename);
}
@@ -374,10 +368,12 @@
if (s->top) {
blk_unref(s->top);
}
+ job_early_fail(&s->common.job);
+ /* commit_top_bs has to be replaced after deleting the block job,
+ * otherwise this would fail because of lack of permissions. */
if (commit_top_bs) {
bdrv_replace_node(commit_top_bs, top, &error_abort);
}
- job_early_fail(&s->common.job);
}
diff --git a/block/crypto.c b/block/crypto.c
index d5b1da6..fd8c7cf 100644
--- a/block/crypto.c
+++ b/block/crypto.c
@@ -619,6 +619,12 @@
return spec_info;
}
+static const char *const block_crypto_strong_runtime_opts[] = {
+ BLOCK_CRYPTO_OPT_LUKS_KEY_SECRET,
+
+ NULL
+};
+
BlockDriver bdrv_crypto_luks = {
.format_name = "luks",
.instance_size = sizeof(BlockCrypto),
@@ -640,6 +646,8 @@
.bdrv_getlength = block_crypto_getlength,
.bdrv_get_info = block_crypto_get_info_luks,
.bdrv_get_specific_info = block_crypto_get_specific_info_luks,
+
+ .strong_runtime_opts = block_crypto_strong_runtime_opts,
};
static void block_crypto_init(void)
diff --git a/block/curl.c b/block/curl.c
index b7ac265..606709f 100644
--- a/block/curl.c
+++ b/block/curl.c
@@ -61,8 +61,6 @@
#define CURL_NUM_STATES 8
#define CURL_NUM_ACB 8
-#define READ_AHEAD_DEFAULT (256 * 1024)
-#define CURL_TIMEOUT_DEFAULT 5
#define CURL_TIMEOUT_MAX 10000
#define CURL_BLOCK_OPT_URL "url"
@@ -76,6 +74,10 @@
#define CURL_BLOCK_OPT_PROXY_USERNAME "proxy-username"
#define CURL_BLOCK_OPT_PROXY_PASSWORD_SECRET "proxy-password-secret"
+#define CURL_BLOCK_OPT_READAHEAD_DEFAULT (256 * 1024)
+#define CURL_BLOCK_OPT_SSLVERIFY_DEFAULT true
+#define CURL_BLOCK_OPT_TIMEOUT_DEFAULT 5
+
struct BDRVCURLState;
static bool libcurl_initialized;
@@ -696,7 +698,7 @@
}
s->readahead_size = qemu_opt_get_size(opts, CURL_BLOCK_OPT_READAHEAD,
- READ_AHEAD_DEFAULT);
+ CURL_BLOCK_OPT_READAHEAD_DEFAULT);
if ((s->readahead_size & 0x1ff) != 0) {
error_setg(errp, "HTTP_READAHEAD_SIZE %zd is not a multiple of 512",
s->readahead_size);
@@ -704,13 +706,14 @@
}
s->timeout = qemu_opt_get_number(opts, CURL_BLOCK_OPT_TIMEOUT,
- CURL_TIMEOUT_DEFAULT);
+ CURL_BLOCK_OPT_TIMEOUT_DEFAULT);
if (s->timeout > CURL_TIMEOUT_MAX) {
error_setg(errp, "timeout parameter is too large or negative");
goto out_noclean;
}
- s->sslverify = qemu_opt_get_bool(opts, CURL_BLOCK_OPT_SSLVERIFY, true);
+ s->sslverify = qemu_opt_get_bool(opts, CURL_BLOCK_OPT_SSLVERIFY,
+ CURL_BLOCK_OPT_SSLVERIFY_DEFAULT);
cookie = qemu_opt_get(opts, CURL_BLOCK_OPT_COOKIE);
cookie_secret = qemu_opt_get(opts, CURL_BLOCK_OPT_COOKIE_SECRET);
@@ -947,6 +950,36 @@
return s->len;
}
+static void curl_refresh_filename(BlockDriverState *bs)
+{
+ BDRVCURLState *s = bs->opaque;
+
+ /* "readahead" and "timeout" do not change the guest-visible data,
+ * so ignore them */
+ if (s->sslverify != CURL_BLOCK_OPT_SSLVERIFY_DEFAULT ||
+ s->cookie || s->username || s->password || s->proxyusername ||
+ s->proxypassword)
+ {
+ return;
+ }
+
+ pstrcpy(bs->exact_filename, sizeof(bs->exact_filename), s->url);
+}
+
+
+static const char *const curl_strong_runtime_opts[] = {
+ CURL_BLOCK_OPT_URL,
+ CURL_BLOCK_OPT_SSLVERIFY,
+ CURL_BLOCK_OPT_COOKIE,
+ CURL_BLOCK_OPT_COOKIE_SECRET,
+ CURL_BLOCK_OPT_USERNAME,
+ CURL_BLOCK_OPT_PASSWORD_SECRET,
+ CURL_BLOCK_OPT_PROXY_USERNAME,
+ CURL_BLOCK_OPT_PROXY_PASSWORD_SECRET,
+
+ NULL
+};
+
static BlockDriver bdrv_http = {
.format_name = "http",
.protocol_name = "http",
@@ -961,6 +994,9 @@
.bdrv_detach_aio_context = curl_detach_aio_context,
.bdrv_attach_aio_context = curl_attach_aio_context,
+
+ .bdrv_refresh_filename = curl_refresh_filename,
+ .strong_runtime_opts = curl_strong_runtime_opts,
};
static BlockDriver bdrv_https = {
@@ -977,6 +1013,9 @@
.bdrv_detach_aio_context = curl_detach_aio_context,
.bdrv_attach_aio_context = curl_attach_aio_context,
+
+ .bdrv_refresh_filename = curl_refresh_filename,
+ .strong_runtime_opts = curl_strong_runtime_opts,
};
static BlockDriver bdrv_ftp = {
@@ -993,6 +1032,9 @@
.bdrv_detach_aio_context = curl_detach_aio_context,
.bdrv_attach_aio_context = curl_attach_aio_context,
+
+ .bdrv_refresh_filename = curl_refresh_filename,
+ .strong_runtime_opts = curl_strong_runtime_opts,
};
static BlockDriver bdrv_ftps = {
@@ -1009,6 +1051,9 @@
.bdrv_detach_aio_context = curl_detach_aio_context,
.bdrv_attach_aio_context = curl_attach_aio_context,
+
+ .bdrv_refresh_filename = curl_refresh_filename,
+ .strong_runtime_opts = curl_strong_runtime_opts,
};
static void curl_block_init(void)
diff --git a/block/gluster.c b/block/gluster.c
index 7289106..af64330 100644
--- a/block/gluster.c
+++ b/block/gluster.c
@@ -1495,6 +1495,21 @@
}
+static const char *const gluster_strong_open_opts[] = {
+ GLUSTER_OPT_VOLUME,
+ GLUSTER_OPT_PATH,
+ GLUSTER_OPT_TYPE,
+ GLUSTER_OPT_SERVER_PATTERN,
+ GLUSTER_OPT_HOST,
+ GLUSTER_OPT_PORT,
+ GLUSTER_OPT_TO,
+ GLUSTER_OPT_IPV4,
+ GLUSTER_OPT_IPV6,
+ GLUSTER_OPT_SOCKET,
+
+ NULL
+};
+
static BlockDriver bdrv_gluster = {
.format_name = "gluster",
.protocol_name = "gluster",
@@ -1522,6 +1537,7 @@
#endif
.bdrv_co_block_status = qemu_gluster_co_block_status,
.create_opts = &qemu_gluster_create_opts,
+ .strong_runtime_opts = gluster_strong_open_opts,
};
static BlockDriver bdrv_gluster_tcp = {
@@ -1551,6 +1567,7 @@
#endif
.bdrv_co_block_status = qemu_gluster_co_block_status,
.create_opts = &qemu_gluster_create_opts,
+ .strong_runtime_opts = gluster_strong_open_opts,
};
static BlockDriver bdrv_gluster_unix = {
@@ -1580,6 +1597,7 @@
#endif
.bdrv_co_block_status = qemu_gluster_co_block_status,
.create_opts = &qemu_gluster_create_opts,
+ .strong_runtime_opts = gluster_strong_open_opts,
};
/* rdma is deprecated (actually never supported for volfile fetch).
@@ -1615,6 +1633,7 @@
#endif
.bdrv_co_block_status = qemu_gluster_co_block_status,
.create_opts = &qemu_gluster_create_opts,
+ .strong_runtime_opts = gluster_strong_open_opts,
};
static void bdrv_gluster_init(void)
diff --git a/block/io.c b/block/io.c
index 213ca03..2ba603c 100644
--- a/block/io.c
+++ b/block/io.c
@@ -843,17 +843,13 @@
static int bdrv_rw_co(BdrvChild *child, int64_t sector_num, uint8_t *buf,
int nb_sectors, bool is_write, BdrvRequestFlags flags)
{
- QEMUIOVector qiov;
- struct iovec iov = {
- .iov_base = (void *)buf,
- .iov_len = nb_sectors * BDRV_SECTOR_SIZE,
- };
+ QEMUIOVector qiov = QEMU_IOVEC_INIT_BUF(qiov, buf,
+ nb_sectors * BDRV_SECTOR_SIZE);
if (nb_sectors < 0 || nb_sectors > BDRV_REQUEST_MAX_SECTORS) {
return -EINVAL;
}
- qemu_iovec_init_external(&qiov, &iov, 1);
return bdrv_prwv_co(child, sector_num << BDRV_SECTOR_BITS,
&qiov, is_write, flags);
}
@@ -880,13 +876,8 @@
int bdrv_pwrite_zeroes(BdrvChild *child, int64_t offset,
int bytes, BdrvRequestFlags flags)
{
- QEMUIOVector qiov;
- struct iovec iov = {
- .iov_base = NULL,
- .iov_len = bytes,
- };
+ QEMUIOVector qiov = QEMU_IOVEC_INIT_BUF(qiov, NULL, bytes);
- qemu_iovec_init_external(&qiov, &iov, 1);
return bdrv_prwv_co(child, offset, &qiov, true,
BDRV_REQ_ZERO_WRITE | flags);
}
@@ -950,17 +941,12 @@
int bdrv_pread(BdrvChild *child, int64_t offset, void *buf, int bytes)
{
- QEMUIOVector qiov;
- struct iovec iov = {
- .iov_base = (void *)buf,
- .iov_len = bytes,
- };
+ QEMUIOVector qiov = QEMU_IOVEC_INIT_BUF(qiov, buf, bytes);
if (bytes < 0) {
return -EINVAL;
}
- qemu_iovec_init_external(&qiov, &iov, 1);
return bdrv_preadv(child, offset, &qiov);
}
@@ -978,17 +964,12 @@
int bdrv_pwrite(BdrvChild *child, int64_t offset, const void *buf, int bytes)
{
- QEMUIOVector qiov;
- struct iovec iov = {
- .iov_base = (void *) buf,
- .iov_len = bytes,
- };
+ QEMUIOVector qiov = QEMU_IOVEC_INIT_BUF(qiov, buf, bytes);
if (bytes < 0) {
return -EINVAL;
}
- qemu_iovec_init_external(&qiov, &iov, 1);
return bdrv_pwritev(child, offset, &qiov);
}
@@ -1165,7 +1146,6 @@
void *bounce_buffer;
BlockDriver *drv = bs->drv;
- struct iovec iov;
QEMUIOVector local_qiov;
int64_t cluster_offset;
int64_t cluster_bytes;
@@ -1230,9 +1210,8 @@
if (ret <= 0) {
/* Must copy-on-read; use the bounce buffer */
- iov.iov_base = bounce_buffer;
- iov.iov_len = pnum = MIN(pnum, MAX_BOUNCE_BUFFER);
- qemu_iovec_init_external(&local_qiov, &iov, 1);
+ pnum = MIN(pnum, MAX_BOUNCE_BUFFER);
+ qemu_iovec_init_buf(&local_qiov, bounce_buffer, pnum);
ret = bdrv_driver_preadv(bs, cluster_offset, pnum,
&local_qiov, 0);
@@ -1477,7 +1456,7 @@
{
BlockDriver *drv = bs->drv;
QEMUIOVector qiov;
- struct iovec iov = {0};
+ void *buf = NULL;
int ret = 0;
bool need_flush = false;
int head = 0;
@@ -1547,16 +1526,14 @@
need_flush = true;
}
num = MIN(num, max_transfer);
- iov.iov_len = num;
- if (iov.iov_base == NULL) {
- iov.iov_base = qemu_try_blockalign(bs, num);
- if (iov.iov_base == NULL) {
+ if (buf == NULL) {
+ buf = qemu_try_blockalign0(bs, num);
+ if (buf == NULL) {
ret = -ENOMEM;
goto fail;
}
- memset(iov.iov_base, 0, num);
}
- qemu_iovec_init_external(&qiov, &iov, 1);
+ qemu_iovec_init_buf(&qiov, buf, num);
ret = bdrv_driver_pwritev(bs, offset, num, &qiov, write_flags);
@@ -1564,8 +1541,8 @@
* all future requests.
*/
if (num < max_transfer) {
- qemu_vfree(iov.iov_base);
- iov.iov_base = NULL;
+ qemu_vfree(buf);
+ buf = NULL;
}
}
@@ -1577,7 +1554,7 @@
if (ret == 0 && need_flush) {
ret = bdrv_co_flush(bs);
}
- qemu_vfree(iov.iov_base);
+ qemu_vfree(buf);
return ret;
}
@@ -1763,7 +1740,6 @@
BlockDriverState *bs = child->bs;
uint8_t *buf = NULL;
QEMUIOVector local_qiov;
- struct iovec iov;
uint64_t align = bs->bl.request_alignment;
unsigned int head_padding_bytes, tail_padding_bytes;
int ret = 0;
@@ -1775,11 +1751,7 @@
assert(flags & BDRV_REQ_ZERO_WRITE);
if (head_padding_bytes || tail_padding_bytes) {
buf = qemu_blockalign(bs, align);
- iov = (struct iovec) {
- .iov_base = buf,
- .iov_len = align,
- };
- qemu_iovec_init_external(&local_qiov, &iov, 1);
+ qemu_iovec_init_buf(&local_qiov, buf, align);
}
if (head_padding_bytes) {
uint64_t zero_bytes = MIN(bytes, align - head_padding_bytes);
@@ -1885,17 +1857,12 @@
if (offset & (align - 1)) {
QEMUIOVector head_qiov;
- struct iovec head_iov;
mark_request_serialising(&req, align);
wait_serialising_requests(&req);
head_buf = qemu_blockalign(bs, align);
- head_iov = (struct iovec) {
- .iov_base = head_buf,
- .iov_len = align,
- };
- qemu_iovec_init_external(&head_qiov, &head_iov, 1);
+ qemu_iovec_init_buf(&head_qiov, head_buf, align);
bdrv_debug_event(bs, BLKDBG_PWRITEV_RMW_HEAD);
ret = bdrv_aligned_preadv(child, &req, offset & ~(align - 1), align,
@@ -1924,7 +1891,6 @@
if ((offset + bytes) & (align - 1)) {
QEMUIOVector tail_qiov;
- struct iovec tail_iov;
size_t tail_bytes;
bool waited;
@@ -1933,11 +1899,7 @@
assert(!waited || !use_local_qiov);
tail_buf = qemu_blockalign(bs, align);
- tail_iov = (struct iovec) {
- .iov_base = tail_buf,
- .iov_len = align,
- };
- qemu_iovec_init_external(&tail_qiov, &tail_iov, 1);
+ qemu_iovec_init_buf(&tail_qiov, tail_buf, align);
bdrv_debug_event(bs, BLKDBG_PWRITEV_RMW_TAIL);
ret = bdrv_aligned_preadv(child, &req, (offset + bytes) & ~(align - 1),
@@ -2468,15 +2430,9 @@
int bdrv_save_vmstate(BlockDriverState *bs, const uint8_t *buf,
int64_t pos, int size)
{
- QEMUIOVector qiov;
- struct iovec iov = {
- .iov_base = (void *) buf,
- .iov_len = size,
- };
+ QEMUIOVector qiov = QEMU_IOVEC_INIT_BUF(qiov, buf, size);
int ret;
- qemu_iovec_init_external(&qiov, &iov, 1);
-
ret = bdrv_writev_vmstate(bs, &qiov, pos);
if (ret < 0) {
return ret;
@@ -2493,14 +2449,9 @@
int bdrv_load_vmstate(BlockDriverState *bs, uint8_t *buf,
int64_t pos, int size)
{
- QEMUIOVector qiov;
- struct iovec iov = {
- .iov_base = buf,
- .iov_len = size,
- };
+ QEMUIOVector qiov = QEMU_IOVEC_INIT_BUF(qiov, buf, size);
int ret;
- qemu_iovec_init_external(&qiov, &iov, 1);
ret = bdrv_readv_vmstate(bs, &qiov, pos);
if (ret < 0) {
return ret;
diff --git a/block/iscsi.c b/block/iscsi.c
index ff47320..a0c0084 100644
--- a/block/iscsi.c
+++ b/block/iscsi.c
@@ -2448,6 +2448,20 @@
}
};
+static const char *const iscsi_strong_runtime_opts[] = {
+ "transport",
+ "portal",
+ "target",
+ "user",
+ "password",
+ "password-secret",
+ "lun",
+ "initiator-name",
+ "header-digest",
+
+ NULL
+};
+
static BlockDriver bdrv_iscsi = {
.format_name = "iscsi",
.protocol_name = "iscsi",
@@ -2482,6 +2496,8 @@
.bdrv_detach_aio_context = iscsi_detach_aio_context,
.bdrv_attach_aio_context = iscsi_attach_aio_context,
+
+ .strong_runtime_opts = iscsi_strong_runtime_opts,
};
#if LIBISCSI_API_VERSION >= (20160603)
@@ -2519,6 +2535,8 @@
.bdrv_detach_aio_context = iscsi_detach_aio_context,
.bdrv_attach_aio_context = iscsi_attach_aio_context,
+
+ .strong_runtime_opts = iscsi_strong_runtime_opts,
};
#endif
diff --git a/block/mirror.c b/block/mirror.c
index b67b012..726d3c2 100644
--- a/block/mirror.c
+++ b/block/mirror.c
@@ -1431,14 +1431,13 @@
NULL, 0);
}
-static void bdrv_mirror_top_refresh_filename(BlockDriverState *bs, QDict *opts)
+static void bdrv_mirror_top_refresh_filename(BlockDriverState *bs)
{
if (bs->backing == NULL) {
/* we can be here after failed bdrv_attach_child in
* bdrv_set_backing_hd */
return;
}
- bdrv_refresh_filename(bs->backing->bs);
pstrcpy(bs->exact_filename, sizeof(bs->exact_filename),
bs->backing->bs->filename);
}
diff --git a/block/nbd-client.c b/block/nbd-client.c
index f0ad54c..bfbaf7e 100644
--- a/block/nbd-client.c
+++ b/block/nbd-client.c
@@ -76,8 +76,18 @@
Error *local_err = NULL;
while (!s->quit) {
+ /*
+ * The NBD client can only really be considered idle when it has
+ * yielded from qio_channel_readv_all_eof(), waiting for data. This is
+ * the point where the additional scheduled coroutine entry happens
+ * after nbd_client_attach_aio_context().
+ *
+ * Therefore we keep an additional in_flight reference all the time and
+ * only drop it temporarily here.
+ */
assert(s->reply.handle == 0);
- ret = nbd_receive_reply(s->ioc, &s->reply, &local_err);
+ ret = nbd_receive_reply(s->bs, s->ioc, &s->reply, &local_err);
+
if (local_err) {
trace_nbd_read_reply_entry_fail(ret, error_get_pretty(local_err));
error_free(local_err);
@@ -116,6 +126,8 @@
s->quit = true;
nbd_recv_coroutines_wake_all(s);
+ bdrv_dec_in_flight(s->bs);
+
s->connection_co = NULL;
aio_wait_kick();
}
@@ -965,12 +977,30 @@
qio_channel_detach_aio_context(QIO_CHANNEL(client->ioc));
}
+static void nbd_client_attach_aio_context_bh(void *opaque)
+{
+ BlockDriverState *bs = opaque;
+ NBDClientSession *client = nbd_get_client_session(bs);
+
+ /* The node is still drained, so we know the coroutine has yielded in
+ * nbd_read_eof(), the only place where bs->in_flight can reach 0, or it is
+ * entered for the first time. Both places are safe for entering the
+ * coroutine.*/
+ qemu_aio_coroutine_enter(bs->aio_context, client->connection_co);
+ bdrv_dec_in_flight(bs);
+}
+
void nbd_client_attach_aio_context(BlockDriverState *bs,
AioContext *new_context)
{
NBDClientSession *client = nbd_get_client_session(bs);
qio_channel_attach_aio_context(QIO_CHANNEL(client->ioc), new_context);
- aio_co_schedule(new_context, client->connection_co);
+
+ bdrv_inc_in_flight(bs);
+
+ /* Need to wait here for the BH to run because the BH must run while the
+ * node is still drained. */
+ aio_wait_bh_oneshot(new_context, nbd_client_attach_aio_context_bh, bs);
}
void nbd_client_close(BlockDriverState *bs)
@@ -1076,6 +1106,7 @@
* kick the reply mechanism. */
qio_channel_set_blocking(QIO_CHANNEL(sioc), false, NULL);
client->connection_co = qemu_coroutine_create(nbd_connection_entry, client);
+ bdrv_inc_in_flight(bs);
nbd_client_attach_aio_context(bs, bdrv_get_aio_context(bs));
logout("Established connection with NBD server\n");
@@ -1108,6 +1139,7 @@
{
NBDClientSession *client = nbd_get_client_session(bs);
+ client->bs = bs;
qemu_co_mutex_init(&client->send_mutex);
qemu_co_queue_init(&client->free_sema);
diff --git a/block/nbd-client.h b/block/nbd-client.h
index d990207..09e0301 100644
--- a/block/nbd-client.h
+++ b/block/nbd-client.h
@@ -35,6 +35,7 @@
NBDClientRequest requests[MAX_NBD_REQUESTS];
NBDReply reply;
+ BlockDriverState *bs;
bool quit;
} NBDClientSession;
diff --git a/block/nbd.c b/block/nbd.c
index 9db5ede..2e72df5 100644
--- a/block/nbd.c
+++ b/block/nbd.c
@@ -477,12 +477,9 @@
nbd_client_attach_aio_context(bs, new_context);
}
-static void nbd_refresh_filename(BlockDriverState *bs, QDict *options)
+static void nbd_refresh_filename(BlockDriverState *bs)
{
BDRVNBDState *s = bs->opaque;
- QDict *opts = qdict_new();
- QObject *saddr_qdict;
- Visitor *ov;
const char *host = NULL, *port = NULL, *path = NULL;
if (s->saddr->type == SOCKET_ADDRESS_TYPE_INET) {
@@ -495,8 +492,6 @@
path = s->saddr->u.q_unix.path;
} /* else can't represent as pseudo-filename */
- qdict_put_str(opts, "driver", "nbd");
-
if (path && s->export) {
snprintf(bs->exact_filename, sizeof(bs->exact_filename),
"nbd+unix:///%s?socket=%s", s->export, path);
@@ -510,24 +505,29 @@
snprintf(bs->exact_filename, sizeof(bs->exact_filename),
"nbd://%s:%s", host, port);
}
-
- ov = qobject_output_visitor_new(&saddr_qdict);
- visit_type_SocketAddress(ov, NULL, &s->saddr, &error_abort);
- visit_complete(ov, &saddr_qdict);
- visit_free(ov);
- qdict_put_obj(opts, "server", saddr_qdict);
-
- if (s->export) {
- qdict_put_str(opts, "export", s->export);
- }
- if (s->tlscredsid) {
- qdict_put_str(opts, "tls-creds", s->tlscredsid);
- }
-
- qdict_flatten(opts);
- bs->full_open_options = opts;
}
+static char *nbd_dirname(BlockDriverState *bs, Error **errp)
+{
+ /* The generic bdrv_dirname() implementation is able to work out some
+ * directory name for NBD nodes, but that would be wrong. So far there is no
+ * specification for how "export paths" would work, so NBD does not have
+ * directory names. */
+ error_setg(errp, "Cannot generate a base directory for NBD nodes");
+ return NULL;
+}
+
+static const char *const nbd_strong_runtime_opts[] = {
+ "path",
+ "host",
+ "port",
+ "export",
+ "tls-creds",
+ "server.",
+
+ NULL
+};
+
static BlockDriver bdrv_nbd = {
.format_name = "nbd",
.protocol_name = "nbd",
@@ -546,6 +546,8 @@
.bdrv_attach_aio_context = nbd_attach_aio_context,
.bdrv_refresh_filename = nbd_refresh_filename,
.bdrv_co_block_status = nbd_client_co_block_status,
+ .bdrv_dirname = nbd_dirname,
+ .strong_runtime_opts = nbd_strong_runtime_opts,
};
static BlockDriver bdrv_nbd_tcp = {
@@ -566,6 +568,8 @@
.bdrv_attach_aio_context = nbd_attach_aio_context,
.bdrv_refresh_filename = nbd_refresh_filename,
.bdrv_co_block_status = nbd_client_co_block_status,
+ .bdrv_dirname = nbd_dirname,
+ .strong_runtime_opts = nbd_strong_runtime_opts,
};
static BlockDriver bdrv_nbd_unix = {
@@ -586,6 +590,8 @@
.bdrv_attach_aio_context = nbd_attach_aio_context,
.bdrv_refresh_filename = nbd_refresh_filename,
.bdrv_co_block_status = nbd_client_co_block_status,
+ .bdrv_dirname = nbd_dirname,
+ .strong_runtime_opts = nbd_strong_runtime_opts,
};
static void bdrv_nbd_init(void)
diff --git a/block/nfs.c b/block/nfs.c
index eab1a2c..5319036 100644
--- a/block/nfs.c
+++ b/block/nfs.c
@@ -799,14 +799,9 @@
return 0;
}
-static void nfs_refresh_filename(BlockDriverState *bs, QDict *options)
+static void nfs_refresh_filename(BlockDriverState *bs)
{
NFSClient *client = bs->opaque;
- QDict *opts = qdict_new();
- QObject *server_qdict;
- Visitor *ov;
-
- qdict_put_str(opts, "driver", "nfs");
if (client->uid && !client->gid) {
snprintf(bs->exact_filename, sizeof(bs->exact_filename),
@@ -824,35 +819,20 @@
snprintf(bs->exact_filename, sizeof(bs->exact_filename),
"nfs://%s%s", client->server->host, client->path);
}
+}
- ov = qobject_output_visitor_new(&server_qdict);
- visit_type_NFSServer(ov, NULL, &client->server, &error_abort);
- visit_complete(ov, &server_qdict);
- qdict_put_obj(opts, "server", server_qdict);
- qdict_put_str(opts, "path", client->path);
+static char *nfs_dirname(BlockDriverState *bs, Error **errp)
+{
+ NFSClient *client = bs->opaque;
- if (client->uid) {
- qdict_put_int(opts, "user", client->uid);
- }
- if (client->gid) {
- qdict_put_int(opts, "group", client->gid);
- }
- if (client->tcp_syncnt) {
- qdict_put_int(opts, "tcp-syn-cnt", client->tcp_syncnt);
- }
- if (client->readahead) {
- qdict_put_int(opts, "readahead-size", client->readahead);
- }
- if (client->pagecache) {
- qdict_put_int(opts, "page-cache-size", client->pagecache);
- }
- if (client->debug) {
- qdict_put_int(opts, "debug", client->debug);
+ if (client->uid || client->gid) {
+ bdrv_refresh_filename(bs);
+ error_setg(errp, "Cannot generate a base directory for NFS node '%s'",
+ bs->filename);
+ return NULL;
}
- visit_free(ov);
- qdict_flatten(opts);
- bs->full_open_options = opts;
+ return g_strdup_printf("nfs://%s%s/", client->server->host, client->path);
}
#ifdef LIBNFS_FEATURE_PAGECACHE
@@ -864,6 +844,15 @@
}
#endif
+static const char *nfs_strong_runtime_opts[] = {
+ "path",
+ "user",
+ "group",
+ "server.",
+
+ NULL
+};
+
static BlockDriver bdrv_nfs = {
.format_name = "nfs",
.protocol_name = "nfs",
@@ -889,6 +878,9 @@
.bdrv_detach_aio_context = nfs_detach_aio_context,
.bdrv_attach_aio_context = nfs_attach_aio_context,
.bdrv_refresh_filename = nfs_refresh_filename,
+ .bdrv_dirname = nfs_dirname,
+
+ .strong_runtime_opts = nfs_strong_runtime_opts,
#ifdef LIBNFS_FEATURE_PAGECACHE
.bdrv_co_invalidate_cache = nfs_co_invalidate_cache,
diff --git a/block/null.c b/block/null.c
index d442d3e..a322929 100644
--- a/block/null.c
+++ b/block/null.c
@@ -239,19 +239,33 @@
return ret;
}
-static void null_refresh_filename(BlockDriverState *bs, QDict *opts)
+static void null_refresh_filename(BlockDriverState *bs)
{
- qdict_del(opts, "filename");
+ const QDictEntry *e;
- if (!qdict_size(opts)) {
- snprintf(bs->exact_filename, sizeof(bs->exact_filename), "%s://",
- bs->drv->format_name);
+ for (e = qdict_first(bs->full_open_options); e;
+ e = qdict_next(bs->full_open_options, e))
+ {
+ /* These options can be ignored */
+ if (strcmp(qdict_entry_key(e), "filename") &&
+ strcmp(qdict_entry_key(e), "driver") &&
+ strcmp(qdict_entry_key(e), NULL_OPT_LATENCY))
+ {
+ return;
+ }
}
- qdict_put_str(opts, "driver", bs->drv->format_name);
- bs->full_open_options = qobject_ref(opts);
+ snprintf(bs->exact_filename, sizeof(bs->exact_filename), "%s://",
+ bs->drv->format_name);
}
+static const char *const null_strong_runtime_opts[] = {
+ BLOCK_OPT_SIZE,
+ NULL_OPT_ZEROES,
+
+ NULL
+};
+
static BlockDriver bdrv_null_co = {
.format_name = "null-co",
.protocol_name = "null-co",
@@ -269,6 +283,7 @@
.bdrv_co_block_status = null_co_block_status,
.bdrv_refresh_filename = null_refresh_filename,
+ .strong_runtime_opts = null_strong_runtime_opts,
};
static BlockDriver bdrv_null_aio = {
@@ -288,6 +303,7 @@
.bdrv_co_block_status = null_co_block_status,
.bdrv_refresh_filename = null_refresh_filename,
+ .strong_runtime_opts = null_strong_runtime_opts,
};
static void bdrv_null_init(void)
diff --git a/block/nvme.c b/block/nvme.c
index b5952c9..0684bbd 100644
--- a/block/nvme.c
+++ b/block/nvme.c
@@ -82,7 +82,7 @@
uint8_t reserved1[0xec0];
uint8_t cmd_set_specfic[0x100];
uint32_t doorbells[];
-} QEMU_PACKED NVMeRegs;
+} NVMeRegs;
QEMU_BUILD_BUG_ON(offsetof(NVMeRegs, doorbells) != 0x1000);
@@ -111,6 +111,9 @@
/* Total size of mapped qiov, accessed under dma_map_lock */
int dma_map_count;
+
+ /* PCI address (required for nvme_refresh_filename()) */
+ char *device;
} BDRVNVMeState;
#define NVME_BLOCK_OPT_DEVICE "device"
@@ -557,6 +560,7 @@
qemu_co_mutex_init(&s->dma_map_lock);
qemu_co_queue_init(&s->dma_flush_queue);
+ s->device = g_strdup(device);
s->nsid = namespace;
s->aio_context = bdrv_get_aio_context(bs);
ret = event_notifier_init(&s->irq_notifier, 0);
@@ -729,6 +733,8 @@
event_notifier_cleanup(&s->irq_notifier);
qemu_vfio_pci_unmap_bar(s->vfio, 0, (void *)s->regs, 0, NVME_BAR_SIZE);
qemu_vfio_close(s->vfio);
+
+ g_free(s->device);
}
static int nvme_file_open(BlockDriverState *bs, QDict *options, int flags,
@@ -1053,17 +1059,12 @@
return 0;
}
-static void nvme_refresh_filename(BlockDriverState *bs, QDict *opts)
+static void nvme_refresh_filename(BlockDriverState *bs)
{
- qdict_del(opts, "filename");
+ BDRVNVMeState *s = bs->opaque;
- if (!qdict_size(opts)) {
- snprintf(bs->exact_filename, sizeof(bs->exact_filename), "%s://",
- bs->drv->format_name);
- }
-
- qdict_put_str(opts, "driver", bs->drv->format_name);
- bs->full_open_options = qobject_ref(opts);
+ snprintf(bs->exact_filename, sizeof(bs->exact_filename), "nvme://%s/%i",
+ s->device, s->nsid);
}
static void nvme_refresh_limits(BlockDriverState *bs, Error **errp)
@@ -1136,6 +1137,13 @@
qemu_vfio_dma_unmap(s->vfio, host);
}
+static const char *const nvme_strong_runtime_opts[] = {
+ NVME_BLOCK_OPT_DEVICE,
+ NVME_BLOCK_OPT_NAMESPACE,
+
+ NULL
+};
+
static BlockDriver bdrv_nvme = {
.format_name = "nvme",
.protocol_name = "nvme",
@@ -1153,6 +1161,7 @@
.bdrv_refresh_filename = nvme_refresh_filename,
.bdrv_refresh_limits = nvme_refresh_limits,
+ .strong_runtime_opts = nvme_strong_runtime_opts,
.bdrv_detach_aio_context = nvme_detach_aio_context,
.bdrv_attach_aio_context = nvme_attach_aio_context,
diff --git a/block/parallels.c b/block/parallels.c
index cc94458..15bc97b 100644
--- a/block/parallels.c
+++ b/block/parallels.c
@@ -220,23 +220,20 @@
if (bs->backing) {
int64_t nb_cow_sectors = to_allocate * s->tracks;
int64_t nb_cow_bytes = nb_cow_sectors << BDRV_SECTOR_BITS;
- QEMUIOVector qiov;
- struct iovec iov = {
- .iov_len = nb_cow_bytes,
- .iov_base = qemu_blockalign(bs, nb_cow_bytes)
- };
- qemu_iovec_init_external(&qiov, &iov, 1);
+ QEMUIOVector qiov =
+ QEMU_IOVEC_INIT_BUF(qiov, qemu_blockalign(bs, nb_cow_bytes),
+ nb_cow_bytes);
ret = bdrv_co_preadv(bs->backing, idx * s->tracks * BDRV_SECTOR_SIZE,
nb_cow_bytes, &qiov, 0);
if (ret < 0) {
- qemu_vfree(iov.iov_base);
+ qemu_vfree(qemu_iovec_buf(&qiov));
return ret;
}
ret = bdrv_co_pwritev(bs->file, s->data_end * BDRV_SECTOR_SIZE,
nb_cow_bytes, &qiov, 0);
- qemu_vfree(iov.iov_base);
+ qemu_vfree(qemu_iovec_buf(&qiov));
if (ret < 0) {
return ret;
}
diff --git a/block/qapi.c b/block/qapi.c
index 00291f9..6002a76 100644
--- a/block/qapi.c
+++ b/block/qapi.c
@@ -51,6 +51,8 @@
return NULL;
}
+ bdrv_refresh_filename(bs);
+
info = g_malloc0(sizeof(*info));
info->file = g_strdup(bs->filename);
info->ro = bs->read_only;
@@ -264,6 +266,8 @@
goto out;
}
+ bdrv_refresh_filename(bs);
+
info = g_new0(ImageInfo, 1);
info->filename = g_strdup(bs->filename);
info->format = g_strdup(bdrv_get_format_name(bs));
@@ -292,18 +296,10 @@
backing_filename = bs->backing_file;
if (backing_filename[0] != '\0') {
- char *backing_filename2 = g_malloc0(PATH_MAX);
+ char *backing_filename2;
info->backing_filename = g_strdup(backing_filename);
info->has_backing_filename = true;
- bdrv_get_full_backing_filename(bs, backing_filename2, PATH_MAX, &err);
- if (err) {
- /* Can't reconstruct the full backing filename, so we must omit
- * this field and apply a Best Effort to this query. */
- g_free(backing_filename2);
- backing_filename2 = NULL;
- error_free(err);
- err = NULL;
- }
+ backing_filename2 = bdrv_get_full_backing_filename(bs, NULL);
/* Always report the full_backing_filename if present, even if it's the
* same as backing_filename. That they are same is useful info. */
diff --git a/block/qcow.c b/block/qcow.c
index 0a235bf..10d2cf1 100644
--- a/block/qcow.c
+++ b/block/qcow.c
@@ -31,6 +31,7 @@
#include "qemu/module.h"
#include "qemu/option.h"
#include "qemu/bswap.h"
+#include "qemu/cutils.h"
#include <zlib.h>
#include "qapi/qmp/qdict.h"
#include "qapi/qmp/qstring.h"
@@ -295,11 +296,13 @@
goto fail;
}
ret = bdrv_pread(bs->file, header.backing_file_offset,
- bs->backing_file, len);
+ bs->auto_backing_file, len);
if (ret < 0) {
goto fail;
}
- bs->backing_file[len] = '\0';
+ bs->auto_backing_file[len] = '\0';
+ pstrcpy(bs->backing_file, sizeof(bs->backing_file),
+ bs->auto_backing_file);
}
/* Disable migration when qcow images are used */
@@ -628,7 +631,6 @@
int offset_in_cluster;
int ret = 0, n;
uint64_t cluster_offset;
- struct iovec hd_iov;
QEMUIOVector hd_qiov;
uint8_t *buf;
void *orig_buf;
@@ -661,9 +663,7 @@
if (!cluster_offset) {
if (bs->backing) {
/* read from the base image */
- hd_iov.iov_base = (void *)buf;
- hd_iov.iov_len = n;
- qemu_iovec_init_external(&hd_qiov, &hd_iov, 1);
+ qemu_iovec_init_buf(&hd_qiov, buf, n);
qemu_co_mutex_unlock(&s->lock);
/* qcow2 emits this on bs->file instead of bs->backing */
BLKDBG_EVENT(bs->file, BLKDBG_READ_BACKING_AIO);
@@ -688,9 +688,7 @@
ret = -EIO;
break;
}
- hd_iov.iov_base = (void *)buf;
- hd_iov.iov_len = n;
- qemu_iovec_init_external(&hd_qiov, &hd_iov, 1);
+ qemu_iovec_init_buf(&hd_qiov, buf, n);
qemu_co_mutex_unlock(&s->lock);
BLKDBG_EVENT(bs->file, BLKDBG_READ_AIO);
ret = bdrv_co_preadv(bs->file, cluster_offset + offset_in_cluster,
@@ -733,7 +731,6 @@
int offset_in_cluster;
uint64_t cluster_offset;
int ret = 0, n;
- struct iovec hd_iov;
QEMUIOVector hd_qiov;
uint8_t *buf;
void *orig_buf;
@@ -779,9 +776,7 @@
}
}
- hd_iov.iov_base = (void *)buf;
- hd_iov.iov_len = n;
- qemu_iovec_init_external(&hd_qiov, &hd_iov, 1);
+ qemu_iovec_init_buf(&hd_qiov, buf, n);
qemu_co_mutex_unlock(&s->lock);
BLKDBG_EVENT(bs->file, BLKDBG_WRITE_AIO);
ret = bdrv_co_pwritev(bs->file, cluster_offset + offset_in_cluster,
@@ -1062,7 +1057,6 @@
{
BDRVQcowState *s = bs->opaque;
QEMUIOVector hd_qiov;
- struct iovec iov;
z_stream strm;
int ret, out_len;
uint8_t *buf, *out_buf;
@@ -1128,11 +1122,7 @@
}
cluster_offset &= s->cluster_offset_mask;
- iov = (struct iovec) {
- .iov_base = out_buf,
- .iov_len = out_len,
- };
- qemu_iovec_init_external(&hd_qiov, &iov, 1);
+ qemu_iovec_init_buf(&hd_qiov, out_buf, out_len);
BLKDBG_EVENT(bs->file, BLKDBG_WRITE_COMPRESSED);
ret = bdrv_co_pwritev(bs->file, cluster_offset, out_len, &hd_qiov, 0);
if (ret < 0) {
@@ -1183,6 +1173,12 @@
}
};
+static const char *const qcow_strong_runtime_opts[] = {
+ "encrypt." BLOCK_CRYPTO_OPT_QCOW_KEY_SECRET,
+
+ NULL
+};
+
static BlockDriver bdrv_qcow = {
.format_name = "qcow",
.instance_size = sizeof(BDRVQcowState),
@@ -1206,6 +1202,7 @@
.bdrv_get_info = qcow_get_info,
.create_opts = &qcow_create_opts,
+ .strong_runtime_opts = qcow_strong_runtime_opts,
};
static void bdrv_qcow_init(void)
diff --git a/block/qcow2-cluster.c b/block/qcow2-cluster.c
index 30eca26..179aa2c 100644
--- a/block/qcow2-cluster.c
+++ b/block/qcow2-cluster.c
@@ -285,6 +285,9 @@
goto fail;
}
+ /* The offset must fit in the offset field of the L1 table entry */
+ assert((l2_offset & L1E_OFFSET_MASK) == l2_offset);
+
/* If we're allocating the table at offset 0 then something is wrong */
if (l2_offset == 0) {
qcow2_signal_corruption(bs, true, -1, -1, "Preventing invalid "
diff --git a/block/qcow2-snapshot.c b/block/qcow2-snapshot.c
index bb6a5b7..20e8472 100644
--- a/block/qcow2-snapshot.c
+++ b/block/qcow2-snapshot.c
@@ -358,11 +358,6 @@
/* Generate an ID */
find_new_snapshot_id(bs, sn_info->id_str, sizeof(sn_info->id_str));
- /* Check that the ID is unique */
- if (find_snapshot_by_id_and_name(bs, sn_info->id_str, NULL) >= 0) {
- return -EEXIST;
- }
-
/* Populate sn with passed data */
sn->id_str = g_strdup(sn_info->id_str);
sn->name = g_strdup(sn_info->name);
diff --git a/block/qcow2.c b/block/qcow2.c
index 65a54c9..7fb2730 100644
--- a/block/qcow2.c
+++ b/block/qcow2.c
@@ -1474,13 +1474,15 @@
goto fail;
}
ret = bdrv_pread(bs->file, header.backing_file_offset,
- bs->backing_file, len);
+ bs->auto_backing_file, len);
if (ret < 0) {
error_setg_errno(errp, -ret, "Could not read backing file name");
goto fail;
}
- bs->backing_file[len] = '\0';
- s->image_backing_file = g_strdup(bs->backing_file);
+ bs->auto_backing_file[len] = '\0';
+ pstrcpy(bs->backing_file, sizeof(bs->backing_file),
+ bs->auto_backing_file);
+ s->image_backing_file = g_strdup(bs->auto_backing_file);
}
/* Internal snapshots */
@@ -2518,6 +2520,8 @@
return -EINVAL;
}
+ pstrcpy(bs->auto_backing_file, sizeof(bs->auto_backing_file),
+ backing_file ?: "");
pstrcpy(bs->backing_file, sizeof(bs->backing_file), backing_file ?: "");
pstrcpy(bs->backing_format, sizeof(bs->backing_format), backing_fmt ?: "");
@@ -3894,7 +3898,6 @@
{
BDRVQcow2State *s = bs->opaque;
QEMUIOVector hd_qiov;
- struct iovec iov;
int ret;
size_t out_len;
uint8_t *buf, *out_buf;
@@ -3960,11 +3963,7 @@
goto fail;
}
- iov = (struct iovec) {
- .iov_base = out_buf,
- .iov_len = out_len,
- };
- qemu_iovec_init_external(&hd_qiov, &iov, 1);
+ qemu_iovec_init_buf(&hd_qiov, out_buf, out_len);
BLKDBG_EVENT(bs->file, BLKDBG_WRITE_COMPRESSED);
ret = bdrv_co_pwritev(bs->file, cluster_offset, out_len, &hd_qiov, 0);
@@ -3990,7 +3989,6 @@
int ret = 0, csize, nb_csectors;
uint64_t coffset;
uint8_t *buf, *out_buf;
- struct iovec iov;
QEMUIOVector local_qiov;
int offset_in_cluster = offset_into_cluster(s, offset);
@@ -4002,9 +4000,7 @@
if (!buf) {
return -ENOMEM;
}
- iov.iov_base = buf;
- iov.iov_len = csize;
- qemu_iovec_init_external(&local_qiov, &iov, 1);
+ qemu_iovec_init_buf(&local_qiov, buf, csize);
out_buf = qemu_blockalign(bs, s->cluster_size);
@@ -4232,6 +4228,60 @@
return ret;
}
+static ssize_t qcow2_measure_crypto_hdr_init_func(QCryptoBlock *block,
+ size_t headerlen, void *opaque, Error **errp)
+{
+ size_t *headerlenp = opaque;
+
+ /* Stash away the payload size */
+ *headerlenp = headerlen;
+ return 0;
+}
+
+static ssize_t qcow2_measure_crypto_hdr_write_func(QCryptoBlock *block,
+ size_t offset, const uint8_t *buf, size_t buflen,
+ void *opaque, Error **errp)
+{
+ /* Discard the bytes, we're not actually writing to an image */
+ return buflen;
+}
+
+/* Determine the number of bytes for the LUKS payload */
+static bool qcow2_measure_luks_headerlen(QemuOpts *opts, size_t *len,
+ Error **errp)
+{
+ QDict *opts_qdict;
+ QDict *cryptoopts_qdict;
+ QCryptoBlockCreateOptions *cryptoopts;
+ QCryptoBlock *crypto;
+
+ /* Extract "encrypt." options into a qdict */
+ opts_qdict = qemu_opts_to_qdict(opts, NULL);
+ qdict_extract_subqdict(opts_qdict, &cryptoopts_qdict, "encrypt.");
+ qobject_unref(opts_qdict);
+
+ /* Build QCryptoBlockCreateOptions object from qdict */
+ qdict_put_str(cryptoopts_qdict, "format", "luks");
+ cryptoopts = block_crypto_create_opts_init(cryptoopts_qdict, errp);
+ qobject_unref(cryptoopts_qdict);
+ if (!cryptoopts) {
+ return false;
+ }
+
+ /* Fake LUKS creation in order to determine the payload size */
+ crypto = qcrypto_block_create(cryptoopts, "encrypt.",
+ qcow2_measure_crypto_hdr_init_func,
+ qcow2_measure_crypto_hdr_write_func,
+ len, errp);
+ qapi_free_QCryptoBlockCreateOptions(cryptoopts);
+ if (!crypto) {
+ return false;
+ }
+
+ qcrypto_block_free(crypto);
+ return true;
+}
+
static BlockMeasureInfo *qcow2_measure(QemuOpts *opts, BlockDriverState *in_bs,
Error **errp)
{
@@ -4241,11 +4291,13 @@
uint64_t virtual_size; /* disk size as seen by guest */
uint64_t refcount_bits;
uint64_t l2_tables;
+ uint64_t luks_payload_size = 0;
size_t cluster_size;
int version;
char *optstr;
PreallocMode prealloc;
bool has_backing_file;
+ bool has_luks;
/* Parse image creation options */
cluster_size = qcow2_opt_get_cluster_size_del(opts, &local_err);
@@ -4275,6 +4327,20 @@
has_backing_file = !!optstr;
g_free(optstr);
+ optstr = qemu_opt_get_del(opts, BLOCK_OPT_ENCRYPT_FORMAT);
+ has_luks = optstr && strcmp(optstr, "luks") == 0;
+ g_free(optstr);
+
+ if (has_luks) {
+ size_t headerlen;
+
+ if (!qcow2_measure_luks_headerlen(opts, &headerlen, &local_err)) {
+ goto err;
+ }
+
+ luks_payload_size = ROUND_UP(headerlen, cluster_size);
+ }
+
virtual_size = qemu_opt_get_size_del(opts, BLOCK_OPT_SIZE, 0);
virtual_size = ROUND_UP(virtual_size, cluster_size);
@@ -4345,7 +4411,7 @@
info = g_new(BlockMeasureInfo, 1);
info->fully_allocated =
qcow2_calc_prealloc_size(virtual_size, cluster_size,
- ctz32(refcount_bits));
+ ctz32(refcount_bits)) + luks_payload_size;
/* Remove data clusters that are not required. This overestimates the
* required size because metadata needed for the fully allocated file is
@@ -4932,6 +4998,12 @@
}
};
+static const char *const qcow2_strong_runtime_opts[] = {
+ "encrypt." BLOCK_CRYPTO_OPT_QCOW_KEY_SECRET,
+
+ NULL
+};
+
BlockDriver bdrv_qcow2 = {
.format_name = "qcow2",
.instance_size = sizeof(BDRVQcow2State),
@@ -4980,6 +5052,7 @@
.bdrv_inactivate = qcow2_inactivate,
.create_opts = &qcow2_create_opts,
+ .strong_runtime_opts = qcow2_strong_runtime_opts,
.bdrv_co_check = qcow2_co_check,
.bdrv_amend_options = qcow2_amend_options,
diff --git a/block/qed-table.c b/block/qed-table.c
index 7df5680..c497bd4 100644
--- a/block/qed-table.c
+++ b/block/qed-table.c
@@ -21,16 +21,11 @@
/* Called with table_lock held. */
static int qed_read_table(BDRVQEDState *s, uint64_t offset, QEDTable *table)
{
- QEMUIOVector qiov;
+ QEMUIOVector qiov = QEMU_IOVEC_INIT_BUF(
+ qiov, table->offsets, s->header.cluster_size * s->header.table_size);
int noffsets;
int i, ret;
- struct iovec iov = {
- .iov_base = table->offsets,
- .iov_len = s->header.cluster_size * s->header.table_size,
- };
- qemu_iovec_init_external(&qiov, &iov, 1);
-
trace_qed_read_table(s, offset, table);
qemu_co_mutex_unlock(&s->table_lock);
@@ -71,7 +66,6 @@
unsigned int sector_mask = BDRV_SECTOR_SIZE / sizeof(uint64_t) - 1;
unsigned int start, end, i;
QEDTable *new_table;
- struct iovec iov;
QEMUIOVector qiov;
size_t len_bytes;
int ret;
@@ -85,11 +79,7 @@
len_bytes = (end - start) * sizeof(uint64_t);
new_table = qemu_blockalign(s->bs, len_bytes);
- iov = (struct iovec) {
- .iov_base = new_table->offsets,
- .iov_len = len_bytes,
- };
- qemu_iovec_init_external(&qiov, &iov, 1);
+ qemu_iovec_init_buf(&qiov, new_table->offsets, len_bytes);
/* Byteswap table */
for (i = start; i < end; i++) {
diff --git a/block/qed.c b/block/qed.c
index 1280870..89af05d 100644
--- a/block/qed.c
+++ b/block/qed.c
@@ -113,18 +113,13 @@
int nsectors = DIV_ROUND_UP(sizeof(QEDHeader), BDRV_SECTOR_SIZE);
size_t len = nsectors * BDRV_SECTOR_SIZE;
uint8_t *buf;
- struct iovec iov;
QEMUIOVector qiov;
int ret;
assert(s->allocating_acb || s->allocating_write_reqs_plugged);
buf = qemu_blockalign(s->bs, len);
- iov = (struct iovec) {
- .iov_base = buf,
- .iov_len = len,
- };
- qemu_iovec_init_external(&qiov, &iov, 1);
+ qemu_iovec_init_buf(&qiov, buf, len);
ret = bdrv_co_preadv(s->bs->file, 0, qiov.size, &qiov, 0);
if (ret < 0) {
@@ -454,11 +449,14 @@
}
ret = qed_read_string(bs->file, s->header.backing_filename_offset,
- s->header.backing_filename_size, bs->backing_file,
- sizeof(bs->backing_file));
+ s->header.backing_filename_size,
+ bs->auto_backing_file,
+ sizeof(bs->auto_backing_file));
if (ret < 0) {
return ret;
}
+ pstrcpy(bs->backing_file, sizeof(bs->backing_file),
+ bs->auto_backing_file);
if (s->header.features & QED_F_BACKING_FORMAT_NO_PROBE) {
pstrcpy(bs->backing_format, sizeof(bs->backing_format), "raw");
@@ -913,7 +911,6 @@
{
QEMUIOVector qiov;
QEMUIOVector *backing_qiov = NULL;
- struct iovec iov;
int ret;
/* Skip copy entirely if there is no work to do */
@@ -921,11 +918,7 @@
return 0;
}
- iov = (struct iovec) {
- .iov_base = qemu_blockalign(s->bs, len),
- .iov_len = len,
- };
- qemu_iovec_init_external(&qiov, &iov, 1);
+ qemu_iovec_init_buf(&qiov, qemu_blockalign(s->bs, len), len);
ret = qed_read_backing_file(s, pos, &qiov, &backing_qiov);
@@ -946,7 +939,7 @@
}
ret = 0;
out:
- qemu_vfree(iov.iov_base);
+ qemu_vfree(qemu_iovec_buf(&qiov));
return ret;
}
@@ -1447,8 +1440,12 @@
BdrvRequestFlags flags)
{
BDRVQEDState *s = bs->opaque;
- QEMUIOVector qiov;
- struct iovec iov;
+
+ /*
+ * Zero writes start without an I/O buffer. If a buffer becomes necessary
+ * then it will be allocated during request processing.
+ */
+ QEMUIOVector qiov = QEMU_IOVEC_INIT_BUF(qiov, NULL, bytes);
/* Fall back if the request is not aligned */
if (qed_offset_into_cluster(s, offset) ||
@@ -1456,13 +1453,6 @@
return -ENOTSUP;
}
- /* Zero writes start without an I/O buffer. If a buffer becomes necessary
- * then it will be allocated during request processing.
- */
- iov.iov_base = NULL;
- iov.iov_len = bytes;
-
- qemu_iovec_init_external(&qiov, &iov, 1);
return qed_co_request(bs, offset >> BDRV_SECTOR_BITS, &qiov,
bytes >> BDRV_SECTOR_BITS,
QED_AIOCB_WRITE | QED_AIOCB_ZERO);
diff --git a/block/quorum.c b/block/quorum.c
index 16b3c80..352f729 100644
--- a/block/quorum.c
+++ b/block/quorum.c
@@ -1065,36 +1065,64 @@
bdrv_drained_end(bs);
}
-static void quorum_refresh_filename(BlockDriverState *bs, QDict *options)
+static void quorum_gather_child_options(BlockDriverState *bs, QDict *target,
+ bool backing_overridden)
{
BDRVQuorumState *s = bs->opaque;
- QDict *opts;
- QList *children;
+ QList *children_list;
int i;
- for (i = 0; i < s->num_children; i++) {
- bdrv_refresh_filename(s->children[i]->bs);
- if (!s->children[i]->bs->full_open_options) {
- return;
- }
- }
+ /*
+ * The generic implementation for gathering child options in
+ * bdrv_refresh_filename() would use the names of the children
+ * as specified for bdrv_open_child() or bdrv_attach_child(),
+ * which is "children.%u" with %u being a value
+ * (s->next_child_index) that is incremented each time a new child
+ * is added (and never decremented). Since children can be
+ * deleted at runtime, there may be gaps in that enumeration.
+ * When creating a new quorum BDS and specifying the children for
+ * it through runtime options, the enumeration used there may not
+ * have any gaps, though.
+ *
+ * Therefore, we have to create a new gap-less enumeration here
+ * (which we can achieve by simply putting all of the children's
+ * full_open_options into a QList).
+ *
+ * XXX: Note that there are issues with the current child option
+ * structure quorum uses (such as the fact that children do
+ * not really have unique permanent names). Therefore, this
+ * is going to have to change in the future and ideally we
+ * want quorum to be covered by the generic implementation.
+ */
- children = qlist_new();
+ children_list = qlist_new();
+ qdict_put(target, "children", children_list);
+
for (i = 0; i < s->num_children; i++) {
- qlist_append(children,
+ qlist_append(children_list,
qobject_ref(s->children[i]->bs->full_open_options));
}
-
- opts = qdict_new();
- qdict_put_str(opts, "driver", "quorum");
- qdict_put_int(opts, QUORUM_OPT_VOTE_THRESHOLD, s->threshold);
- qdict_put_bool(opts, QUORUM_OPT_BLKVERIFY, s->is_blkverify);
- qdict_put_bool(opts, QUORUM_OPT_REWRITE, s->rewrite_corrupted);
- qdict_put(opts, "children", children);
-
- bs->full_open_options = opts;
}
+static char *quorum_dirname(BlockDriverState *bs, Error **errp)
+{
+ /* In general, there are multiple BDSs with different dirnames below this
+ * one; so there is no unique dirname we could return (unless all are equal
+ * by chance, or there is only one). Therefore, to be consistent, just
+ * always return NULL. */
+ error_setg(errp, "Cannot generate a base directory for quorum nodes");
+ return NULL;
+}
+
+static const char *const quorum_strong_runtime_opts[] = {
+ QUORUM_OPT_VOTE_THRESHOLD,
+ QUORUM_OPT_BLKVERIFY,
+ QUORUM_OPT_REWRITE,
+ QUORUM_OPT_READ_PATTERN,
+
+ NULL
+};
+
static BlockDriver bdrv_quorum = {
.format_name = "quorum",
@@ -1102,7 +1130,8 @@
.bdrv_open = quorum_open,
.bdrv_close = quorum_close,
- .bdrv_refresh_filename = quorum_refresh_filename,
+ .bdrv_gather_child_options = quorum_gather_child_options,
+ .bdrv_dirname = quorum_dirname,
.bdrv_co_flush_to_disk = quorum_co_flush,
@@ -1118,6 +1147,8 @@
.is_filter = true,
.bdrv_recurse_is_first_non_filter = quorum_recurse_is_first_non_filter,
+
+ .strong_runtime_opts = quorum_strong_runtime_opts,
};
static void bdrv_quorum_init(void)
diff --git a/block/raw-format.c b/block/raw-format.c
index 6f6dc99..e3e5ba2 100644
--- a/block/raw-format.c
+++ b/block/raw-format.c
@@ -436,6 +436,7 @@
bs->file->bs->supported_zero_flags);
if (bs->probed && !bdrv_is_read_only(bs)) {
+ bdrv_refresh_filename(bs->file->bs);
fprintf(stderr,
"WARNING: Image format was not specified for '%s' and probing "
"guessed raw.\n"
@@ -531,6 +532,13 @@
read_flags, write_flags);
}
+static const char *const raw_strong_runtime_opts[] = {
+ "offset",
+ "size",
+
+ NULL
+};
+
BlockDriver bdrv_raw = {
.format_name = "raw",
.instance_size = sizeof(BDRVRawState),
@@ -560,7 +568,8 @@
.bdrv_lock_medium = &raw_lock_medium,
.bdrv_co_ioctl = &raw_co_ioctl,
.create_opts = &raw_create_opts,
- .bdrv_has_zero_init = &raw_has_zero_init
+ .bdrv_has_zero_init = &raw_has_zero_init,
+ .strong_runtime_opts = raw_strong_runtime_opts,
};
static void bdrv_raw_init(void)
diff --git a/block/rbd.c b/block/rbd.c
index 8a1a9f4..0c549c9 100644
--- a/block/rbd.c
+++ b/block/rbd.c
@@ -1228,6 +1228,18 @@
}
};
+static const char *const qemu_rbd_strong_runtime_opts[] = {
+ "pool",
+ "image",
+ "conf",
+ "snapshot",
+ "user",
+ "server.",
+ "password-secret",
+
+ NULL
+};
+
static BlockDriver bdrv_rbd = {
.format_name = "rbd",
.instance_size = sizeof(BDRVRBDState),
@@ -1265,6 +1277,8 @@
#ifdef LIBRBD_SUPPORTS_INVALIDATE
.bdrv_co_invalidate_cache = qemu_rbd_co_invalidate_cache,
#endif
+
+ .strong_runtime_opts = qemu_rbd_strong_runtime_opts,
};
static void bdrv_rbd_init(void)
diff --git a/block/replication.c b/block/replication.c
index e70dd95..4c80b54 100644
--- a/block/replication.c
+++ b/block/replication.c
@@ -616,8 +616,6 @@
if (ret == 0) {
s->stage = BLOCK_REPLICATION_DONE;
- /* refresh top bs's filename */
- bdrv_refresh_filename(bs);
s->active_disk = NULL;
s->secondary_disk = NULL;
s->hidden_disk = NULL;
@@ -678,6 +676,13 @@
aio_context_release(aio_context);
}
+static const char *const replication_strong_runtime_opts[] = {
+ REPLICATION_MODE,
+ REPLICATION_TOP_ID,
+
+ NULL
+};
+
BlockDriver bdrv_replication = {
.format_name = "replication",
.instance_size = sizeof(BDRVReplicationState),
@@ -694,6 +699,7 @@
.bdrv_recurse_is_first_non_filter = replication_recurse_is_first_non_filter,
.has_variable_length = true,
+ .strong_runtime_opts = replication_strong_runtime_opts,
};
static void bdrv_replication_init(void)
diff --git a/block/sheepdog.c b/block/sheepdog.c
index b916ba0..cbdfe9a 100644
--- a/block/sheepdog.c
+++ b/block/sheepdog.c
@@ -3203,6 +3203,15 @@
}
};
+static const char *const sd_strong_runtime_opts[] = {
+ "vdi",
+ "snap-id",
+ "tag",
+ "server.",
+
+ NULL
+};
+
static BlockDriver bdrv_sheepdog = {
.format_name = "sheepdog",
.protocol_name = "sheepdog",
@@ -3238,6 +3247,7 @@
.bdrv_attach_aio_context = sd_attach_aio_context,
.create_opts = &sd_create_opts,
+ .strong_runtime_opts = sd_strong_runtime_opts,
};
static BlockDriver bdrv_sheepdog_tcp = {
@@ -3275,6 +3285,7 @@
.bdrv_attach_aio_context = sd_attach_aio_context,
.create_opts = &sd_create_opts,
+ .strong_runtime_opts = sd_strong_runtime_opts,
};
static BlockDriver bdrv_sheepdog_unix = {
@@ -3312,6 +3323,7 @@
.bdrv_attach_aio_context = sd_attach_aio_context,
.create_opts = &sd_create_opts,
+ .strong_runtime_opts = sd_strong_runtime_opts,
};
static void bdrv_sheepdog_init(void)
diff --git a/block/snapshot.c b/block/snapshot.c
index 3218a54..f2f48f9 100644
--- a/block/snapshot.c
+++ b/block/snapshot.c
@@ -63,7 +63,7 @@
}
for (i = 0; i < nb_sns; i++) {
sn = &sn_tab[i];
- if (!strcmp(sn->id_str, name) || !strcmp(sn->name, name)) {
+ if (!strcmp(sn->name, name)) {
*sn_info = *sn;
ret = 0;
break;
@@ -301,26 +301,6 @@
return ret;
}
-int bdrv_snapshot_delete_by_id_or_name(BlockDriverState *bs,
- const char *id_or_name,
- Error **errp)
-{
- int ret;
- Error *local_err = NULL;
-
- ret = bdrv_snapshot_delete(bs, id_or_name, NULL, &local_err);
- if (ret == -ENOENT || ret == -EINVAL) {
- error_free(local_err);
- local_err = NULL;
- ret = bdrv_snapshot_delete(bs, NULL, id_or_name, &local_err);
- }
-
- if (ret < 0) {
- error_propagate(errp, local_err);
- }
- return ret;
-}
-
int bdrv_snapshot_list(BlockDriverState *bs,
QEMUSnapshotInfo **psn_info)
{
@@ -448,7 +428,8 @@
aio_context_acquire(ctx);
if (bdrv_can_snapshot(bs) &&
bdrv_snapshot_find(bs, snapshot, name) >= 0) {
- ret = bdrv_snapshot_delete_by_id_or_name(bs, name, err);
+ ret = bdrv_snapshot_delete(bs, snapshot->id_str,
+ snapshot->name, err);
}
aio_context_release(ctx);
if (ret < 0) {
diff --git a/block/ssh.c b/block/ssh.c
index bbc513e..190ef95 100644
--- a/block/ssh.c
+++ b/block/ssh.c
@@ -1254,6 +1254,17 @@
return ssh_grow_file(s, offset, errp);
}
+static const char *const ssh_strong_runtime_opts[] = {
+ "host",
+ "port",
+ "path",
+ "user",
+ "host_key_check",
+ "server.",
+
+ NULL
+};
+
static BlockDriver bdrv_ssh = {
.format_name = "ssh",
.protocol_name = "ssh",
@@ -1270,6 +1281,7 @@
.bdrv_co_truncate = ssh_co_truncate,
.bdrv_co_flush_to_disk = ssh_co_flush,
.create_opts = &ssh_create_opts,
+ .strong_runtime_opts = ssh_strong_runtime_opts,
};
static void bdrv_ssh_init(void)
diff --git a/block/stream.c b/block/stream.c
index 7a49ac0..e14579f 100644
--- a/block/stream.c
+++ b/block/stream.c
@@ -41,14 +41,9 @@
int64_t offset, uint64_t bytes,
void *buf)
{
- struct iovec iov = {
- .iov_base = buf,
- .iov_len = bytes,
- };
- QEMUIOVector qiov;
+ QEMUIOVector qiov = QEMU_IOVEC_INIT_BUF(qiov, buf, bytes);
assert(bytes < SIZE_MAX);
- qemu_iovec_init_external(&qiov, &iov, 1);
/* Copy-on-read the unallocated clusters */
return blk_co_preadv(blk, offset, qiov.size, &qiov, BDRV_REQ_COPY_ON_READ);
diff --git a/block/throttle.c b/block/throttle.c
index 636c976..f64dcc2 100644
--- a/block/throttle.c
+++ b/block/throttle.c
@@ -227,6 +227,12 @@
atomic_dec(&tgm->io_limits_disabled);
}
+static const char *const throttle_strong_runtime_opts[] = {
+ QEMU_OPT_THROTTLE_GROUP_NAME,
+
+ NULL
+};
+
static BlockDriver bdrv_throttle = {
.format_name = "throttle",
.instance_size = sizeof(ThrottleGroupMember),
@@ -259,6 +265,7 @@
.bdrv_co_drain_end = throttle_co_drain_end,
.is_filter = true,
+ .strong_runtime_opts = throttle_strong_runtime_opts,
};
static void bdrv_throttle_init(void)
diff --git a/block/vhdx-log.c b/block/vhdx-log.c
index ecd6426..3149ff0 100644
--- a/block/vhdx-log.c
+++ b/block/vhdx-log.c
@@ -803,6 +803,7 @@
if (logs.valid) {
if (bs->read_only) {
+ bdrv_refresh_filename(bs);
ret = -EPERM;
error_setg(errp,
"VHDX image file '%s' opened read-only, but "
diff --git a/block/vmdk.c b/block/vmdk.c
index 096e8eb..d8c0c50 100644
--- a/block/vmdk.c
+++ b/block/vmdk.c
@@ -27,6 +27,7 @@
#include "qapi/error.h"
#include "block/block_int.h"
#include "sysemu/block-backend.h"
+#include "qapi/qmp/qdict.h"
#include "qapi/qmp/qerror.h"
#include "qemu/error-report.h"
#include "qemu/module.h"
@@ -386,12 +387,14 @@
ret = -EINVAL;
goto out;
}
- if ((end_name - p_name) > sizeof(bs->backing_file) - 1) {
+ if ((end_name - p_name) > sizeof(bs->auto_backing_file) - 1) {
ret = -EINVAL;
goto out;
}
- pstrcpy(bs->backing_file, end_name - p_name + 1, p_name);
+ pstrcpy(bs->auto_backing_file, end_name - p_name + 1, p_name);
+ pstrcpy(bs->backing_file, sizeof(bs->backing_file),
+ bs->auto_backing_file);
}
out:
@@ -479,6 +482,7 @@
extent->l1_table,
l1_size);
if (ret < 0) {
+ bdrv_refresh_filename(extent->file->bs);
error_setg_errno(errp, -ret,
"Could not read l1 table from extent '%s'",
extent->file->bs->filename);
@@ -499,6 +503,7 @@
extent->l1_backup_table,
l1_size);
if (ret < 0) {
+ bdrv_refresh_filename(extent->file->bs);
error_setg_errno(errp, -ret,
"Could not read l1 backup table from extent '%s'",
extent->file->bs->filename);
@@ -530,6 +535,7 @@
ret = bdrv_pread(file, sizeof(magic), &header, sizeof(header));
if (ret < 0) {
+ bdrv_refresh_filename(file->bs);
error_setg_errno(errp, -ret,
"Could not read header from file '%s'",
file->bs->filename);
@@ -607,6 +613,7 @@
ret = bdrv_pread(file, sizeof(magic), &header, sizeof(header));
if (ret < 0) {
+ bdrv_refresh_filename(file->bs);
error_setg_errno(errp, -ret,
"Could not read header from file '%s'",
file->bs->filename);
@@ -861,13 +868,13 @@
if (!path_is_absolute(fname) && !path_has_protocol(fname) &&
!desc_file_path[0])
{
+ bdrv_refresh_filename(bs->file->bs);
error_setg(errp, "Cannot use relative extent paths with VMDK "
"descriptor file '%s'", bs->file->bs->filename);
return -EINVAL;
}
- extent_path = g_malloc0(PATH_MAX);
- path_combine(extent_path, PATH_MAX, desc_file_path, fname);
+ extent_path = path_combine(desc_file_path, fname);
ret = snprintf(extent_opt_prefix, 32, "extents.%d", s->num_extents);
assert(ret < 32);
@@ -1371,7 +1378,6 @@
VmdkGrainMarker *data = NULL;
uLongf buf_len;
QEMUIOVector local_qiov;
- struct iovec iov;
int64_t write_offset;
int64_t write_end_sector;
@@ -1399,11 +1405,7 @@
data->size = cpu_to_le32(buf_len);
n_bytes = buf_len + sizeof(VmdkGrainMarker);
- iov = (struct iovec) {
- .iov_base = data,
- .iov_len = n_bytes,
- };
- qemu_iovec_init_external(&local_qiov, &iov, 1);
+ qemu_iovec_init_buf(&local_qiov, data, n_bytes);
BLKDBG_EVENT(extent->file, BLKDBG_WRITE_COMPRESSED);
} else {
@@ -2072,16 +2074,16 @@
if (backing_file) {
BlockBackend *backing;
- char *full_backing = g_new0(char, PATH_MAX);
- bdrv_get_full_backing_filename_from_filename(blk_bs(blk)->filename, backing_file,
- full_backing, PATH_MAX,
- &local_err);
+ char *full_backing =
+ bdrv_get_full_backing_filename_from_filename(blk_bs(blk)->filename,
+ backing_file,
+ &local_err);
if (local_err) {
- g_free(full_backing);
error_propagate(errp, local_err);
ret = -ENOENT;
goto exit;
}
+ assert(full_backing);
backing = blk_new_open(full_backing, NULL, NULL,
BDRV_O_NO_BACKING, errp);
@@ -2260,7 +2262,7 @@
compat6 = qemu_opt_get_bool_del(opts, BLOCK_OPT_COMPAT6, false);
if (strcmp(hw_version, "undefined") == 0) {
g_free(hw_version);
- hw_version = g_strdup("4");
+ hw_version = NULL;
}
fmt = qemu_opt_get_del(opts, BLOCK_OPT_SUBFMT);
zeroed_grain = qemu_opt_get_bool_del(opts, BLOCK_OPT_ZEROED_GRAIN, false);
@@ -2470,6 +2472,7 @@
{
ImageInfo *info = g_new0(ImageInfo, 1);
+ bdrv_refresh_filename(extent->file->bs);
*info = (ImageInfo){
.filename = g_strdup(extent->file->bs->filename),
.format = g_strdup(extent->type),
@@ -2601,6 +2604,23 @@
return 0;
}
+static void vmdk_gather_child_options(BlockDriverState *bs, QDict *target,
+ bool backing_overridden)
+{
+ /* No children but file and backing can be explicitly specified (TODO) */
+ qdict_put(target, "file",
+ qobject_ref(bs->file->bs->full_open_options));
+
+ if (backing_overridden) {
+ if (bs->backing) {
+ qdict_put(target, "backing",
+ qobject_ref(bs->backing->bs->full_open_options));
+ } else {
+ qdict_put_null(target, "backing");
+ }
+ }
+}
+
static QemuOptsList vmdk_create_opts = {
.name = "vmdk-create-opts",
.head = QTAILQ_HEAD_INITIALIZER(vmdk_create_opts.head),
@@ -2672,6 +2692,7 @@
.bdrv_get_specific_info = vmdk_get_specific_info,
.bdrv_refresh_limits = vmdk_refresh_limits,
.bdrv_get_info = vmdk_get_info,
+ .bdrv_gather_child_options = vmdk_gather_child_options,
.supports_backing = true,
.create_opts = &vmdk_create_opts,
diff --git a/block/vpc.c b/block/vpc.c
index 52ab717..a902a4c 100644
--- a/block/vpc.c
+++ b/block/vpc.c
@@ -1218,6 +1218,12 @@
}
};
+static const char *const vpc_strong_runtime_opts[] = {
+ VPC_OPT_SIZE_CALC,
+
+ NULL
+};
+
static BlockDriver bdrv_vpc = {
.format_name = "vpc",
.instance_size = sizeof(BDRVVPCState),
@@ -1238,6 +1244,7 @@
.create_opts = &vpc_create_opts,
.bdrv_has_zero_init = vpc_has_zero_init,
+ .strong_runtime_opts = vpc_strong_runtime_opts,
};
static void bdrv_vpc_init(void)
diff --git a/block/vvfat.c b/block/vvfat.c
index b7b61ea..5f66787 100644
--- a/block/vvfat.c
+++ b/block/vvfat.c
@@ -3253,6 +3253,16 @@
}
}
+static const char *const vvfat_strong_runtime_opts[] = {
+ "dir",
+ "fat-type",
+ "floppy",
+ "label",
+ "rw",
+
+ NULL
+};
+
static BlockDriver bdrv_vvfat = {
.format_name = "vvfat",
.protocol_name = "fat",
@@ -3267,6 +3277,8 @@
.bdrv_co_preadv = vvfat_co_preadv,
.bdrv_co_pwritev = vvfat_co_pwritev,
.bdrv_co_block_status = vvfat_co_block_status,
+
+ .strong_runtime_opts = vvfat_strong_runtime_opts,
};
static void bdrv_vvfat_init(void)
diff --git a/block/vxhs.c b/block/vxhs.c
index 0cb0a00..2e18229 100644
--- a/block/vxhs.c
+++ b/block/vxhs.c
@@ -556,6 +556,16 @@
return vdisk_size;
}
+static const char *const vxhs_strong_runtime_opts[] = {
+ VXHS_OPT_VDISK_ID,
+ "tls-creds",
+ VXHS_OPT_HOST,
+ VXHS_OPT_PORT,
+ VXHS_OPT_SERVER".",
+
+ NULL
+};
+
static BlockDriver bdrv_vxhs = {
.format_name = "vxhs",
.protocol_name = "vxhs",
@@ -567,6 +577,7 @@
.bdrv_getlength = vxhs_getlength,
.bdrv_aio_preadv = vxhs_aio_preadv,
.bdrv_aio_pwritev = vxhs_aio_pwritev,
+ .strong_runtime_opts = vxhs_strong_runtime_opts,
};
static void bdrv_vxhs_init(void)
diff --git a/blockdev.c b/blockdev.c
index 8714ad2..7e6bf99 100644
--- a/blockdev.c
+++ b/blockdev.c
@@ -1627,6 +1627,7 @@
error_setg_errno(errp, -size, "bdrv_getlength failed");
goto out;
}
+ bdrv_refresh_filename(state->old_bs);
bdrv_img_create(new_image_file, format,
state->old_bs->filename,
state->old_bs->drv->format_name,
@@ -3230,6 +3231,7 @@
goto out;
}
assert(bdrv_get_aio_context(base_bs) == aio_context);
+ bdrv_refresh_filename(base_bs);
base_name = base_bs->filename;
}
@@ -3349,6 +3351,10 @@
goto out;
}
} else if (has_top && top) {
+ /* This strcmp() is just a shortcut, there is no need to
+ * refresh @bs's filename. If it mismatches,
+ * bdrv_find_backing_image() will do the refresh and may still
+ * return @bs. */
if (strcmp(bs->filename, top) != 0) {
top_bs = bdrv_find_backing_image(bs, top);
}
@@ -3509,6 +3515,7 @@
if (backup->mode != NEW_IMAGE_MODE_EXISTING) {
assert(backup->format);
if (source) {
+ bdrv_refresh_filename(source);
bdrv_img_create(backup->target, backup->format, source->filename,
source->drv->format_name, NULL,
size, flags, false, &local_err);
@@ -3889,6 +3896,7 @@
break;
case NEW_IMAGE_MODE_ABSOLUTE_PATHS:
/* create new image with backing file */
+ bdrv_refresh_filename(source);
bdrv_img_create(arg->target, format,
source->filename,
source->drv->format_name,
diff --git a/chardev/spice.c b/chardev/spice.c
index 173c257..22c30ae 100644
--- a/chardev/spice.c
+++ b/chardev/spice.c
@@ -2,30 +2,12 @@
#include "trace.h"
#include "ui/qemu-spice.h"
#include "chardev/char.h"
+#include "chardev/spice.h"
#include "qapi/error.h"
#include "qemu/error-report.h"
#include "qemu/option.h"
-#include <spice.h>
#include <spice/protocol.h>
-
-typedef struct SpiceChardev {
- Chardev parent;
-
- SpiceCharDeviceInstance sin;
- bool active;
- bool blocked;
- const uint8_t *datapos;
- int datalen;
- QLIST_ENTRY(SpiceChardev) next;
-} SpiceChardev;
-
-#define TYPE_CHARDEV_SPICE "chardev-spice"
-#define TYPE_CHARDEV_SPICEVMC "chardev-spicevmc"
-#define TYPE_CHARDEV_SPICEPORT "chardev-spiceport"
-
-#define SPICE_CHARDEV(obj) OBJECT_CHECK(SpiceChardev, (obj), TYPE_CHARDEV_SPICE)
-
typedef struct SpiceCharSource {
GSource source;
SpiceChardev *scd;
@@ -148,15 +130,25 @@
static gboolean spice_char_source_prepare(GSource *source, gint *timeout)
{
SpiceCharSource *src = (SpiceCharSource *)source;
+ Chardev *chr = CHARDEV(src->scd);
*timeout = -1;
+ if (!chr->be_open) {
+ return true;
+ }
+
return !src->scd->blocked;
}
static gboolean spice_char_source_check(GSource *source)
{
SpiceCharSource *src = (SpiceCharSource *)source;
+ Chardev *chr = CHARDEV(src->scd);
+
+ if (!chr->be_open) {
+ return true;
+ }
return !src->scd->blocked;
}
@@ -164,9 +156,12 @@
static gboolean spice_char_source_dispatch(GSource *source,
GSourceFunc callback, gpointer user_data)
{
+ SpiceCharSource *src = (SpiceCharSource *)source;
+ Chardev *chr = CHARDEV(src->scd);
GIOFunc func = (GIOFunc)callback;
+ GIOCondition cond = chr->be_open ? G_IO_OUT : G_IO_HUP;
- return func(NULL, G_IO_OUT, user_data);
+ return func(NULL, cond, user_data);
}
static GSourceFuncs SpiceCharSourceFuncs = {
@@ -195,6 +190,12 @@
int read_bytes;
assert(s->datalen == 0);
+
+ if (!chr->be_open) {
+ trace_spice_chr_discard_write(len);
+ return len;
+ }
+
s->datapos = buf;
s->datalen = len;
spice_server_char_device_wakeup(&s->sin);
@@ -287,13 +288,19 @@
}
*be_opened = false;
+#if SPICE_SERVER_VERSION < 0x000e02
+ /* Spice < 0.14.2 doesn't explicitly open smartcard chardev */
+ if (strcmp(type, "smartcard") == 0) {
+ *be_opened = true;
+ }
+#endif
chr_open(chr, type);
}
-static void qemu_chr_open_spice_port(Chardev *chr,
- ChardevBackend *backend,
- bool *be_opened,
- Error **errp)
+void qemu_chr_open_spice_port(Chardev *chr,
+ ChardevBackend *backend,
+ bool *be_opened,
+ Error **errp)
{
ChardevSpicePort *spiceport = backend->u.spiceport.data;
const char *name = spiceport->fqdn;
@@ -309,6 +316,11 @@
*be_opened = false;
s = SPICE_CHARDEV(chr);
s->sin.portname = g_strdup(name);
+
+ if (using_spice) {
+ /* spice server already created */
+ vmc_register_interface(s);
+ }
}
void qemu_spice_register_ports(void)
diff --git a/chardev/trace-events b/chardev/trace-events
index d0e5f3b..b8a7596 100644
--- a/chardev/trace-events
+++ b/chardev/trace-events
@@ -10,6 +10,7 @@
wct_speed(int speed) "%d"
# chardev/spice.c
+spice_chr_discard_write(int len) "spice chr write discarded %d"
spice_vmc_write(ssize_t out, int len) "spice wrote %zd of requested %d"
spice_vmc_read(int bytes, int len) "spice read %d of requested %d"
spice_vmc_register_interface(void *scd) "spice vmc registered interface %p"
diff --git a/configure b/configure
index 343dd00..5921d08 100755
--- a/configure
+++ b/configure
@@ -368,10 +368,10 @@
xfs=""
tcg="yes"
membarrier=""
-vhost_net="no"
-vhost_crypto="no"
-vhost_scsi="no"
-vhost_vsock="no"
+vhost_net=""
+vhost_crypto=""
+vhost_scsi=""
+vhost_vsock=""
vhost_user=""
kvm="no"
hax="no"
@@ -463,6 +463,7 @@
nettle=""
gcrypt=""
gcrypt_hmac="no"
+auth_pam=""
vte=""
virglrenderer=""
tpm="yes"
@@ -782,6 +783,7 @@
MINGW32*)
mingw32="yes"
hax="yes"
+ vhost_user="no"
audio_possible_drivers="dsound sdl"
if check_include dsound.h; then
audio_drv_list="dsound"
@@ -878,15 +880,11 @@
LIBS="-lposix_error_mapper -lnetwork $LIBS"
;;
Linux)
- audio_drv_list="try-pa try-alsa try-sdl oss"
+ audio_drv_list="try-pa oss"
audio_possible_drivers="oss alsa sdl pa"
linux="yes"
linux_user="yes"
kvm="yes"
- vhost_net="yes"
- vhost_crypto="yes"
- vhost_scsi="yes"
- vhost_vsock="yes"
QEMU_INCLUDES="-I\$(SRC_PATH)/linux-headers -I$PWD/linux-headers $QEMU_INCLUDES"
supported_os="yes"
libudev="yes"
@@ -1262,11 +1260,7 @@
;;
--disable-vhost-crypto) vhost_crypto="no"
;;
- --enable-vhost-crypto)
- vhost_crypto="yes"
- if test "$mingw32" = "yes"; then
- error_exit "vhost-crypto isn't available on win32"
- fi
+ --enable-vhost-crypto) vhost_crypto="yes"
;;
--disable-vhost-scsi) vhost_scsi="no"
;;
@@ -1381,6 +1375,10 @@
;;
--enable-gcrypt) gcrypt="yes"
;;
+ --disable-auth-pam) auth_pam="no"
+ ;;
+ --enable-auth-pam) auth_pam="yes"
+ ;;
--enable-rdma) rdma="yes"
;;
--disable-rdma) rdma="no"
@@ -1471,11 +1469,11 @@
;;
--disable-vhost-user) vhost_user="no"
;;
- --enable-vhost-user)
- vhost_user="yes"
- if test "$mingw32" = "yes"; then
- error_exit "vhost-user isn't available on win32"
- fi
+ --enable-vhost-user) vhost_user="yes"
+ ;;
+ --disable-vhost-kernel) vhost_kernel="no"
+ ;;
+ --enable-vhost-kernel) vhost_kernel="yes"
;;
--disable-capstone) capstone="no"
;;
@@ -1507,14 +1505,6 @@
esac
done
-if test "$vhost_user" = ""; then
- if test "$mingw32" = "yes"; then
- vhost_user="no"
- else
- vhost_user="yes"
- fi
-fi
-
case "$cpu" in
ppc)
CPU_CFLAGS="-m32"
@@ -1707,6 +1697,7 @@
gnutls GNUTLS cryptography support
nettle nettle cryptography support
gcrypt libgcrypt cryptography support
+ auth-pam PAM access control
sdl SDL UI
sdl_image SDL Image support for icons
gtk gtk UI
@@ -1737,8 +1728,12 @@
linux-aio Linux AIO support
cap-ng libcap-ng support
attr attr and xattr support
- vhost-net vhost-net acceleration support
- vhost-crypto vhost-crypto acceleration support
+ vhost-net vhost-net kernel acceleration support
+ vhost-vsock virtio sockets device support
+ vhost-scsi vhost-scsi kernel target support
+ vhost-crypto vhost-user-crypto backend support
+ vhost-kernel vhost kernel backend support
+ vhost-user vhost-user backend support
spice spice
rbd rados block device (rbd)
libiscsi iscsi support
@@ -1764,7 +1759,6 @@
jemalloc jemalloc support
avx2 AVX2 optimization support
replication replication support
- vhost-vsock virtio sockets device support
opengl opengl support
virglrenderer virgl rendering support
xfsctl xfsctl support
@@ -1781,7 +1775,6 @@
parallels parallels image format support
sheepdog sheepdog block driver support
crypto-afalg Linux AF_ALG crypto backend driver
- vhost-user vhost-user support
capstone capstone disassembler support
debug-mutex mutex debugging support
libpmem libpmem support
@@ -2171,6 +2164,45 @@
l2tpv3=no
fi
+#########################################
+# vhost interdependencies and host support
+
+# vhost backends
+test "$vhost_user" = "" && vhost_user=yes
+if test "$vhost_user" = "yes" && test "$mingw32" = "yes"; then
+ error_exit "vhost-user isn't available on win32"
+fi
+test "$vhost_kernel" = "" && vhost_kernel=$linux
+if test "$vhost_kernel" = "yes" && test "$linux" != "yes"; then
+ error_exit "vhost-kernel is only available on Linux"
+fi
+
+# vhost-kernel devices
+test "$vhost_scsi" = "" && vhost_scsi=$vhost_kernel
+if test "$vhost_scsi" = "yes" && test "$vhost_kernel" != "yes"; then
+ error_exit "--enable-vhost-scsi requires --enable-vhost-kernel"
+fi
+test "$vhost_vsock" = "" && vhost_vsock=$vhost_kernel
+if test "$vhost_vsock" = "yes" && test "$vhost_kernel" != "yes"; then
+ error_exit "--enable-vhost-vsock requires --enable-vhost-kernel"
+fi
+
+# vhost-user backends
+test "$vhost_net_user" = "" && vhost_net_user=$vhost_user
+if test "$vhost_net_user" = "yes" && test "$vhost_user" = "no"; then
+ error_exit "--enable-vhost-net-user requires --enable-vhost-user"
+fi
+test "$vhost_crypto" = "" && vhost_crypto=$vhost_user
+if test "$vhost_crypto" = "yes" && test "$vhost_user" = "no"; then
+ error_exit "--enable-vhost-crypto requires --enable-vhost-user"
+fi
+
+# OR the vhost-kernel and vhost-user values for simplicity
+if test "$vhost_net" = ""; then
+ test "$vhost_net_user" = "yes" && vhost_net=yes
+ test "$vhost_kernel" = "yes" && vhost_net=yes
+fi
+
##########################################
# MinGW / Mingw-w64 localtime_r/gmtime_r check
@@ -2865,6 +2897,33 @@
##########################################
+# PAM probe
+
+if test "$auth_pam" != "no"; then
+ cat > $TMPC <<EOF
+#include <security/pam_appl.h>
+#include <stdio.h>
+int main(void) {
+ const char *service_name = "qemu";
+ const char *user = "frank";
+ const struct pam_conv *pam_conv = NULL;
+ pam_handle_t *pamh = NULL;
+ pam_start(service_name, user, pam_conv, &pamh);
+ return 0;
+}
+EOF
+ if compile_prog "" "-lpam" ; then
+ auth_pam=yes
+ else
+ if test "$auth_pam" = "yes"; then
+ feature_not_found "PAM" "Install PAM development package"
+ else
+ auth_pam=no
+ fi
+ fi
+fi
+
+##########################################
# getifaddrs (for tests/test-io-channel-socket )
have_ifaddrs_h=yes
@@ -3172,20 +3231,6 @@
fi
fi
-##########################################
-# fnmatch() probe, used for ACL routines
-fnmatch="no"
-cat > $TMPC << EOF
-#include <fnmatch.h>
-int main(void)
-{
- fnmatch("foo", "foo", 0);
- return 0;
-}
-EOF
-if compile_prog "" "" ; then
- fnmatch="yes"
-fi
##########################################
# xfsctl() probe, used for file-posix.c
@@ -3503,6 +3548,14 @@
fi
done
+if $pkg_config --atleast-version=$glib_req_ver gio-2.0; then
+ gio=yes
+ gio_cflags=$($pkg_config --cflags gio-2.0)
+ gio_libs=$($pkg_config --libs gio-2.0)
+else
+ gio=no
+fi
+
# Sanity check that the current size_t matches the
# size that glib thinks it should be. This catches
# problems on multi-arch where people try to build
@@ -4536,13 +4589,24 @@
syncfs=yes
fi
+# Check we have a new enough version of sphinx-build
+has_sphinx_build() {
+ # This is a bit awkward but works: create a trivial document and
+ # try to run it with our configuration file (which enforces a
+ # version requirement). This will fail if either
+ # sphinx-build doesn't exist at all or if it is too old.
+ mkdir -p "$TMPDIR1/sphinx"
+ touch "$TMPDIR1/sphinx/index.rst"
+ sphinx-build -c "$source_path/docs" -b html "$TMPDIR1/sphinx" "$TMPDIR1/sphinx/out" >/dev/null 2>&1
+}
+
# Check if tools are available to build documentation.
if test "$docs" != "no" ; then
- if has makeinfo && has pod2man; then
+ if has makeinfo && has pod2man && has_sphinx_build; then
docs=yes
else
if test "$docs" = "yes" ; then
- feature_not_found "docs" "Install texinfo and Perl/perl-podlators"
+ feature_not_found "docs" "Install texinfo, Perl/perl-podlators and python-sphinx"
fi
docs=no
fi
@@ -6083,6 +6147,7 @@
echo "libgcrypt $gcrypt"
echo "nettle $nettle $(echo_version $nettle $nettle_version)"
echo "libtasn1 $tasn1"
+echo "PAM $auth_pam"
echo "curses support $curses"
echo "virgl support $virglrenderer $(echo_version $virglrenderer $virgl_version)"
echo "curl support $curl"
@@ -6374,9 +6439,6 @@
echo "XKBCOMMON_CFLAGS=$xkbcommon_cflags" >> $config_host_mak
echo "XKBCOMMON_LIBS=$xkbcommon_libs" >> $config_host_mak
fi
-if test "$fnmatch" = "yes" ; then
- echo "CONFIG_FNMATCH=y" >> $config_host_mak
-fi
if test "$xfs" = "yes" ; then
echo "CONFIG_XFS=y" >> $config_host_mak
fi
@@ -6520,6 +6582,11 @@
echo "CONFIG_GTK_GL=y" >> $config_host_mak
fi
fi
+if test "$gio" = "yes" ; then
+ echo "CONFIG_GIO=y" >> $config_host_mak
+ echo "GIO_CFLAGS=$gio_cflags" >> $config_host_mak
+ echo "GIO_LIBS=$gio_libs" >> $config_host_mak
+fi
echo "CONFIG_TLS_PRIORITY=\"$tls_priority\"" >> $config_host_mak
if test "$gnutls" = "yes" ; then
echo "CONFIG_GNUTLS=y" >> $config_host_mak
@@ -6537,6 +6604,9 @@
if test "$tasn1" = "yes" ; then
echo "CONFIG_TASN1=y" >> $config_host_mak
fi
+if test "$auth_pam" = "yes" ; then
+ echo "CONFIG_AUTH_PAM=y" >> $config_host_mak
+fi
if test "$have_ifaddrs_h" = "yes" ; then
echo "HAVE_IFADDRS_H=y" >> $config_host_mak
fi
@@ -6589,8 +6659,11 @@
if test "$vhost_scsi" = "yes" ; then
echo "CONFIG_VHOST_SCSI=y" >> $config_host_mak
fi
-if test "$vhost_net" = "yes" && test "$vhost_user" = "yes"; then
- echo "CONFIG_VHOST_NET_USED=y" >> $config_host_mak
+if test "$vhost_net" = "yes" ; then
+ echo "CONFIG_VHOST_NET=y" >> $config_host_mak
+fi
+if test "$vhost_net_user" = "yes" ; then
+ echo "CONFIG_VHOST_NET_USER=y" >> $config_host_mak
fi
if test "$vhost_crypto" = "yes" ; then
echo "CONFIG_VHOST_CRYPTO=y" >> $config_host_mak
@@ -6598,6 +6671,9 @@
if test "$vhost_vsock" = "yes" ; then
echo "CONFIG_VHOST_VSOCK=y" >> $config_host_mak
fi
+if test "$vhost_kernel" = "yes" ; then
+ echo "CONFIG_VHOST_KERNEL=y" >> $config_host_mak
+fi
if test "$vhost_user" = "yes" ; then
echo "CONFIG_VHOST_USER=y" >> $config_host_mak
fi
@@ -7368,12 +7444,6 @@
fi
if supported_kvm_target $target; then
echo "CONFIG_KVM=y" >> $config_target_mak
- if test "$vhost_net" = "yes" ; then
- echo "CONFIG_VHOST_NET=y" >> $config_target_mak
- if test "$vhost_user" = "yes" ; then
- echo "CONFIG_VHOST_USER_NET_TEST_$target_name=y" >> $config_host_mak
- fi
- fi
fi
if supported_hax_target $target; then
echo "CONFIG_HAX=y" >> $config_target_mak
diff --git a/cpus.c b/cpus.c
index 154daf5..e83f72b 100644
--- a/cpus.c
+++ b/cpus.c
@@ -1333,6 +1333,7 @@
qemu_wait_io_event(cpu);
} while (!cpu->unplug);
+ qemu_mutex_unlock_iothread();
rcu_unregister_thread();
return NULL;
#endif
diff --git a/crypto/tlssession.c b/crypto/tlssession.c
index 0dedd4a..c3a920d 100644
--- a/crypto/tlssession.c
+++ b/crypto/tlssession.c
@@ -24,7 +24,7 @@
#include "crypto/tlscredspsk.h"
#include "crypto/tlscredsx509.h"
#include "qapi/error.h"
-#include "qemu/acl.h"
+#include "authz/base.h"
#include "trace.h"
#ifdef CONFIG_GNUTLS
@@ -37,7 +37,7 @@
QCryptoTLSCreds *creds;
gnutls_session_t handle;
char *hostname;
- char *aclname;
+ char *authzid;
bool handshakeComplete;
QCryptoTLSSessionWriteFunc writeFunc;
QCryptoTLSSessionReadFunc readFunc;
@@ -56,7 +56,7 @@
gnutls_deinit(session->handle);
g_free(session->hostname);
g_free(session->peername);
- g_free(session->aclname);
+ g_free(session->authzid);
object_unref(OBJECT(session->creds));
g_free(session);
}
@@ -95,7 +95,7 @@
QCryptoTLSSession *
qcrypto_tls_session_new(QCryptoTLSCreds *creds,
const char *hostname,
- const char *aclname,
+ const char *authzid,
QCryptoTLSCredsEndpoint endpoint,
Error **errp)
{
@@ -105,13 +105,13 @@
session = g_new0(QCryptoTLSSession, 1);
trace_qcrypto_tls_session_new(
session, creds, hostname ? hostname : "<none>",
- aclname ? aclname : "<none>", endpoint);
+ authzid ? authzid : "<none>", endpoint);
if (hostname) {
session->hostname = g_strdup(hostname);
}
- if (aclname) {
- session->aclname = g_strdup(aclname);
+ if (authzid) {
+ session->authzid = g_strdup(authzid);
}
session->creds = creds;
object_ref(OBJECT(creds));
@@ -262,6 +262,7 @@
unsigned int nCerts, i;
time_t now;
gnutls_x509_crt_t cert = NULL;
+ Error *err = NULL;
now = time(NULL);
if (now == ((time_t)-1)) {
@@ -349,19 +350,17 @@
gnutls_strerror(ret));
goto error;
}
- if (session->aclname) {
- qemu_acl *acl = qemu_acl_find(session->aclname);
- int allow;
- if (!acl) {
- error_setg(errp, "Cannot find ACL %s",
- session->aclname);
+ if (session->authzid) {
+ bool allow;
+
+ allow = qauthz_is_allowed_by_id(session->authzid,
+ session->peername, &err);
+ if (err) {
+ error_propagate(errp, err);
goto error;
}
-
- allow = qemu_acl_party_is_allowed(acl, session->peername);
-
if (!allow) {
- error_setg(errp, "TLS x509 ACL check for %s is denied",
+ error_setg(errp, "TLS x509 authz check for %s is denied",
session->peername);
goto error;
}
@@ -555,7 +554,7 @@
QCryptoTLSSession *
qcrypto_tls_session_new(QCryptoTLSCreds *creds G_GNUC_UNUSED,
const char *hostname G_GNUC_UNUSED,
- const char *aclname G_GNUC_UNUSED,
+ const char *authzid G_GNUC_UNUSED,
QCryptoTLSCredsEndpoint endpoint G_GNUC_UNUSED,
Error **errp)
{
diff --git a/crypto/trace-events b/crypto/trace-events
index 597389b..a38ad7b 100644
--- a/crypto/trace-events
+++ b/crypto/trace-events
@@ -19,5 +19,5 @@
qcrypto_tls_creds_x509_load_cert_list(void *creds, const char *file) "TLS creds x509 load cert list creds=%p file=%s"
# crypto/tlssession.c
-qcrypto_tls_session_new(void *session, void *creds, const char *hostname, const char *aclname, int endpoint) "TLS session new session=%p creds=%p hostname=%s aclname=%s endpoint=%d"
+qcrypto_tls_session_new(void *session, void *creds, const char *hostname, const char *authzid, int endpoint) "TLS session new session=%p creds=%p hostname=%s authzid=%s endpoint=%d"
qcrypto_tls_session_check_creds(void *session, const char *status) "TLS session check creds session=%p status=%s"
diff --git a/default-configs/arm-softmmu.mak b/default-configs/arm-softmmu.mak
index 87ad267..bd6943b 100644
--- a/default-configs/arm-softmmu.mak
+++ b/default-configs/arm-softmmu.mak
@@ -119,6 +119,7 @@
CONFIG_IOTKIT_SYSCTL=y
CONFIG_IOTKIT_SYSINFO=y
CONFIG_ARMSSE_CPUID=y
+CONFIG_ARMSSE_MHU=y
CONFIG_VERSATILE=y
CONFIG_VERSATILE_PCI=y
diff --git a/default-configs/virtio.mak b/default-configs/virtio.mak
index ecb4420..b653aa0 100644
--- a/default-configs/virtio.mak
+++ b/default-configs/virtio.mak
@@ -1,5 +1,5 @@
-CONFIG_VHOST_USER_SCSI=$(call land,$(CONFIG_VHOST_USER),$(CONFIG_LINUX))
-CONFIG_VHOST_USER_BLK=$(call land,$(CONFIG_VHOST_USER),$(CONFIG_LINUX))
+CONFIG_VHOST_USER_SCSI=$(CONFIG_VHOST_USER)
+CONFIG_VHOST_USER_BLK=$(CONFIG_VHOST_USER)
CONFIG_VIRTIO=y
CONFIG_VIRTIO_9P=$(CONFIG_VIRTFS)
CONFIG_VIRTIO_BALLOON=y
diff --git a/disas/nanomips.cpp b/disas/nanomips.cpp
index f90f1a9..c8495b1 100644
--- a/disas/nanomips.cpp
+++ b/disas/nanomips.cpp
@@ -1058,7 +1058,7 @@
}
-uint64 NMD::extract_ac_13_12(uint64 instruction)
+uint64 NMD::extract_ac_15_14(uint64 instruction)
{
uint64 value = 0;
value |= extract_bits(instruction, 14, 2);
@@ -3452,14 +3452,14 @@
/*
- *
+ * [DSP] BPOSGE32C offset - Branch on greater than or equal to value 32 in
+ * DSPControl Pos field
*
* 3 2 1
* 10987654321098765432109876543210
- * 001000 x1110000101
- * rt -----
- * rs -----
- * rd -----
+ * 100010xxxxx0010001
+ * s[13:1] -------------
+ * s[14] -
*/
std::string NMD::BPOSGE32C(uint64 instruction)
{
@@ -3872,14 +3872,13 @@
/*
- *
+ * [DSP] CMP.EQ.PH rs, rt - Compare vectors of signed integer halfword values
*
* 3 2 1
* 10987654321098765432109876543210
- * 001000 x1110000101
+ * 001000 xxxxxx0000000101
* rt -----
* rs -----
- * rd -----
*/
std::string NMD::CMP_EQ_PH(uint64 instruction)
{
@@ -3942,14 +3941,13 @@
/*
- *
+ * [DSP] CMP.LE.PH rs, rt - Compare vectors of signed integer halfword values
*
* 3 2 1
* 10987654321098765432109876543210
- * 001000 x1110000101
+ * 001000 xxxxxx0010000101
* rt -----
* rs -----
- * rd -----
*/
std::string NMD::CMP_LE_PH(uint64 instruction)
{
@@ -4012,14 +4010,13 @@
/*
- *
+ * [DSP] CMP.LT.PH rs, rt - Compare vectors of signed integer halfword values
*
* 3 2 1
* 10987654321098765432109876543210
- * 001000 x1110000101
+ * 001000 xxxxxx0001000101
* rt -----
* rs -----
- * rd -----
*/
std::string NMD::CMP_LT_PH(uint64 instruction)
{
@@ -4922,11 +4919,12 @@
/*
- *
+ * [DSP] CMPGDU.EQ.QB rd, rs, rt - Compare unsigned vector of
+ * four bytes and write result to GPR and DSPControl
*
* 3 2 1
* 10987654321098765432109876543210
- * 001000 x1110000101
+ * 001000 x0110000101
* rt -----
* rs -----
* rd -----
@@ -4946,11 +4944,12 @@
/*
- *
+ * [DSP] CMPGDU.LE.QB rd, rs, rt - Compare unsigned vector of
+ * four bytes and write result to GPR and DSPControl
*
* 3 2 1
* 10987654321098765432109876543210
- * 001000 x1110000101
+ * 001000 x1000000101
* rt -----
* rs -----
* rd -----
@@ -4970,11 +4969,12 @@
/*
- *
+ * [DSP] CMPGDU.EQ.QB rd, rs, rt - Compare unsigned vector of
+ * four bytes and write result to GPR and DSPControl
*
* 3 2 1
* 10987654321098765432109876543210
- * 001000 x1110000101
+ * 001000 x0111000101
* rt -----
* rs -----
* rd -----
@@ -4994,11 +4994,12 @@
/*
- *
+ * [DSP] CMPGU.EQ.QB rd, rs, rt - Compare vectors of unsigned
+ * byte values and write result to a GPR
*
* 3 2 1
* 10987654321098765432109876543210
- * 001000 x1110000101
+ * 001000 x0011000101
* rt -----
* rs -----
* rd -----
@@ -5018,11 +5019,12 @@
/*
- *
+ * [DSP] CMPGU.LE.QB rd, rs, rt - Compare vectors of unsigned
+ * byte values and write result to a GPR
*
* 3 2 1
* 10987654321098765432109876543210
- * 001000 x1110000101
+ * 001000 x0101000101
* rt -----
* rs -----
* rd -----
@@ -5042,11 +5044,12 @@
/*
- *
+ * [DSP] CMPGU.LT.QB rd, rs, rt - Compare vectors of unsigned
+ * byte values and write result to a GPR
*
* 3 2 1
* 10987654321098765432109876543210
- * 001000 x1110000101
+ * 001000 x0100000101
* rt -----
* rs -----
* rd -----
@@ -5066,14 +5069,14 @@
/*
- *
+ * [DSP] CMPU.EQ.QB rd, rs, rt - Compare vectors of unsigned
+ * byte values
*
* 3 2 1
* 10987654321098765432109876543210
- * 001000 x1110000101
+ * 001000 xxxxxx1001000101
* rt -----
* rs -----
- * rd -----
*/
std::string NMD::CMPU_EQ_QB(uint64 instruction)
{
@@ -5088,14 +5091,14 @@
/*
- *
+ * [DSP] CMPU.LE.QB rd, rs, rt - Compare vectors of unsigned
+ * byte values
*
* 3 2 1
* 10987654321098765432109876543210
- * 001000 x1110000101
+ * 001000 xxxxxx1011000101
* rt -----
* rs -----
- * rd -----
*/
std::string NMD::CMPU_LE_QB(uint64 instruction)
{
@@ -5110,14 +5113,14 @@
/*
- *
+ * [DSP] CMPU.LT.QB rd, rs, rt - Compare vectors of unsigned
+ * byte values
*
* 3 2 1
* 10987654321098765432109876543210
- * 001000 x1110000101
+ * 001000 xxxxxx1010000101
* rt -----
* rs -----
- * rd -----
*/
std::string NMD::CMPU_LT_QB(uint64 instruction)
{
@@ -6362,20 +6365,21 @@
/*
- *
+ * [DSP] DPA.W.PH ac, rs, rt - Dot product with accumulate on
+ * vector integer halfword elements
*
* 3 2 1
* 10987654321098765432109876543210
- * 001000 x1110000101
+ * 001000 00000010111111
* rt -----
* rs -----
- * rd -----
+ * ac --
*/
std::string NMD::DPA_W_PH(uint64 instruction)
{
uint64 rt_value = extract_rt_25_24_23_22_21(instruction);
uint64 rs_value = extract_rs_20_19_18_17_16(instruction);
- uint64 ac_value = extract_ac_13_12(instruction);
+ uint64 ac_value = extract_ac_15_14(instruction);
std::string ac = AC(copy(ac_value));
std::string rs = GPR(copy(rs_value));
@@ -6399,7 +6403,7 @@
{
uint64 rt_value = extract_rt_25_24_23_22_21(instruction);
uint64 rs_value = extract_rs_20_19_18_17_16(instruction);
- uint64 ac_value = extract_ac_13_12(instruction);
+ uint64 ac_value = extract_ac_15_14(instruction);
std::string ac = AC(copy(ac_value));
std::string rs = GPR(copy(rs_value));
@@ -6423,7 +6427,7 @@
{
uint64 rt_value = extract_rt_25_24_23_22_21(instruction);
uint64 rs_value = extract_rs_20_19_18_17_16(instruction);
- uint64 ac_value = extract_ac_13_12(instruction);
+ uint64 ac_value = extract_ac_15_14(instruction);
std::string ac = AC(copy(ac_value));
std::string rs = GPR(copy(rs_value));
@@ -6447,7 +6451,7 @@
{
uint64 rt_value = extract_rt_25_24_23_22_21(instruction);
uint64 rs_value = extract_rs_20_19_18_17_16(instruction);
- uint64 ac_value = extract_ac_13_12(instruction);
+ uint64 ac_value = extract_ac_15_14(instruction);
std::string ac = AC(copy(ac_value));
std::string rs = GPR(copy(rs_value));
@@ -6471,7 +6475,7 @@
{
uint64 rt_value = extract_rt_25_24_23_22_21(instruction);
uint64 rs_value = extract_rs_20_19_18_17_16(instruction);
- uint64 ac_value = extract_ac_13_12(instruction);
+ uint64 ac_value = extract_ac_15_14(instruction);
std::string ac = AC(copy(ac_value));
std::string rs = GPR(copy(rs_value));
@@ -6495,7 +6499,7 @@
{
uint64 rt_value = extract_rt_25_24_23_22_21(instruction);
uint64 rs_value = extract_rs_20_19_18_17_16(instruction);
- uint64 ac_value = extract_ac_13_12(instruction);
+ uint64 ac_value = extract_ac_15_14(instruction);
std::string ac = AC(copy(ac_value));
std::string rs = GPR(copy(rs_value));
@@ -6519,7 +6523,7 @@
{
uint64 rt_value = extract_rt_25_24_23_22_21(instruction);
uint64 rs_value = extract_rs_20_19_18_17_16(instruction);
- uint64 ac_value = extract_ac_13_12(instruction);
+ uint64 ac_value = extract_ac_15_14(instruction);
std::string ac = AC(copy(ac_value));
std::string rs = GPR(copy(rs_value));
@@ -6543,7 +6547,7 @@
{
uint64 rt_value = extract_rt_25_24_23_22_21(instruction);
uint64 rs_value = extract_rs_20_19_18_17_16(instruction);
- uint64 ac_value = extract_ac_13_12(instruction);
+ uint64 ac_value = extract_ac_15_14(instruction);
std::string ac = AC(copy(ac_value));
std::string rs = GPR(copy(rs_value));
@@ -6567,7 +6571,7 @@
{
uint64 rt_value = extract_rt_25_24_23_22_21(instruction);
uint64 rs_value = extract_rs_20_19_18_17_16(instruction);
- uint64 ac_value = extract_ac_13_12(instruction);
+ uint64 ac_value = extract_ac_15_14(instruction);
std::string ac = AC(copy(ac_value));
std::string rs = GPR(copy(rs_value));
@@ -6591,7 +6595,7 @@
{
uint64 rt_value = extract_rt_25_24_23_22_21(instruction);
uint64 rs_value = extract_rs_20_19_18_17_16(instruction);
- uint64 ac_value = extract_ac_13_12(instruction);
+ uint64 ac_value = extract_ac_15_14(instruction);
std::string ac = AC(copy(ac_value));
std::string rs = GPR(copy(rs_value));
@@ -6615,7 +6619,7 @@
{
uint64 rt_value = extract_rt_25_24_23_22_21(instruction);
uint64 rs_value = extract_rs_20_19_18_17_16(instruction);
- uint64 ac_value = extract_ac_13_12(instruction);
+ uint64 ac_value = extract_ac_15_14(instruction);
std::string ac = AC(copy(ac_value));
std::string rs = GPR(copy(rs_value));
@@ -6639,7 +6643,7 @@
{
uint64 rt_value = extract_rt_25_24_23_22_21(instruction);
uint64 rs_value = extract_rs_20_19_18_17_16(instruction);
- uint64 ac_value = extract_ac_13_12(instruction);
+ uint64 ac_value = extract_ac_15_14(instruction);
std::string ac = AC(copy(ac_value));
std::string rs = GPR(copy(rs_value));
@@ -6663,7 +6667,7 @@
{
uint64 rt_value = extract_rt_25_24_23_22_21(instruction);
uint64 rs_value = extract_rs_20_19_18_17_16(instruction);
- uint64 ac_value = extract_ac_13_12(instruction);
+ uint64 ac_value = extract_ac_15_14(instruction);
std::string ac = AC(copy(ac_value));
std::string rs = GPR(copy(rs_value));
@@ -6687,7 +6691,7 @@
{
uint64 rt_value = extract_rt_25_24_23_22_21(instruction);
uint64 rs_value = extract_rs_20_19_18_17_16(instruction);
- uint64 ac_value = extract_ac_13_12(instruction);
+ uint64 ac_value = extract_ac_15_14(instruction);
std::string ac = AC(copy(ac_value));
std::string rs = GPR(copy(rs_value));
@@ -6711,7 +6715,7 @@
{
uint64 rt_value = extract_rt_25_24_23_22_21(instruction);
uint64 rs_value = extract_rs_20_19_18_17_16(instruction);
- uint64 ac_value = extract_ac_13_12(instruction);
+ uint64 ac_value = extract_ac_15_14(instruction);
std::string ac = AC(copy(ac_value));
std::string rs = GPR(copy(rs_value));
@@ -6735,7 +6739,7 @@
{
uint64 rt_value = extract_rt_25_24_23_22_21(instruction);
uint64 rs_value = extract_rs_20_19_18_17_16(instruction);
- uint64 ac_value = extract_ac_13_12(instruction);
+ uint64 ac_value = extract_ac_15_14(instruction);
std::string ac = AC(copy(ac_value));
std::string rs = GPR(copy(rs_value));
@@ -7373,7 +7377,7 @@
{
uint64 rt_value = extract_rt_25_24_23_22_21(instruction);
uint64 size_value = extract_size_20_19_18_17_16(instruction);
- uint64 ac_value = extract_ac_13_12(instruction);
+ uint64 ac_value = extract_ac_15_14(instruction);
std::string rt = GPR(copy(rt_value));
std::string ac = AC(copy(ac_value));
@@ -7397,7 +7401,7 @@
{
uint64 rt_value = extract_rt_25_24_23_22_21(instruction);
uint64 rs_value = extract_rs_20_19_18_17_16(instruction);
- uint64 ac_value = extract_ac_13_12(instruction);
+ uint64 ac_value = extract_ac_15_14(instruction);
std::string rt = GPR(copy(rt_value));
std::string ac = AC(copy(ac_value));
@@ -7421,7 +7425,7 @@
{
uint64 rt_value = extract_rt_25_24_23_22_21(instruction);
uint64 size_value = extract_size_20_19_18_17_16(instruction);
- uint64 ac_value = extract_ac_13_12(instruction);
+ uint64 ac_value = extract_ac_15_14(instruction);
std::string rt = GPR(copy(rt_value));
std::string ac = AC(copy(ac_value));
@@ -7445,7 +7449,7 @@
{
uint64 rt_value = extract_rt_25_24_23_22_21(instruction);
uint64 rs_value = extract_rs_20_19_18_17_16(instruction);
- uint64 ac_value = extract_ac_13_12(instruction);
+ uint64 ac_value = extract_ac_15_14(instruction);
std::string rt = GPR(copy(rt_value));
std::string ac = AC(copy(ac_value));
@@ -7456,20 +7460,21 @@
/*
- *
+ * [DSP] EXTR_RS.W rt, ac, shift - Extract word value from accumulator to GPR
+ * with right shift
*
* 3 2 1
* 10987654321098765432109876543210
- * 001000 x1110000101
+ * 001000 10111001111111
* rt -----
- * rs -----
- * rd -----
+ * shift -----
+ * ac --
*/
std::string NMD::EXTR_RS_W(uint64 instruction)
{
uint64 rt_value = extract_rt_25_24_23_22_21(instruction);
uint64 shift_value = extract_shift_20_19_18_17_16(instruction);
- uint64 ac_value = extract_ac_13_12(instruction);
+ uint64 ac_value = extract_ac_15_14(instruction);
std::string rt = GPR(copy(rt_value));
std::string ac = AC(copy(ac_value));
@@ -7480,20 +7485,21 @@
/*
- *
+ * [DSP] EXTR_R.W rt, ac, shift - Extract word value from accumulator to GPR
+ * with right shift
*
* 3 2 1
* 10987654321098765432109876543210
- * 001000 x1110000101
+ * 001000 01111001111111
* rt -----
- * rs -----
- * rd -----
+ * shift -----
+ * ac --
*/
std::string NMD::EXTR_R_W(uint64 instruction)
{
uint64 rt_value = extract_rt_25_24_23_22_21(instruction);
uint64 shift_value = extract_shift_20_19_18_17_16(instruction);
- uint64 ac_value = extract_ac_13_12(instruction);
+ uint64 ac_value = extract_ac_15_14(instruction);
std::string rt = GPR(copy(rt_value));
std::string ac = AC(copy(ac_value));
@@ -7504,20 +7510,21 @@
/*
- *
+ * [DSP] EXTR_S.H rt, ac, shift - Extract halfword value from accumulator
+ * to GPR with right shift and saturate
*
* 3 2 1
* 10987654321098765432109876543210
- * 001000 x1110000101
+ * 001000 11111001111111
* rt -----
- * rs -----
- * rd -----
+ * shift -----
+ * ac --
*/
std::string NMD::EXTR_S_H(uint64 instruction)
{
uint64 rt_value = extract_rt_25_24_23_22_21(instruction);
uint64 shift_value = extract_shift_20_19_18_17_16(instruction);
- uint64 ac_value = extract_ac_13_12(instruction);
+ uint64 ac_value = extract_ac_15_14(instruction);
std::string rt = GPR(copy(rt_value));
std::string ac = AC(copy(ac_value));
@@ -7528,20 +7535,21 @@
/*
- *
+ * [DSP] EXTR.W rt, ac, shift - Extract word value from accumulator to GPR
+ * with right shift
*
* 3 2 1
* 10987654321098765432109876543210
- * 001000 x1110000101
+ * 001000 00111001111111
* rt -----
- * rs -----
- * rd -----
+ * shift -----
+ * ac --
*/
std::string NMD::EXTR_W(uint64 instruction)
{
uint64 rt_value = extract_rt_25_24_23_22_21(instruction);
uint64 shift_value = extract_shift_20_19_18_17_16(instruction);
- uint64 ac_value = extract_ac_13_12(instruction);
+ uint64 ac_value = extract_ac_15_14(instruction);
std::string rt = GPR(copy(rt_value));
std::string ac = AC(copy(ac_value));
@@ -7552,20 +7560,21 @@
/*
- *
+ * [DSP] EXTRV_RS.W rt, ac, rs - Extract word value with variable
+ * right shift from accumulator to GPR
*
* 3 2 1
* 10987654321098765432109876543210
- * 001000 x1110000101
+ * 001000 10111010111111
* rt -----
* rs -----
- * rd -----
+ * ac --
*/
std::string NMD::EXTRV_RS_W(uint64 instruction)
{
uint64 rt_value = extract_rt_25_24_23_22_21(instruction);
uint64 rs_value = extract_rs_20_19_18_17_16(instruction);
- uint64 ac_value = extract_ac_13_12(instruction);
+ uint64 ac_value = extract_ac_15_14(instruction);
std::string rt = GPR(copy(rt_value));
std::string ac = AC(copy(ac_value));
@@ -7576,20 +7585,21 @@
/*
- *
+ * [DSP] EXTRV_R.W rt, ac, rs - Extract word value with variable
+ * right shift from accumulator to GPR
*
* 3 2 1
* 10987654321098765432109876543210
- * 001000 x1110000101
+ * 001000 01111010111111
* rt -----
* rs -----
- * rd -----
+ * ac --
*/
std::string NMD::EXTRV_R_W(uint64 instruction)
{
uint64 rt_value = extract_rt_25_24_23_22_21(instruction);
uint64 rs_value = extract_rs_20_19_18_17_16(instruction);
- uint64 ac_value = extract_ac_13_12(instruction);
+ uint64 ac_value = extract_ac_15_14(instruction);
std::string rt = GPR(copy(rt_value));
std::string ac = AC(copy(ac_value));
@@ -7600,20 +7610,21 @@
/*
- *
+ * [DSP] EXTRV_S.H rt, ac, rs - Extract halfword value variable from
+ * accumulator to GPR with right shift and saturate
*
* 3 2 1
* 10987654321098765432109876543210
- * 001000 x1110000101
+ * 001000 11111010111111
* rt -----
* rs -----
- * rd -----
+ * ac --
*/
std::string NMD::EXTRV_S_H(uint64 instruction)
{
uint64 rt_value = extract_rt_25_24_23_22_21(instruction);
uint64 rs_value = extract_rs_20_19_18_17_16(instruction);
- uint64 ac_value = extract_ac_13_12(instruction);
+ uint64 ac_value = extract_ac_15_14(instruction);
std::string rt = GPR(copy(rt_value));
std::string ac = AC(copy(ac_value));
@@ -7624,20 +7635,21 @@
/*
- *
+ * [DSP] EXTRV.W rt, ac, rs - Extract word value with variable
+ * right shift from accumulator to GPR
*
* 3 2 1
* 10987654321098765432109876543210
- * 001000 x1110000101
+ * 001000 00111010111111
* rt -----
* rs -----
- * rd -----
+ * ac --
*/
std::string NMD::EXTRV_W(uint64 instruction)
{
uint64 rt_value = extract_rt_25_24_23_22_21(instruction);
uint64 rs_value = extract_rs_20_19_18_17_16(instruction);
- uint64 ac_value = extract_ac_13_12(instruction);
+ uint64 ac_value = extract_ac_15_14(instruction);
std::string rt = GPR(copy(rt_value));
std::string ac = AC(copy(ac_value));
@@ -7855,14 +7867,13 @@
/*
- * [DSP] INSV - Insert bit field variable
+ * [DSP] INSV rt, rs - Insert bit field variable
*
* 3 2 1
* 10987654321098765432109876543210
- * 001000 x1110000101
+ * 001000 0100000100111111
* rt -----
* rs -----
- * rd -----
*/
std::string NMD::INSV(uint64 instruction)
{
@@ -9719,7 +9730,7 @@
{
uint64 rt_value = extract_rt_25_24_23_22_21(instruction);
uint64 rs_value = extract_rs_20_19_18_17_16(instruction);
- uint64 ac_value = extract_ac_13_12(instruction);
+ uint64 ac_value = extract_ac_15_14(instruction);
std::string ac = AC(copy(ac_value));
std::string rs = GPR(copy(rs_value));
@@ -9792,7 +9803,7 @@
{
uint64 rt_value = extract_rt_25_24_23_22_21(instruction);
uint64 rs_value = extract_rs_20_19_18_17_16(instruction);
- uint64 ac_value = extract_ac_13_12(instruction);
+ uint64 ac_value = extract_ac_15_14(instruction);
std::string ac = AC(copy(ac_value));
std::string rs = GPR(copy(rs_value));
@@ -9817,7 +9828,7 @@
{
uint64 rt_value = extract_rt_25_24_23_22_21(instruction);
uint64 rs_value = extract_rs_20_19_18_17_16(instruction);
- uint64 ac_value = extract_ac_13_12(instruction);
+ uint64 ac_value = extract_ac_15_14(instruction);
std::string ac = AC(copy(ac_value));
std::string rs = GPR(copy(rs_value));
@@ -9842,7 +9853,7 @@
{
uint64 rt_value = extract_rt_25_24_23_22_21(instruction);
uint64 rs_value = extract_rs_20_19_18_17_16(instruction);
- uint64 ac_value = extract_ac_13_12(instruction);
+ uint64 ac_value = extract_ac_15_14(instruction);
std::string ac = AC(copy(ac_value));
std::string rs = GPR(copy(rs_value));
@@ -9867,7 +9878,7 @@
{
uint64 rt_value = extract_rt_25_24_23_22_21(instruction);
uint64 rs_value = extract_rs_20_19_18_17_16(instruction);
- uint64 ac_value = extract_ac_13_12(instruction);
+ uint64 ac_value = extract_ac_15_14(instruction);
std::string ac = AC(copy(ac_value));
std::string rs = GPR(copy(rs_value));
@@ -9892,7 +9903,7 @@
{
uint64 rt_value = extract_rt_25_24_23_22_21(instruction);
uint64 rs_value = extract_rs_20_19_18_17_16(instruction);
- uint64 ac_value = extract_ac_13_12(instruction);
+ uint64 ac_value = extract_ac_15_14(instruction);
std::string ac = AC(copy(ac_value));
std::string rs = GPR(copy(rs_value));
@@ -10183,19 +10194,18 @@
/*
- *
+ * [DSP] MFHI rs, ac - Move from HI register
*
* 3 2 1
* 10987654321098765432109876543210
- * 001000 x1110000101
+ * 001000 xxxxx 00000001111111
* rt -----
- * rs -----
- * rd -----
+ * ac --
*/
std::string NMD::MFHI_DSP_(uint64 instruction)
{
uint64 rt_value = extract_rt_25_24_23_22_21(instruction);
- uint64 ac_value = extract_ac_13_12(instruction);
+ uint64 ac_value = extract_ac_15_14(instruction);
std::string rt = GPR(copy(rt_value));
std::string ac = AC(copy(ac_value));
@@ -10231,19 +10241,18 @@
/*
- *
+ * [DSP] MFLO rs, ac - Move from HI register
*
* 3 2 1
* 10987654321098765432109876543210
- * 001000 x1110000101
+ * 001000 xxxxx 01000001111111
* rt -----
- * rs -----
- * rd -----
+ * ac --
*/
std::string NMD::MFLO_DSP_(uint64 instruction)
{
uint64 rt_value = extract_rt_25_24_23_22_21(instruction);
- uint64 ac_value = extract_ac_13_12(instruction);
+ uint64 ac_value = extract_ac_15_14(instruction);
std::string rt = GPR(copy(rt_value));
std::string ac = AC(copy(ac_value));
@@ -10399,7 +10408,7 @@
/*
- *
+ * [DSP] MODSUB rd, rs, rt - Modular subtraction on an index value
*
* 3 2 1
* 10987654321098765432109876543210
@@ -10427,7 +10436,7 @@
*
* 3 2 1
* 10987654321098765432109876543210
- * 001000 x1110000101
+ * 001000 x1010010101
* rt -----
* rs -----
* rd -----
@@ -10639,20 +10648,20 @@
/*
- * ADDQH_R.W rd, rt, rs - Add Fractional Words And Shift Right to Halve Results
+ * [DSP] MSUB ac, rs, rt - Multiply word and subtract from accumulator
*
* 3 2 1
* 10987654321098765432109876543210
- * 001000 00010001101
+ * 001000 10101010111111
* rt -----
* rs -----
- * rd -----
+ * ac --
*/
std::string NMD::MSUB_DSP_(uint64 instruction)
{
uint64 rt_value = extract_rt_25_24_23_22_21(instruction);
uint64 rs_value = extract_rs_20_19_18_17_16(instruction);
- uint64 ac_value = extract_ac_13_12(instruction);
+ uint64 ac_value = extract_ac_15_14(instruction);
std::string ac = AC(copy(ac_value));
std::string rs = GPR(copy(rs_value));
@@ -10711,20 +10720,20 @@
/*
- * ADDQH_R.W rd, rt, rs - Add Fractional Words And Shift Right to Halve Results
+ * [DSP] MSUBU ac, rs, rt - Multiply word and add to accumulator
*
* 3 2 1
* 10987654321098765432109876543210
- * 001000 00010001101
+ * 001000 11101010111111
* rt -----
* rs -----
- * rd -----
+ * ac --
*/
std::string NMD::MSUBU_DSP_(uint64 instruction)
{
uint64 rt_value = extract_rt_25_24_23_22_21(instruction);
uint64 rs_value = extract_rs_20_19_18_17_16(instruction);
- uint64 ac_value = extract_ac_13_12(instruction);
+ uint64 ac_value = extract_ac_15_14(instruction);
std::string ac = AC(copy(ac_value));
std::string rs = GPR(copy(rs_value));
@@ -10919,19 +10928,18 @@
/*
- * ADDQH_R.W rd, rt, rs - Add Fractional Words And Shift Right to Halve Results
+ * [DSP] MTHI rs, ac - Move to HI register
*
* 3 2 1
* 10987654321098765432109876543210
- * 001000 00010001101
- * rt -----
+ * 001000xxxxx 10000001111111
* rs -----
- * rd -----
+ * ac --
*/
std::string NMD::MTHI_DSP_(uint64 instruction)
{
uint64 rs_value = extract_rs_20_19_18_17_16(instruction);
- uint64 ac_value = extract_ac_13_12(instruction);
+ uint64 ac_value = extract_ac_15_14(instruction);
std::string rs = GPR(copy(rs_value));
std::string ac = AC(copy(ac_value));
@@ -10941,19 +10949,18 @@
/*
- * ADDQH_R.W rd, rt, rs - Add Fractional Words And Shift Right to Halve Results
+ * [DSP] MTHLIP rs, ac - Copy LO to HI and a GPR to LO and increment pos by 32
*
* 3 2 1
* 10987654321098765432109876543210
- * 001000 00010001101
- * rt -----
+ * 001000xxxxx 00001001111111
* rs -----
- * rd -----
+ * ac --
*/
std::string NMD::MTHLIP(uint64 instruction)
{
uint64 rs_value = extract_rs_20_19_18_17_16(instruction);
- uint64 ac_value = extract_ac_13_12(instruction);
+ uint64 ac_value = extract_ac_15_14(instruction);
std::string rs = GPR(copy(rs_value));
std::string ac = AC(copy(ac_value));
@@ -10989,19 +10996,18 @@
/*
- * ADDQH_R.W rd, rt, rs - Add Fractional Words And Shift Right to Halve Results
+ * [DSP] MTLO rs, ac - Move to LO register
*
* 3 2 1
* 10987654321098765432109876543210
- * 001000 00010001101
- * rt -----
+ * 001000xxxxx 11000001111111
* rs -----
- * rd -----
+ * ac --
*/
std::string NMD::MTLO_DSP_(uint64 instruction)
{
uint64 rs_value = extract_rs_20_19_18_17_16(instruction);
- uint64 ac_value = extract_ac_13_12(instruction);
+ uint64 ac_value = extract_ac_15_14(instruction);
std::string rs = GPR(copy(rs_value));
std::string ac = AC(copy(ac_value));
@@ -11155,11 +11161,12 @@
/*
- * ADDQH_R.W rd, rt, rs - Add Fractional Words And Shift Right to Halve Results
+ * [DSP] MUL.PH rd, rs, rt - Multiply vector integer half words to same size
+ * products
*
* 3 2 1
* 10987654321098765432109876543210
- * 001000 00010001101
+ * 001000 00000101101
* rt -----
* rs -----
* rd -----
@@ -11179,11 +11186,12 @@
/*
- * ADDQH_R.W rd, rt, rs - Add Fractional Words And Shift Right to Halve Results
+ * [DSP] MUL_S.PH rd, rs, rt - Multiply vector integer half words to same size
+ * products (saturated)
*
* 3 2 1
* 10987654321098765432109876543210
- * 001000 00010001101
+ * 001000 10000101101
* rt -----
* rs -----
* rd -----
@@ -11227,11 +11235,12 @@
/*
- * ADDQH_R.W rd, rt, rs - Add Fractional Words And Shift Right to Halve Results
+ * [DSP] MULEQ_S.W.PHL rd, rs, rt - Multiply vector fractional left halfwords
+ * to expanded width products
*
* 3 2 1
* 10987654321098765432109876543210
- * 001000 00010001101
+ * 001000 x0000100101
* rt -----
* rs -----
* rd -----
@@ -11251,11 +11260,12 @@
/*
- * ADDQH_R.W rd, rt, rs - Add Fractional Words And Shift Right to Halve Results
+ * [DSP] MULEQ_S.W.PHR rd, rs, rt - Multiply vector fractional right halfwords
+ * to expanded width products
*
* 3 2 1
* 10987654321098765432109876543210
- * 001000 00010001101
+ * 001000 x0001100101
* rt -----
* rs -----
* rd -----
@@ -11275,11 +11285,12 @@
/*
- * ADDQH_R.W rd, rt, rs - Add Fractional Words And Shift Right to Halve Results
+ * [DSP] MULEU_S.PH.QBL rd, rs, rt - Multiply vector fractional left bytes
+ * by halfwords to halfword products
*
* 3 2 1
* 10987654321098765432109876543210
- * 001000 00010001101
+ * 001000 x0010010101
* rt -----
* rs -----
* rd -----
@@ -11299,11 +11310,12 @@
/*
- * ADDQH_R.W rd, rt, rs - Add Fractional Words And Shift Right to Halve Results
+ * [DSP] MULEU_S.PH.QBR rd, rs, rt - Multiply vector fractional right bytes
+ * by halfwords to halfword products
*
* 3 2 1
* 10987654321098765432109876543210
- * 001000 00010001101
+ * 001000 x0011010101
* rt -----
* rs -----
* rd -----
@@ -11323,11 +11335,12 @@
/*
- * ADDQH_R.W rd, rt, rs - Add Fractional Words And Shift Right to Halve Results
+ * [DSP] MULQ_RS.PH rd, rs, rt - Multiply vector fractional halfwords
+ * to fractional halfword products
*
* 3 2 1
* 10987654321098765432109876543210
- * 001000 00010001101
+ * 001000 x0100010101
* rt -----
* rs -----
* rd -----
@@ -11347,11 +11360,12 @@
/*
- * ADDQH_R.W rd, rt, rs - Add Fractional Words And Shift Right to Halve Results
+ * [DSP] MULQ_RS.W rd, rs, rt - Multiply fractional words to same size
+ * product with saturation and rounding
*
* 3 2 1
* 10987654321098765432109876543210
- * 001000 00010001101
+ * 001000 x0110010101
* rt -----
* rs -----
* rd -----
@@ -11371,11 +11385,12 @@
/*
- * ADDQH_R.W rd, rt, rs - Add Fractional Words And Shift Right to Halve Results
+ * [DSP] MULQ_S.PH rd, rs, rt - Multiply fractional halfwords to same size
+ * products
*
* 3 2 1
* 10987654321098765432109876543210
- * 001000 00010001101
+ * 001000 x0101010101
* rt -----
* rs -----
* rd -----
@@ -11395,11 +11410,12 @@
/*
- * ADDQH_R.W rd, rt, rs - Add Fractional Words And Shift Right to Halve Results
+ * [DSP] MULQ_S.W rd, rs, rt - Multiply fractional words to same size product
+ * with saturation
*
* 3 2 1
* 10987654321098765432109876543210
- * 001000 00010001101
+ * 001000 x0111010101
* rt -----
* rs -----
* rd -----
@@ -11419,20 +11435,21 @@
/*
- * ADDQH_R.W rd, rt, rs - Add Fractional Words And Shift Right to Halve Results
+ * [DSP] MULSA.W.PH ac, rs, rt - Multiply and subtract vector integer halfword
+ * elements and accumulate
*
* 3 2 1
* 10987654321098765432109876543210
- * 001000 00010001101
+ * 001000 10110010111111
* rt -----
* rs -----
- * rd -----
+ * ac --
*/
std::string NMD::MULSA_W_PH(uint64 instruction)
{
uint64 rt_value = extract_rt_25_24_23_22_21(instruction);
uint64 rs_value = extract_rs_20_19_18_17_16(instruction);
- uint64 ac_value = extract_ac_13_12(instruction);
+ uint64 ac_value = extract_ac_15_14(instruction);
std::string ac = AC(copy(ac_value));
std::string rs = GPR(copy(rs_value));
@@ -11443,20 +11460,21 @@
/*
- * ADDQH_R.W rd, rt, rs - Add Fractional Words And Shift Right to Halve Results
+ * [DSP] MULSAQ_S.W.PH ac, rs, rt - Multiply and subtract vector fractional
+ * halfwords and accumulate
*
* 3 2 1
* 10987654321098765432109876543210
- * 001000 00010001101
+ * 001000 11110010111111
* rt -----
* rs -----
- * rd -----
+ * ac --
*/
std::string NMD::MULSAQ_S_W_PH(uint64 instruction)
{
uint64 rt_value = extract_rt_25_24_23_22_21(instruction);
uint64 rs_value = extract_rs_20_19_18_17_16(instruction);
- uint64 ac_value = extract_ac_13_12(instruction);
+ uint64 ac_value = extract_ac_15_14(instruction);
std::string ac = AC(copy(ac_value));
std::string rs = GPR(copy(rs_value));
@@ -11467,20 +11485,20 @@
/*
- * ADDQH_R.W rd, rt, rs - Add Fractional Words And Shift Right to Halve Results
+ * [DSP] MULT ac, rs, rt - Multiply word
*
* 3 2 1
* 10987654321098765432109876543210
- * 001000 00010001101
+ * 001000 00110010111111
* rt -----
* rs -----
- * rd -----
+ * ac --
*/
std::string NMD::MULT_DSP_(uint64 instruction)
{
uint64 rt_value = extract_rt_25_24_23_22_21(instruction);
uint64 rs_value = extract_rs_20_19_18_17_16(instruction);
- uint64 ac_value = extract_ac_13_12(instruction);
+ uint64 ac_value = extract_ac_15_14(instruction);
std::string ac = AC(copy(ac_value));
std::string rs = GPR(copy(rs_value));
@@ -11491,20 +11509,20 @@
/*
- * ADDQH_R.W rd, rt, rs - Add Fractional Words And Shift Right to Halve Results
+ * [DSP] MULTU ac, rs, rt - Multiply unsigned word
*
* 3 2 1
* 10987654321098765432109876543210
- * 001000 00010001101
+ * 001000 01110010111111
* rt -----
* rs -----
- * rd -----
+ * ac --
*/
std::string NMD::MULTU_DSP_(uint64 instruction)
{
uint64 rt_value = extract_rt_25_24_23_22_21(instruction);
uint64 rs_value = extract_rs_20_19_18_17_16(instruction);
- uint64 ac_value = extract_ac_13_12(instruction);
+ uint64 ac_value = extract_ac_15_14(instruction);
std::string ac = AC(copy(ac_value));
std::string rs = GPR(copy(rs_value));
@@ -12060,11 +12078,12 @@
/*
- * ADDQH_R.W rd, rt, rs - Add Fractional Words And Shift Right to Halve Results
+ * [DSP] PRECR.QB.PH rd, rs, rt - Reduce the precision of four integer
+ * halfwords to four bytes
*
* 3 2 1
* 10987654321098765432109876543210
- * 001000 00010001101
+ * 001000 x0001101101
* rt -----
* rs -----
* rd -----
@@ -12084,7 +12103,8 @@
/*
- *
+ * [DSP] PRECR_SRA.PH.W rt, rs, sa - Reduce the precision of two integer
+ * words to halfwords after a right shift
*
* 3 2 1
* 10987654321098765432109876543210
@@ -12108,7 +12128,8 @@
/*
- *
+ * [DSP] PRECR_SRA_R.PH.W rt, rs, sa - Reduce the precision of two integer
+ * words to halfwords after a right shift with rounding
*
* 3 2 1
* 10987654321098765432109876543210
@@ -12132,7 +12153,8 @@
/*
- *
+ * [DSP] PRECRQ.PH.W rd, rs, rt - Reduce the precision of fractional
+ * words to fractional halfwords
*
* 3 2 1
* 10987654321098765432109876543210
@@ -12156,11 +12178,12 @@
/*
- *
+ * [DSP] PRECRQ.QB.PH rd, rs, rt - Reduce the precision of four fractional
+ * halfwords to four bytes
*
* 3 2 1
* 10987654321098765432109876543210
- * 001000 x1110000101
+ * 001000 x0010101101
* rt -----
* rs -----
* rd -----
@@ -12180,7 +12203,8 @@
/*
- *
+ * [DSP] PRECRQ_RS.PH.W rd, rs, rt - Reduce the precision of fractional
+ * words to halfwords with rounding and saturation
*
* 3 2 1
* 10987654321098765432109876543210
@@ -12204,7 +12228,8 @@
/*
- *
+ * [DSP] PRECRQU_S.QB.PH rd, rs, rt - Reduce the precision of fractional
+ * halfwords to unsigned bytes with saturation
*
* 3 2 1
* 10987654321098765432109876543210
@@ -12300,7 +12325,7 @@
/*
- *
+ * [DSP] PREPEND rt, rs, sa - Right shift and prepend bits to the MSB
*
* 3 2 1
* 10987654321098765432109876543210
@@ -12324,14 +12349,13 @@
/*
- *
+ * [DSP] RADDU.W.QB rt, rs - Unsigned reduction add of vector quad bytes
*
* 3 2 1
* 10987654321098765432109876543210
- * 001000 x1110000101
+ * 001000 1111000100111111
* rt -----
* rs -----
- * rd -----
*/
std::string NMD::RADDU_W_QB(uint64 instruction)
{
@@ -12346,14 +12370,13 @@
/*
- *
+ * [DSP] RDDSP rt, mask - Read DSPControl register fields to a GPR
*
* 3 2 1
* 10987654321098765432109876543210
- * 001000 x1110000101
+ * 001000 00011001111111
* rt -----
- * rs -----
- * rd -----
+ * mask -------
*/
std::string NMD::RDDSP(uint64 instruction)
{
@@ -12458,14 +12481,14 @@
/*
- *
+ * [DSP] REPL.PH rd, s - Replicate immediate integer into all vector element
+ * positions
*
* 3 2 1
* 10987654321098765432109876543210
- * 001000 x1110000101
+ * 001000 x0000111101
* rt -----
- * rs -----
- * rd -----
+ * s ----------
*/
std::string NMD::REPL_PH(uint64 instruction)
{
@@ -12480,14 +12503,14 @@
/*
- *
+ * [DSP] REPL.QB rd, u - Replicate immediate integer into all vector element
+ * positions
*
* 3 2 1
* 10987654321098765432109876543210
- * 001000 x1110000101
+ * 001000 x010111111111
* rt -----
- * rs -----
- * rd -----
+ * u --------
*/
std::string NMD::REPL_QB(uint64 instruction)
{
@@ -12502,14 +12525,14 @@
/*
- *
+ * [DSP] REPLV.PH rt, rs - Replicate a halfword into all vector element
+ * positions
*
* 3 2 1
* 10987654321098765432109876543210
- * 001000 x1110000101
+ * 001000 0000001100111111
* rt -----
* rs -----
- * rd -----
*/
std::string NMD::REPLV_PH(uint64 instruction)
{
@@ -12524,14 +12547,13 @@
/*
- *
+ * [DSP] REPLV.QB rt, rs - Replicate byte into all vector element positions
*
* 3 2 1
* 10987654321098765432109876543210
- * 001000 x1110000101
+ * 001000 0001001100111111
* rt -----
* rs -----
- * rd -----
*/
std::string NMD::REPLV_QB(uint64 instruction)
{
@@ -13920,8 +13942,8 @@
/*
- * SHILO ac, shift - Shift an Accumulator Value Leaving the Result in the Same
- * Accumulator
+ * [DSP] SHILO ac, shift - Shift an accumulator value leaving the result in
+ * the same accumulator
*
* 3 2 1
* 10987654321098765432109876543210
@@ -13932,7 +13954,7 @@
std::string NMD::SHILO(uint64 instruction)
{
int64 shift_value = extract_shift__se5_21_20_19_18_17_16(instruction);
- uint64 ac_value = extract_ac_13_12(instruction);
+ uint64 ac_value = extract_ac_15_14(instruction);
std::string shift = IMMEDIATE(copy(shift_value));
std::string ac = AC(copy(ac_value));
@@ -13942,8 +13964,8 @@
/*
- * SHILOV ac, rs - Variable Shift of Accumulator Value Leaving the Result in
- * the Same Accumulator
+ * [DSP] SHILOV ac, rs - Variable shift of accumulator value leaving the result
+ * in the same accumulator
*
* 3 2 1
* 10987654321098765432109876543210
@@ -13954,7 +13976,7 @@
std::string NMD::SHILOV(uint64 instruction)
{
uint64 rs_value = extract_rs_20_19_18_17_16(instruction);
- uint64 ac_value = extract_ac_13_12(instruction);
+ uint64 ac_value = extract_ac_15_14(instruction);
std::string rs = GPR(copy(rs_value));
std::string ac = AC(copy(ac_value));
@@ -13964,7 +13986,7 @@
/*
- * SHLL.PH rt, rs, sa - Shift Left Logical Vector Pair Halfwords
+ * [DSP] SHLL.PH rt, rs, sa - Shift left logical vector pair halfwords
*
* 3 2 1
* 10987654321098765432109876543210
@@ -13988,7 +14010,7 @@
/*
- * SHLL.QB rt, rs, sa - Shift Left Logical Vector Quad Bytes
+ * [DSP] SHLL.QB rt, rs, sa - Shift left logical vector quad bytes
*
* 3 2 1
* 10987654321098765432109876543210
@@ -14012,7 +14034,8 @@
/*
- * SHLL_S.PH rt, rs, sa - Shift Left Logical Vector Pair Halfwords (saturated)
+ * [DSP] SHLL_S.PH rt, rs, sa - Shift left logical vector pair halfwords
+ * with saturation
*
* 3 2 1
* 10987654321098765432109876543210
@@ -14036,14 +14059,14 @@
/*
- *
+ * [DSP] SHLL_S.PH rt, rs, sa - Shift left logical word with saturation
*
* 3 2 1
* 10987654321098765432109876543210
- * 001000 01001001101
+ * 001000 x1111110101
* rt -----
* rs -----
- * rd -----
+ * sa -----
*/
std::string NMD::SHLL_S_W(uint64 instruction)
{
@@ -14060,11 +14083,12 @@
/*
- *
+ * [DSP] SHLLV.PH rd, rt, rs - Shift left logical variable vector pair
+ * halfwords
*
* 3 2 1
* 10987654321098765432109876543210
- * 001000 01001001101
+ * 001000 01110001101
* rt -----
* rs -----
* rd -----
@@ -14084,11 +14108,11 @@
/*
- *
+ * [DSP] SHLLV_S.QB rd, rt, rs - Shift left logical variable vector quad bytes
*
* 3 2 1
* 10987654321098765432109876543210
- * 001000 01001001101
+ * 001000 x1110010101
* rt -----
* rs -----
* rd -----
@@ -14108,11 +14132,12 @@
/*
- *
+ * [DSP] SHLLV.PH rd, rt, rs - Shift left logical variable vector pair
+ * halfwords with saturation
*
* 3 2 1
* 10987654321098765432109876543210
- * 001000 01001001101
+ * 001000 11110001101
* rt -----
* rs -----
* rd -----
@@ -14132,11 +14157,11 @@
/*
- *
+ * [DSP] SHLLV_S.W rd, rt, rs - Shift left logical variable vector word
*
* 3 2 1
* 10987654321098765432109876543210
- * 001000 01001001101
+ * 001000 x1111010101
* rt -----
* rs -----
* rd -----
@@ -14396,14 +14421,14 @@
/*
- *
+ * [DSP] SHRL.PH rt, rs, sa - Shift right logical two halfwords
*
* 3 2 1
* 10987654321098765432109876543210
- * 001000 01001001101
+ * 001000 001111111111
* rt -----
* rs -----
- * rd -----
+ * sa ----
*/
std::string NMD::SHRL_PH(uint64 instruction)
{
@@ -14420,14 +14445,14 @@
/*
- *
+ * [DSP] SHRL.QB rt, rs, sa - Shift right logical vector quad bytes
*
* 3 2 1
* 10987654321098765432109876543210
- * 001000 01001001101
+ * 001000 1100001111111
* rt -----
* rs -----
- * rd -----
+ * sa ---
*/
std::string NMD::SHRL_QB(uint64 instruction)
{
@@ -14444,11 +14469,12 @@
/*
- *
+ * [DSP] SHLLV.PH rd, rt, rs - Shift right logical variable vector pair of
+ * halfwords
*
* 3 2 1
* 10987654321098765432109876543210
- * 001000 01001001101
+ * 001000 x1100010101
* rt -----
* rs -----
* rd -----
@@ -14468,11 +14494,11 @@
/*
- *
+ * [DSP] SHLLV.QB rd, rt, rs - Shift right logical variable vector quad bytes
*
* 3 2 1
* 10987654321098765432109876543210
- * 001000 01001001101
+ * 001000 x1101010101
* rt -----
* rs -----
* rd -----
@@ -15032,8 +15058,8 @@
/*
- * SUBQH.PH rd, rt, rs - Subtract Fractional Halfword Vectors And Shift Right
- * to Halve Results
+ * [DSP] SUBQ.S.PH rd, rt, rs - Subtract fractional halfword vectors and shift
+ * right to halve results
*
* 3 2 1
* 10987654321098765432109876543210
@@ -15057,8 +15083,8 @@
/*
- * SUBQH.PH rd, rt, rs - Subtract Fractional Halfword Vectors And Shift Right
- * to Halve Results
+ * [DSP] SUBQ.S.W rd, rt, rs - Subtract fractional halfword vectors and shift
+ * right to halve results
*
* 3 2 1
* 10987654321098765432109876543210
@@ -15082,8 +15108,8 @@
/*
- * SUBQH.PH rd, rt, rs - Subtract Fractional Halfword Vectors And Shift Right
- * to Halve Results
+ * [DSP] SUBQH.PH rd, rt, rs - Subtract fractional halfword vectors and shift
+ * right to halve results
*
* 3 2 1
* 10987654321098765432109876543210
@@ -15107,8 +15133,8 @@
/*
- * SUBQH.PH rd, rt, rs - Subtract Fractional Halfword Vectors And Shift Right
- * to Halve Results
+ * [DSP] SUBQH_R.PH rd, rt, rs - Subtract fractional halfword vectors and shift
+ * right to halve results
*
* 3 2 1
* 10987654321098765432109876543210
@@ -15132,8 +15158,8 @@
/*
- * SUBQH_R.PH rd, rt, rs - Subtract Fractional Halfword Vectors And Shift Right
- * to Halve Results (rounding)
+ * [DSP] SUBQH_R.W rd, rt, rs - Subtract fractional halfword vectors and shift
+ * right to halve results with rounding
*
* 3 2 1
* 10987654321098765432109876543210
@@ -15157,8 +15183,8 @@
/*
- * SUBQH.W rd, rs, rt - Subtract Fractional Words And Shift Right to Halve
- * Results
+ * [DSP] SUBQH.W rd, rs, rt - Subtract fractional words and shift right to
+ * halve results
*
* 3 2 1
* 10987654321098765432109876543210
@@ -15279,7 +15305,7 @@
/*
* [DSP] SUBU_S.PH rd, rs, rt - Subtract unsigned unsigned halfwords with
- * 8-bit saturation
+ * 8-bit saturation
*
* 3 2 1
* 10987654321098765432109876543210
@@ -15304,7 +15330,7 @@
/*
* [DSP] SUBU_S.QB rd, rs, rt - Subtract unsigned quad byte vectors with
- * 8-bit saturation
+ * 8-bit saturation
*
* 3 2 1
* 10987654321098765432109876543210
@@ -15329,7 +15355,7 @@
/*
* [DSP] SUBUH.QB rd, rs, rt - Subtract unsigned bytes and right shift
- * to halve results
+ * to halve results
*
* 3 2 1
* 10987654321098765432109876543210
@@ -15354,7 +15380,7 @@
/*
* [DSP] SUBUH_R.QB rd, rs, rt - Subtract unsigned bytes and right shift
- * to halve results with rounding
+ * to halve results with rounding
*
* 3 2 1
* 10987654321098765432109876543210
@@ -16577,6 +16603,108 @@
+/*
+ * nanoMIPS instruction pool organization
+ * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ *
+ *
+ * ┌─ P.ADDIU ─── P.RI ─── P.SYSCALL
+ * │
+ * │ ┌─ P.TRAP
+ * │ │
+ * │ ┌─ _POOL32A0_0 ─┼─ P.CMOVE
+ * │ │ │
+ * │ │ └─ P.SLTU
+ * │ ┌─ _POOL32A0 ─┤
+ * │ │ │
+ * │ │ │
+ * │ │ └─ _POOL32A0_1 ─── CRC32
+ * │ │
+ * ├─ P32A ─┤
+ * │ │ ┌─ PP.LSX
+ * │ │ ┌─ P.LSX ─────┤
+ * │ │ │ └─ PP.LSXS
+ * │ └─ _POOL32A7 ─┤
+ * │ │ ┌─ POOL32Axf_4
+ * │ └─ POOL32Axf ─┤
+ * │ └─ POOL32Axf_5
+ * │
+ * ├─ PBAL
+ * │
+ * ├─ P.GP.W ┌─ PP.LSX
+ * ┌─ P32 ─┤ │
+ * │ ├─ P.GP.BH ─┴─ PP.LSXS
+ * │ │
+ * │ ├─ P.J ─────── PP.BALRSC
+ * │ │
+ * │ ├─ P48I
+ * │ │ ┌─ P.SR
+ * │ │ │
+ * │ │ ├─ P.SHIFT
+ * │ │ │
+ * │ ├─ P.U12 ───┼─ P.ROTX
+ * │ │ │
+ * │ │ ├─ P.INS
+ * │ │ │
+ * │ │ └─ P.EXT
+ * │ │
+ * │ ├─ P.LS.U12 ── P.PREF.U12
+ * │ │
+ * │ ├─ P.BR1 ───── P.BR3A
+ * │ │
+ * │ │ ┌─ P.LS.S0 ─── P16.SYSCALL
+ * │ │ │
+ * │ │ │ ┌─ P.LL
+ * │ │ ├─ P.LS.S1 ─┤
+ * │ │ │ └─ P.SC
+ * │ │ │
+ * │ │ │ ┌─ P.PREFE
+ * MAJOR ─┤ ├─ P.LS.S9 ─┤ │
+ * │ │ ├─ P.LS.E0 ─┼─ P.LLE
+ * │ │ │ │
+ * │ │ │ └─ P.SCE
+ * │ │ │
+ * │ │ ├─ P.LS.WM
+ * │ │ │
+ * │ │ └─ P.LS.UAWM
+ * │ │
+ * │ │
+ * │ ├─ P.BR2
+ * │ │
+ * │ ├─ P.BRI
+ * │ │
+ * │ └─ P.LUI
+ * │
+ * │
+ * │ ┌─ P16.MV ──── P16.RI ─── P16.SYSCALL
+ * │ │
+ * │ ├─ P16.SR
+ * │ │
+ * │ ├─ P16.SHIFT
+ * │ │
+ * │ ├─ P16.4x4
+ * │ │
+ * │ ├─ P16C ────── POOL16C_0 ── POOL16C_00
+ * │ │
+ * └─ P16 ─┼─ P16.LB
+ * │
+ * ├─ P16.A1
+ * │
+ * ├─ P16.LH
+ * │
+ * ├─ P16.A2 ──── P.ADDIU[RS5]
+ * │
+ * ├─ P16.ADDU
+ * │
+ * └─ P16.BR ──┬─ P16.JRC
+ * │
+ * └─ P16.BR1
+ *
+ *
+ * (FP, DPS, and some minor instruction pools are omitted from the diagram)
+ *
+ */
+
NMD::Pool NMD::P_SYSCALL[2] = {
{ instruction , 0 , 0 , 32,
0xfffc0000, 0x00080000, &NMD::SYSCALL_32_ , 0,
diff --git a/disas/nanomips.h b/disas/nanomips.h
index 6482eda..243c3e3 100644
--- a/disas/nanomips.h
+++ b/disas/nanomips.h
@@ -159,7 +159,7 @@
int64 extract_s__se31_0_11_to_2_20_to_12_s12(uint64 instruction);
int64 extract_shift__se5_21_20_19_18_17_16(uint64 instruction);
- uint64 extract_ac_13_12(uint64 instruction);
+ uint64 extract_ac_15_14(uint64 instruction);
uint64 extract_bit_16_15_14_13_12_11(uint64 instruction);
uint64 extract_bit_23_22_21(uint64 instruction);
uint64 extract_c0s_20_19_18_17_16(uint64 instruction);
diff --git a/docs/COLO-FT.txt b/docs/COLO-FT.txt
index e2686bb..ad24680 100644
--- a/docs/COLO-FT.txt
+++ b/docs/COLO-FT.txt
@@ -102,7 +102,7 @@
Primary side.
COLO Proxy:
-Delivers packets to Primary and Seconday, and then compare the responses from
+Delivers packets to Primary and Secondary, and then compare the responses from
both side. Then decide whether to start a checkpoint according to some rules.
Please refer to docs/colo-proxy.txt for more information.
diff --git a/docs/amd-memory-encryption.txt b/docs/amd-memory-encryption.txt
index f483795..43bf3ee 100644
--- a/docs/amd-memory-encryption.txt
+++ b/docs/amd-memory-encryption.txt
@@ -97,7 +97,7 @@
AMD Memory Encryption whitepaper:
http://amd-dev.wpengine.netdna-cdn.com/wordpress/media/2013/12/AMD_Memory_Encryption_Whitepaper_v7-Public.pdf
-Secure Encrypted Virutualization Key Management:
+Secure Encrypted Virtualization Key Management:
[1] http://support.amd.com/TechDocs/55766_SEV-KM API_Specification.pdf
KVM Forum slides:
diff --git a/docs/can.txt b/docs/can.txt
index 7ba23b2..9fa6ed5 100644
--- a/docs/can.txt
+++ b/docs/can.txt
@@ -99,7 +99,7 @@
https://gitlab.fel.cvut.cz/canbus/qemu-canbus
(3) RTEMS page describing project
https://devel.rtems.org/wiki/Developer/Simulators/QEMU/CANEmulation
- (4) RTLWS 2015 article about the projevt and its use with CANopen emulation
+ (4) RTLWS 2015 article about the project and its use with CANopen emulation
http://rtime.felk.cvut.cz/publications/public/rtlws2015-qemu-can.pdf
Slides
http://rtime.felk.cvut.cz/publications/public/rtlws2015-qemu-can-slides.pdf
diff --git a/docs/colo-proxy.txt b/docs/colo-proxy.txt
index 1f8e4b4..fa1cef0 100644
--- a/docs/colo-proxy.txt
+++ b/docs/colo-proxy.txt
@@ -41,7 +41,7 @@
| | +------------------------------------------------------+ | | | |
|netfilter| | | | | | netfilter | | |
| +----------+ +----------------------------+ | | | +-----------------------------------------------------------+ |
-| | | | | | out | | | | | | filter excute order | |
+| | | | | | out | | | | | | filter execute order | |
| | | | +-----------------------------+ | | | | | | +-------------------> | |
| | | | | | | | | | | | | | TCP | |
| | +-----+--+-+ +-----v----+ +-----v----+ |pri +----+----+sec| | | | +------------+ +---+----+---v+rewriter++ +------------+ | |
@@ -53,7 +53,7 @@
| | | tx | rx rx | | | | | tx all | rx | |
| | | | | | | | +-----------------------------------------------------------+ |
| | | +--------------+ | | | | | |
-| | | filter excute order | | | | | | |
+| | | filter execute order | | | | | | |
| | | +----------------> | | | +--------------------------------------------------------+ |
| +-----------------------------------------+ | | |
| | | | | |
@@ -92,7 +92,7 @@
Redirect Server Filter --> COLO-Compare
COLO-compare receive primary guest packet then
-waiting scondary redirect packet to compare it.
+waiting secondary redirect packet to compare it.
If packet same,send queued primary packet and clear
queued secondary packet, Otherwise send primary packet
and do checkpoint.
diff --git a/docs/conf.py b/docs/conf.py
new file mode 100644
index 0000000..befbcc6
--- /dev/null
+++ b/docs/conf.py
@@ -0,0 +1,216 @@
+# -*- coding: utf-8 -*-
+#
+# QEMU documentation build configuration file, created by
+# sphinx-quickstart on Thu Jan 31 16:40:14 2019.
+#
+# This config file can be used in one of two ways:
+# (1) as a common config file which is included by the conf.py
+# for each of QEMU's manuals: in this case sphinx-build is run multiple
+# times, once per subdirectory.
+# (2) as a top level conf file which will result in building all
+# the manuals into a single document: in this case sphinx-build is
+# run once, on the top-level docs directory.
+#
+# QEMU's makefiles take option (1), which allows us to install
+# only the ones the user cares about (in particular we don't want
+# to ship the 'devel' manual to end-users).
+# Third-party sites such as readthedocs.org will take option (2).
+#
+#
+# This file is execfile()d with the current directory set to its
+# containing dir.
+#
+# Note that not all possible configuration values are present in this
+# autogenerated file.
+#
+# All configuration values have a default; values that are commented out
+# serve to show the default.
+
+import os
+import sys
+
+# The per-manual conf.py will set qemu_docdir for a single-manual build;
+# otherwise set it here if this is an entire-manual-set build.
+# This is always the absolute path of the docs/ directory in the source tree.
+try:
+ qemu_docdir
+except NameError:
+ qemu_docdir = os.path.abspath(".")
+
+# If extensions (or modules to document with autodoc) are in another directory,
+# add these directories to sys.path here. If the directory is relative to the
+# documentation root, use an absolute path starting from qemu_docdir.
+#
+# sys.path.insert(0, os.path.join(qemu_docdir, "my_subdir"))
+
+
+# -- General configuration ------------------------------------------------
+
+# If your documentation needs a minimal Sphinx version, state it here.
+#
+# 1.3 is where the 'alabaster' theme was shipped with Sphinx.
+needs_sphinx = '1.3'
+
+# Add any Sphinx extension module names here, as strings. They can be
+# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom
+# ones.
+extensions = []
+
+# Add any paths that contain templates here, relative to this directory.
+templates_path = ['_templates']
+
+# The suffix(es) of source filenames.
+# You can specify multiple suffix as a list of string:
+#
+# source_suffix = ['.rst', '.md']
+source_suffix = '.rst'
+
+# The master toctree document.
+master_doc = 'index'
+
+# General information about the project.
+project = u'QEMU'
+copyright = u'2019, The QEMU Project Developers'
+author = u'The QEMU Project Developers'
+
+# The version info for the project you're documenting, acts as replacement for
+# |version| and |release|, also used in various other places throughout the
+# built documents.
+
+# Extract this information from the VERSION file, for the benefit of
+# standalone Sphinx runs as used by readthedocs.org. Builds run from
+# the Makefile will pass version and release on the sphinx-build
+# command line, which override this.
+try:
+ extracted_version = None
+ with open(os.path.join(qemu_docdir, '../VERSION')) as f:
+ extracted_version = f.readline().strip()
+except:
+ pass
+finally:
+ if extracted_version:
+ version = release = extracted_version
+ else:
+ version = release = "unknown version"
+
+# The language for content autogenerated by Sphinx. Refer to documentation
+# for a list of supported languages.
+#
+# This is also used if you do content translation via gettext catalogs.
+# Usually you set "language" from the command line for these cases.
+language = None
+
+# List of patterns, relative to source directory, that match files and
+# directories to ignore when looking for source files.
+# This patterns also effect to html_static_path and html_extra_path
+exclude_patterns = ['_build', 'Thumbs.db', '.DS_Store']
+
+# The name of the Pygments (syntax highlighting) style to use.
+pygments_style = 'sphinx'
+
+# If true, `todo` and `todoList` produce output, else they produce nothing.
+todo_include_todos = False
+
+# Sphinx defaults to warning about use of :option: for options not defined
+# with "option::" in the document being processed. Turn that off.
+suppress_warnings = ["ref.option"]
+
+# -- Options for HTML output ----------------------------------------------
+
+# The theme to use for HTML and HTML Help pages. See the documentation for
+# a list of builtin themes.
+#
+html_theme = 'alabaster'
+
+# Theme options are theme-specific and customize the look and feel of a theme
+# further. For a list of options available for each theme, see the
+# documentation.
+# We initialize this to empty here, so the per-manual conf.py can just
+# add individual key/value entries.
+html_theme_options = {
+}
+
+# Add any paths that contain custom static files (such as style sheets) here,
+# relative to this directory. They are copied after the builtin static files,
+# so a file named "default.css" will overwrite the builtin "default.css".
+# QEMU doesn't yet have any static files, so comment this out so we don't
+# get a warning about a missing directory.
+# If we do ever add this then it would probably be better to call the
+# subdirectory sphinx_static, as the Linux kernel does.
+# html_static_path = ['_static']
+
+# Custom sidebar templates, must be a dictionary that maps document names
+# to template names.
+#
+# This is required for the alabaster theme
+# refs: http://alabaster.readthedocs.io/en/latest/installation.html#sidebars
+html_sidebars = {
+ '**': [
+ 'about.html',
+ 'navigation.html',
+ 'searchbox.html',
+ ]
+}
+
+# Don't copy the rST source files to the HTML output directory,
+# and don't put links to the sources into the output HTML.
+html_copy_source = False
+
+# -- Options for HTMLHelp output ------------------------------------------
+
+# Output file base name for HTML help builder.
+htmlhelp_basename = 'QEMUdoc'
+
+
+# -- Options for LaTeX output ---------------------------------------------
+
+latex_elements = {
+ # The paper size ('letterpaper' or 'a4paper').
+ #
+ # 'papersize': 'letterpaper',
+
+ # The font size ('10pt', '11pt' or '12pt').
+ #
+ # 'pointsize': '10pt',
+
+ # Additional stuff for the LaTeX preamble.
+ #
+ # 'preamble': '',
+
+ # Latex figure (float) alignment
+ #
+ # 'figure_align': 'htbp',
+}
+
+# Grouping the document tree into LaTeX files. List of tuples
+# (source start file, target name, title,
+# author, documentclass [howto, manual, or own class]).
+latex_documents = [
+ (master_doc, 'QEMU.tex', u'QEMU Documentation',
+ u'The QEMU Project Developers', 'manual'),
+]
+
+
+# -- Options for manual page output ---------------------------------------
+
+# One entry per manual page. List of tuples
+# (source start file, name, description, authors, manual section).
+man_pages = [
+ (master_doc, 'qemu', u'QEMU Documentation',
+ [author], 1)
+]
+
+
+# -- Options for Texinfo output -------------------------------------------
+
+# Grouping the document tree into Texinfo files. List of tuples
+# (source start file, target name, title, author,
+# dir menu entry, description, category)
+texinfo_documents = [
+ (master_doc, 'QEMU', u'QEMU Documentation',
+ author, 'QEMU', 'One line description of project.',
+ 'Miscellaneous'),
+]
+
+
+
diff --git a/docs/cpu-hotplug.rst b/docs/cpu-hotplug.rst
index 1c268e0..d0b0640 100644
--- a/docs/cpu-hotplug.rst
+++ b/docs/cpu-hotplug.rst
@@ -60,7 +60,7 @@
hot-plugged (no "qom-path" member). From its output in step (3), we
can see that ``IvyBridge-IBRS-x86_64-cpu`` is present in socket 0,
while hot-plugging a CPU into socket 1 requires passing the listed
- properties to QMP ``device_add``:
+ properties to QMP ``device_add``::
(QEMU) device_add id=cpu-2 driver=IvyBridge-IBRS-x86_64-cpu socket-id=1 core-id=0 thread-id=0
{
@@ -137,6 +137,6 @@
vCPU hot-unplug requires guest cooperation; so the ``device_del``
command above does not guarantee vCPU removal -- it's a "request to
unplug". At this point, the guest will get a System Control
- Interupt (SCI) and calls the ACPI handler for the affected vCPU
+ Interrupt (SCI) and calls the ACPI handler for the affected vCPU
device. Then the guest kernel will bring the vCPU offline and tell
QEMU to unplug it.
diff --git a/docs/devel/conf.py b/docs/devel/conf.py
new file mode 100644
index 0000000..7441f87
--- /dev/null
+++ b/docs/devel/conf.py
@@ -0,0 +1,15 @@
+# -*- coding: utf-8 -*-
+#
+# QEMU documentation build configuration file for the 'devel' manual.
+#
+# This includes the top level conf file and then makes any necessary tweaks.
+import sys
+import os
+
+qemu_docdir = os.path.abspath("..")
+parent_config = os.path.join(qemu_docdir, "conf.py")
+exec(compile(open(parent_config, "rb").read(), parent_config, 'exec'))
+
+# This slightly misuses the 'description', but is the best way to get
+# the manual title to appear in the sidebar.
+html_theme_options['description'] = u'Developer''s Guide'
diff --git a/docs/devel/index.rst b/docs/devel/index.rst
new file mode 100644
index 0000000..cd0fa6c
--- /dev/null
+++ b/docs/devel/index.rst
@@ -0,0 +1,21 @@
+.. This is the top level page for the 'devel' manual.
+
+
+QEMU Developer's Guide
+======================
+
+This manual documents various parts of the internals of QEMU.
+You only need to read it if you are interested in reading or
+modifying QEMU's source code.
+
+Contents:
+
+.. toctree::
+ :maxdepth: 2
+
+ loads-stores
+ memory
+ migration
+ stable-process
+ testing
+
diff --git a/docs/devel/memory.txt b/docs/devel/memory.rst
similarity index 84%
rename from docs/devel/memory.txt
rename to docs/devel/memory.rst
index 42577e1..b6a4c37 100644
--- a/docs/devel/memory.txt
+++ b/docs/devel/memory.rst
@@ -1,19 +1,20 @@
+==============
The memory API
==============
The memory API models the memory and I/O buses and controllers of a QEMU
machine. It attempts to allow modelling of:
- - ordinary RAM
- - memory-mapped I/O (MMIO)
- - memory controllers that can dynamically reroute physical memory regions
- to different destinations
+- ordinary RAM
+- memory-mapped I/O (MMIO)
+- memory controllers that can dynamically reroute physical memory regions
+ to different destinations
The memory model provides support for
- - tracking RAM changes by the guest
- - setting up coalesced memory for kvm
- - setting up ioeventfd regions for kvm
+- tracking RAM changes by the guest
+- setting up coalesced memory for kvm
+- setting up ioeventfd regions for kvm
Memory is modelled as an acyclic graph of MemoryRegion objects. Sinks
(leaves) are RAM and MMIO regions, while other nodes represent
@@ -98,25 +99,30 @@
copied to the destination on migration. These APIs which allocate
the host memory for you will also register the memory so it is
migrated:
- - memory_region_init_ram()
- - memory_region_init_rom()
- - memory_region_init_rom_device()
+
+- memory_region_init_ram()
+- memory_region_init_rom()
+- memory_region_init_rom_device()
For most devices and boards this is the correct thing. If you
have a special case where you need to manage the migration of
the backing memory yourself, you can call the functions:
- - memory_region_init_ram_nomigrate()
- - memory_region_init_rom_nomigrate()
- - memory_region_init_rom_device_nomigrate()
+
+- memory_region_init_ram_nomigrate()
+- memory_region_init_rom_nomigrate()
+- memory_region_init_rom_device_nomigrate()
+
which only initialize the MemoryRegion and leave handling
migration to the caller.
The functions:
- - memory_region_init_resizeable_ram()
- - memory_region_init_ram_from_file()
- - memory_region_init_ram_from_fd()
- - memory_region_init_ram_ptr()
- - memory_region_init_ram_device_ptr()
+
+- memory_region_init_resizeable_ram()
+- memory_region_init_ram_from_file()
+- memory_region_init_ram_from_fd()
+- memory_region_init_ram_ptr()
+- memory_region_init_ram_device_ptr()
+
are for special cases only, and so they do not automatically
register the backing memory for migration; the caller must
manage migration if necessary.
@@ -218,7 +224,7 @@
B and C. B is a container mapped at 0x2000, size 0x4000, priority 2; C is
an MMIO region mapped at 0x0, size 0x6000, priority 1. B currently has two
of its own subregions: D of size 0x1000 at offset 0 and E of size 0x1000 at
-offset 0x2000. As a diagram:
+offset 0x2000. As a diagram::
0 1000 2000 3000 4000 5000 6000 7000 8000
|------|------|------|------|------|------|------|------|
@@ -228,8 +234,9 @@
D: [DDDDD]
E: [EEEEE]
-The regions that will be seen within this address range then are:
- [CCCCCCCCCCCC][DDDDD][CCCCC][EEEEE][CCCCC]
+The regions that will be seen within this address range then are::
+
+ [CCCCCCCCCCCC][DDDDD][CCCCC][EEEEE][CCCCC]
Since B has higher priority than C, its subregions appear in the flat map
even where they overlap with C. In ranges where B has not mapped anything
@@ -237,8 +244,9 @@
If B had provided its own MMIO operations (ie it was not a pure container)
then these would be used for any addresses in its range not handled by
-D or E, and the result would be:
- [CCCCCCCCCCCC][DDDDD][BBBBB][EEEEE][BBBBB]
+D or E, and the result would be::
+
+ [CCCCCCCCCCCC][DDDDD][BBBBB][EEEEE][BBBBB]
Priority values are local to a container, because the priorities of two
regions are only compared when they are both children of the same container.
@@ -257,6 +265,7 @@
- all direct subregions of the root region are matched against the address, in
descending priority order
+
- if the address lies outside the region offset/size, the subregion is
discarded
- if the subregion is a leaf (RAM or MMIO), the search terminates, returning
@@ -270,36 +279,39 @@
address range), then if this is a container with its own MMIO or RAM
backing the search terminates, returning the container itself. Otherwise
we continue with the next subregion in priority order
+
- if none of the subregions match the address then the search terminates
with no match found
Example memory map
------------------
-system_memory: container@0-2^48-1
- |
- +---- lomem: alias@0-0xdfffffff ---> #ram (0-0xdfffffff)
- |
- +---- himem: alias@0x100000000-0x11fffffff ---> #ram (0xe0000000-0xffffffff)
- |
- +---- vga-window: alias@0xa0000-0xbffff ---> #pci (0xa0000-0xbffff)
- | (prio 1)
- |
- +---- pci-hole: alias@0xe0000000-0xffffffff ---> #pci (0xe0000000-0xffffffff)
+::
-pci (0-2^32-1)
- |
- +--- vga-area: container@0xa0000-0xbffff
- | |
- | +--- alias@0x00000-0x7fff ---> #vram (0x010000-0x017fff)
- | |
- | +--- alias@0x08000-0xffff ---> #vram (0x020000-0x027fff)
- |
- +---- vram: ram@0xe1000000-0xe1ffffff
- |
- +---- vga-mmio: mmio@0xe2000000-0xe200ffff
+ system_memory: container@0-2^48-1
+ |
+ +---- lomem: alias@0-0xdfffffff ---> #ram (0-0xdfffffff)
+ |
+ +---- himem: alias@0x100000000-0x11fffffff ---> #ram (0xe0000000-0xffffffff)
+ |
+ +---- vga-window: alias@0xa0000-0xbffff ---> #pci (0xa0000-0xbffff)
+ | (prio 1)
+ |
+ +---- pci-hole: alias@0xe0000000-0xffffffff ---> #pci (0xe0000000-0xffffffff)
-ram: ram@0x00000000-0xffffffff
+ pci (0-2^32-1)
+ |
+ +--- vga-area: container@0xa0000-0xbffff
+ | |
+ | +--- alias@0x00000-0x7fff ---> #vram (0x010000-0x017fff)
+ | |
+ | +--- alias@0x08000-0xffff ---> #vram (0x020000-0x027fff)
+ |
+ +---- vram: ram@0xe1000000-0xe1ffffff
+ |
+ +---- vga-mmio: mmio@0xe2000000-0xe200ffff
+
+ ram: ram@0x00000000-0xffffffff
This is a (simplified) PC memory map. The 4GB RAM block is mapped into the
system address space via two aliases: "lomem" is a 1:1 mapping of the first
@@ -336,16 +348,16 @@
In addition various constraints can be supplied to control how these
callbacks are called:
- - .valid.min_access_size, .valid.max_access_size define the access sizes
- (in bytes) which the device accepts; accesses outside this range will
- have device and bus specific behaviour (ignored, or machine check)
- - .valid.unaligned specifies that the *device being modelled* supports
- unaligned accesses; if false, unaligned accesses will invoke the
- appropriate bus or CPU specific behaviour.
- - .impl.min_access_size, .impl.max_access_size define the access sizes
- (in bytes) supported by the *implementation*; other access sizes will be
- emulated using the ones available. For example a 4-byte write will be
- emulated using four 1-byte writes, if .impl.max_access_size = 1.
- - .impl.unaligned specifies that the *implementation* supports unaligned
- accesses; if false, unaligned accesses will be emulated by two aligned
- accesses.
+- .valid.min_access_size, .valid.max_access_size define the access sizes
+ (in bytes) which the device accepts; accesses outside this range will
+ have device and bus specific behaviour (ignored, or machine check)
+- .valid.unaligned specifies that the *device being modelled* supports
+ unaligned accesses; if false, unaligned accesses will invoke the
+ appropriate bus or CPU specific behaviour.
+- .impl.min_access_size, .impl.max_access_size define the access sizes
+ (in bytes) supported by the *implementation*; other access sizes will be
+ emulated using the ones available. For example a 4-byte write will be
+ emulated using four 1-byte writes, if .impl.max_access_size = 1.
+- .impl.unaligned specifies that the *implementation* supports unaligned
+ accesses; if false, unaligned accesses will be emulated by two aligned
+ accesses.
diff --git a/docs/index.rst b/docs/index.rst
new file mode 100644
index 0000000..3690955
--- /dev/null
+++ b/docs/index.rst
@@ -0,0 +1,15 @@
+.. QEMU documentation master file, created by
+ sphinx-quickstart on Thu Jan 31 16:40:14 2019.
+ You can adapt this file completely to your liking, but it should at least
+ contain the root `toctree` directive.
+
+Welcome to QEMU's documentation!
+================================
+
+.. toctree::
+ :maxdepth: 2
+ :caption: Contents:
+
+ interop/index
+ devel/index
+
diff --git a/docs/interop/conf.py b/docs/interop/conf.py
new file mode 100644
index 0000000..cf3c69d
--- /dev/null
+++ b/docs/interop/conf.py
@@ -0,0 +1,15 @@
+# -*- coding: utf-8 -*-
+#
+# QEMU documentation build configuration file for the 'interop' manual.
+#
+# This includes the top level conf file and then makes any necessary tweaks.
+import sys
+import os
+
+qemu_docdir = os.path.abspath("..")
+parent_config = os.path.join(qemu_docdir, "conf.py")
+exec(compile(open(parent_config, "rb").read(), parent_config, 'exec'))
+
+# This slightly misuses the 'description', but is the best way to get
+# the manual title to appear in the sidebar.
+html_theme_options['description'] = u'System Emulation Management and Interoperability Guide'
diff --git a/docs/interop/index.rst b/docs/interop/index.rst
new file mode 100644
index 0000000..2df977d
--- /dev/null
+++ b/docs/interop/index.rst
@@ -0,0 +1,18 @@
+.. This is the top level page for the 'interop' manual.
+
+
+QEMU System Emulation Management and Interoperability Guide
+===========================================================
+
+This manual contains documents and specifications that are useful
+for making QEMU interoperate with other software.
+
+Contents:
+
+.. toctree::
+ :maxdepth: 2
+
+ bitmaps
+ live-block-operations
+ pr-helper
+
diff --git a/docs/qcow2-cache.txt b/docs/qcow2-cache.txt
index c459bf5..c1e7751 100644
--- a/docs/qcow2-cache.txt
+++ b/docs/qcow2-cache.txt
@@ -55,7 +55,7 @@
The refcount blocks
-------------------
-The qcow2 format also mantains a reference count for each cluster.
+The qcow2 format also maintains a reference count for each cluster.
Reference counts are used for cluster allocation and internal
snapshots. The data is stored in a two-level structure similar to the
L1/L2 tables described above.
diff --git a/docs/qemu-block-drivers.texi b/docs/qemu-block-drivers.texi
index 38e9f34..da06a9b 100644
--- a/docs/qemu-block-drivers.texi
+++ b/docs/qemu-block-drivers.texi
@@ -632,7 +632,7 @@
@end example
-Howto set up a simple iSCSI target on loopback and accessing it via QEMU:
+How to set up a simple iSCSI target on loopback and access it via QEMU:
@example
This example shows how to set up an iSCSI target with one CDROM and one DISK
using the Linux STGT software target. This target is available on Red Hat based
diff --git a/docs/qemu-cpu-models.texi b/docs/qemu-cpu-models.texi
index 475d434..1b72584 100644
--- a/docs/qemu-cpu-models.texi
+++ b/docs/qemu-cpu-models.texi
@@ -49,7 +49,7 @@
The information that follows provides recommendations for configuring
CPU models on x86 hosts. The goals are to maximise performance, while
protecting guest OS against various CPU hardware flaws, and optionally
-enabling live migration between hosts with hetergeneous CPU models.
+enabling live migration between hosts with heterogeneous CPU models.
@menu
* preferred_cpu_models_intel_x86:: Preferred CPU models for Intel x86 hosts
@@ -287,7 +287,7 @@
This provides higher performance than virt-ssbd so should be
exposed to guests whenever available in the host. virt-ssbd
should none the less also be exposed for maximum guest
-compatability as some kernels only know about virt-ssbd.
+compatibility as some kernels only know about virt-ssbd.
@item @code{amd-no-ssb}
@@ -296,7 +296,7 @@
Not included by default in any AMD CPU model.
-Future hardware genarations of CPU will not be vulnerable to
+Future hardware generations of CPU will not be vulnerable to
CVE-2018-3639, and thus the guest should be told not to enable
its mitigations, by exposing amd-no-ssb. This is mutually
exclusive with virt-ssbd and amd-ssbd.
@@ -451,7 +451,7 @@
@item @code{Loongson-2F}
-MIPS64 Processor (Longsoon 2, 2008)
+MIPS64 Processor (Loongson 2, 2008)
@item @code{Loongson-2E}
diff --git a/docs/rdma.txt b/docs/rdma.txt
index e6f9902..a86e992 100644
--- a/docs/rdma.txt
+++ b/docs/rdma.txt
@@ -30,7 +30,7 @@
because the RDMA I/O architecture reduces the number of interrupts and
data copies by bypassing the host networking stack. In particular, a TCP-based
migration, under certain types of memory-bound workloads, may take a more
-unpredicatable amount of time to complete the migration if the amount of
+unpredictable amount of time to complete the migration if the amount of
memory tracked during each live migration iteration round cannot keep pace
with the rate of dirty memory produced by the workload.
@@ -408,7 +408,7 @@
TODO:
=====
1. Currently, 'ulimit -l' mlock() limits as well as cgroups swap limits
- are not compatible with infinband memory pinning and will result in
+ are not compatible with infiniband memory pinning and will result in
an aborted migration (but with the source VM left unaffected).
2. Use of the recent /proc/<pid>/pagemap would likely speed up
the use of KSM and ballooning while using RDMA.
diff --git a/docs/replay.txt b/docs/replay.txt
index 3497585..ee6aee9 100644
--- a/docs/replay.txt
+++ b/docs/replay.txt
@@ -290,7 +290,7 @@
Replay log format
-----------------
-Record/replay log consits of the header and the sequence of execution
+Record/replay log consists of the header and the sequence of execution
events. The header includes 4-byte replay version id and 8-byte reserved
field. Version is updated every time replay log format changes to prevent
using replay log created by another build of qemu.
diff --git a/docs/vfio-ap.txt b/docs/vfio-ap.txt
index 1233968..b1eb2de 100644
--- a/docs/vfio-ap.txt
+++ b/docs/vfio-ap.txt
@@ -440,8 +440,7 @@
'unassign_domain' file. This may be done multiple times to unassign more than
one control domain.
-Notes: Hot plug/unplug is not currently supported for mediated AP matrix
-devices, so no changes to the AP matrix will be allowed while a guest using
+Notes: No changes to the AP matrix will be allowed while a guest using
the mediated matrix device is running. Attempts to assign an adapter,
domain or control domain will be rejected and an error (EBUSY) returned.
@@ -562,6 +561,54 @@
for guest usage, no AP devices can be made accessible to a
guest started without APFT installed.
+Hot plug a vfio-ap device into a running guest:
+==============================================
+Only one vfio-ap device can be attached to the virtual machine's ap-bus, so a
+vfio-ap device can be hot plugged if and only if no vfio-ap device is attached
+to the bus already, whether via the QEMU command line or a prior hot plug
+action.
+
+To hot plug a vfio-ap device, use the QEMU device_add command:
+
+ (qemu) device_add vfio-ap,sysfsdev="$path-to-mdev"
+
+ Where the '$path-to-mdev' value specifies the absolute path to a mediated
+ device to which AP resources to be used by the guest have been assigned.
+
+Note that on Linux guests, the AP devices will be created in the
+/sys/bus/ap/devices directory when the AP bus subsequently performs its periodic
+scan, so there may be a short delay before the AP devices are accessible on the
+guest.
+
+The command will fail if:
+
+* A vfio-ap device has already been attached to the virtual machine's ap-bus.
+
+* The CPU model features for controlling guest access to AP facilities are not
+ enabled (see 'CPU model features' subsection in the previous section).
+
+Hot unplug a vfio-ap device from a running guest:
+================================================
+A vfio-ap device can be unplugged from a running KVM guest if a vfio-ap device
+has been attached to the virtual machine's ap-bus via the QEMU command line
+or a prior hot plug action.
+
+To hot unplug a vfio-ap device, use the QEMU device_del command:
+
+ (qemu) device_del vfio-ap,sysfsdev="$path-to-mdev"
+
+ Where $path-to-mdev is the same as the path specified when the vfio-ap
+ device was attached to the virtual machine's ap-bus.
+
+On a Linux guest, the AP devices will be removed from the /sys/bus/ap/devices
+directory on the guest when the AP bus subsequently performs its periodic scan,
+so there may be a short delay before the AP devices are no longer accessible by
+the guest.
+
+The command will fail if the $path-to-mdev specified on the device_del command
+does not match the value specified when the vfio-ap device was attached to
+the virtual machine's ap-bus.
+
Example: Configure AP Matrixes for Three Linux Guests:
=====================================================
Let's now provide an example to illustrate how KVM guests may be given
@@ -624,7 +671,7 @@
-> IOMMU Hardware Support
select S390 AP IOMMU Support
-> VFIO Non-Privileged userspace driver framework
- -> Mediated device driver frramework
+ -> Mediated device driver framework
-> VFIO driver for Mediated devices
-> I/O subsystem
-> VFIO support for AP devices
@@ -819,7 +866,11 @@
assigned lest the host be given access to the private data of the AP queue
device, such as a private key configured specifically for the guest.
-* Dynamically modifying the AP matrix for a running guest (which would amount to
- hot(un)plug of AP devices for the guest) is currently not supported
+* Dynamically assigning AP resources to or unassigning AP resources from a
+ mediated matrix device - see 'Configuring an AP matrix for a linux guest'
+ section above - while a running guest is using it is currently not supported.
-* Live guest migration is not supported for guests using AP devices.
+* Live guest migration is not supported for guests using AP devices. If a guest
+ is using AP devices, the vfio-ap device configured for the guest must be
+ unplugged before migrating the guest (see 'Hot unplug a vfio-ap device from a
+ running guest' section above.
diff --git a/exec.c b/exec.c
index 5180645..1d4f378 100644
--- a/exec.c
+++ b/exec.c
@@ -1972,6 +1972,21 @@
return rb->idstr;
}
+void *qemu_ram_get_host_addr(RAMBlock *rb)
+{
+ return rb->host;
+}
+
+ram_addr_t qemu_ram_get_offset(RAMBlock *rb)
+{
+ return rb->offset;
+}
+
+ram_addr_t qemu_ram_get_used_length(RAMBlock *rb)
+{
+ return rb->used_length;
+}
+
bool qemu_ram_is_shared(RAMBlock *rb)
{
return rb->flags & RAM_SHARED;
@@ -3961,28 +3976,7 @@
rcu_read_lock();
RAMBLOCK_FOREACH(block) {
- ret = func(block->idstr, block->host, block->offset,
- block->used_length, opaque);
- if (ret) {
- break;
- }
- }
- rcu_read_unlock();
- return ret;
-}
-
-int qemu_ram_foreach_migratable_block(RAMBlockIterFunc func, void *opaque)
-{
- RAMBlock *block;
- int ret = 0;
-
- rcu_read_lock();
- RAMBLOCK_FOREACH(block) {
- if (!qemu_ram_is_migratable(block)) {
- continue;
- }
- ret = func(block->idstr, block->host, block->offset,
- block->used_length, opaque);
+ ret = func(block, opaque);
if (ret) {
break;
}
diff --git a/fpu/softfloat.c b/fpu/softfloat.c
index 9132d7a..4610738 100644
--- a/fpu/softfloat.c
+++ b/fpu/softfloat.c
@@ -696,6 +696,7 @@
static FloatParts round_canonical(FloatParts p, float_status *s,
const FloatFmt *parm)
{
+ const uint64_t frac_lsb = parm->frac_lsb;
const uint64_t frac_lsbm1 = parm->frac_lsbm1;
const uint64_t round_mask = parm->round_mask;
const uint64_t roundeven_mask = parm->roundeven_mask;
@@ -731,6 +732,10 @@
inc = p.sign ? round_mask : 0;
overflow_norm = !p.sign;
break;
+ case float_round_to_odd:
+ overflow_norm = true;
+ inc = frac & frac_lsb ? 0 : round_mask;
+ break;
default:
g_assert_not_reached();
}
@@ -778,9 +783,14 @@
shift64RightJamming(frac, 1 - exp, &frac);
if (frac & round_mask) {
/* Need to recompute round-to-even. */
- if (s->float_rounding_mode == float_round_nearest_even) {
+ switch (s->float_rounding_mode) {
+ case float_round_nearest_even:
inc = ((frac & roundeven_mask) != frac_lsbm1
? frac_lsbm1 : 0);
+ break;
+ case float_round_to_odd:
+ inc = frac & frac_lsb ? 0 : round_mask;
+ break;
}
flags |= float_flag_inexact;
frac += inc;
@@ -1988,6 +1998,9 @@
case float_round_down:
one = a.sign;
break;
+ case float_round_to_odd:
+ one = true;
+ break;
default:
g_assert_not_reached();
}
@@ -2021,6 +2034,9 @@
case float_round_down:
inc = a.sign ? rnd_mask : 0;
break;
+ case float_round_to_odd:
+ inc = a.frac & frac_lsb ? 0 : rnd_mask;
+ break;
default:
g_assert_not_reached();
}
@@ -3314,6 +3330,9 @@
case float_round_down:
roundIncrement = zSign ? 0x7f : 0;
break;
+ case float_round_to_odd:
+ roundIncrement = absZ & 0x80 ? 0 : 0x7f;
+ break;
default:
abort();
}
@@ -3368,6 +3387,9 @@
case float_round_down:
increment = zSign && absZ1;
break;
+ case float_round_to_odd:
+ increment = !(absZ0 & 1) && absZ1;
+ break;
default:
abort();
}
@@ -3424,6 +3446,9 @@
case float_round_down:
increment = zSign && absZ1;
break;
+ case float_round_to_odd:
+ increment = !(absZ0 & 1) && absZ1;
+ break;
default:
abort();
}
@@ -3526,6 +3551,9 @@
case float_round_down:
roundIncrement = zSign ? 0x7f : 0;
break;
+ case float_round_to_odd:
+ roundIncrement = zSig & 0x80 ? 0 : 0x7f;
+ break;
default:
abort();
break;
@@ -3536,8 +3564,10 @@
|| ( ( zExp == 0xFD )
&& ( (int32_t) ( zSig + roundIncrement ) < 0 ) )
) {
+ bool overflow_to_inf = roundingMode != float_round_to_odd &&
+ roundIncrement != 0;
float_raise(float_flag_overflow | float_flag_inexact, status);
- return packFloat32( zSign, 0xFF, - ( roundIncrement == 0 ));
+ return packFloat32(zSign, 0xFF, -!overflow_to_inf);
}
if ( zExp < 0 ) {
if (status->flush_to_zero) {
@@ -3555,6 +3585,13 @@
if (isTiny && roundBits) {
float_raise(float_flag_underflow, status);
}
+ if (roundingMode == float_round_to_odd) {
+ /*
+ * For round-to-odd case, the roundIncrement depends on
+ * zSig which just changed.
+ */
+ roundIncrement = zSig & 0x80 ? 0 : 0x7f;
+ }
}
}
if (roundBits) {
@@ -6793,6 +6830,35 @@
}
/*----------------------------------------------------------------------------
+| Returns the result of converting the quadruple-precision floating-point value
+| `a' to the 32-bit unsigned integer format. The conversion is
+| performed according to the IEC/IEEE Standard for Binary Floating-Point
+| Arithmetic---which means in particular that the conversion is rounded
+| according to the current rounding mode. If `a' is a NaN, the largest
+| positive integer is returned. If the conversion overflows, the
+| largest unsigned integer is returned. If 'a' is negative, the value is
+| rounded and zero is returned; negative values that do not round to zero
+| will raise the inexact exception.
+*----------------------------------------------------------------------------*/
+
+uint32_t float128_to_uint32(float128 a, float_status *status)
+{
+ uint64_t v;
+ uint32_t res;
+ int old_exc_flags = get_float_exception_flags(status);
+
+ v = float128_to_uint64(a, status);
+ if (v > 0xffffffff) {
+ res = 0xffffffff;
+ } else {
+ return v;
+ }
+ set_float_exception_flags(old_exc_flags, status);
+ float_raise(float_flag_invalid, status);
+ return res;
+}
+
+/*----------------------------------------------------------------------------
| Returns the result of converting the quadruple-precision floating-point
| value `a' to the single-precision floating-point format. The conversion
| is performed according to the IEC/IEEE Standard for Binary Floating-Point
@@ -6958,6 +7024,15 @@
add128(z.high, z.low, 0, roundBitsMask, &z.high, &z.low);
}
break;
+ case float_round_to_odd:
+ /*
+ * Note that if lastBitMask == 0, the last bit is the lsb
+ * of high, and roundBitsMask == -1.
+ */
+ if ((lastBitMask ? z.low & lastBitMask : z.high & 1) == 0) {
+ add128(z.high, z.low, 0, roundBitsMask, &z.high, &z.low);
+ }
+ break;
default:
abort();
}
@@ -6969,7 +7044,7 @@
status->float_exception_flags |= float_flag_inexact;
aSign = extractFloat128Sign( a );
switch (status->float_rounding_mode) {
- case float_round_nearest_even:
+ case float_round_nearest_even:
if ( ( aExp == 0x3FFE )
&& ( extractFloat128Frac0( a )
| extractFloat128Frac1( a ) )
@@ -6982,14 +7057,17 @@
return packFloat128(aSign, 0x3FFF, 0, 0);
}
break;
- case float_round_down:
+ case float_round_down:
return
aSign ? packFloat128( 1, 0x3FFF, 0, 0 )
: packFloat128( 0, 0, 0, 0 );
- case float_round_up:
+ case float_round_up:
return
aSign ? packFloat128( 1, 0, 0, 0 )
: packFloat128( 0, 0x3FFF, 0, 0 );
+
+ case float_round_to_odd:
+ return packFloat128(aSign, 0x3FFF, 0, 0);
}
return packFloat128( aSign, 0, 0, 0 );
}
@@ -7022,6 +7100,12 @@
z.high += roundBitsMask;
}
break;
+ case float_round_to_odd:
+ if ((z.high & lastBitMask) == 0) {
+ z.high |= (a.low != 0);
+ z.high += roundBitsMask;
+ }
+ break;
default:
abort();
}
diff --git a/hmp-commands.hx b/hmp-commands.hx
index ba71558..9b40359 100644
--- a/hmp-commands.hx
+++ b/hmp-commands.hx
@@ -350,49 +350,57 @@
{
.name = "savevm",
.args_type = "name:s?",
- .params = "[tag|id]",
- .help = "save a VM snapshot. If no tag or id are provided, a new snapshot is created",
+ .params = "tag",
+ .help = "save a VM snapshot. If no tag is provided, a new snapshot is created",
.cmd = hmp_savevm,
},
STEXI
-@item savevm [@var{tag}|@var{id}]
+@item savevm @var{tag}
@findex savevm
Create a snapshot of the whole virtual machine. If @var{tag} is
provided, it is used as human readable identifier. If there is already
-a snapshot with the same tag or ID, it is replaced. More info at
+a snapshot with the same tag, it is replaced. More info at
@ref{vm_snapshots}.
+
+Since 4.0, savevm stopped allowing the snapshot id to be set, accepting
+only @var{tag} as parameter.
ETEXI
{
.name = "loadvm",
.args_type = "name:s",
- .params = "tag|id",
- .help = "restore a VM snapshot from its tag or id",
+ .params = "tag",
+ .help = "restore a VM snapshot from its tag",
.cmd = hmp_loadvm,
.command_completion = loadvm_completion,
},
STEXI
-@item loadvm @var{tag}|@var{id}
+@item loadvm @var{tag}
@findex loadvm
Set the whole virtual machine to the snapshot identified by the tag
-@var{tag} or the unique snapshot ID @var{id}.
+@var{tag}.
+
+Since 4.0, loadvm stopped accepting snapshot id as parameter.
ETEXI
{
.name = "delvm",
.args_type = "name:s",
- .params = "tag|id",
- .help = "delete a VM snapshot from its tag or id",
+ .params = "tag",
+ .help = "delete a VM snapshot from its tag",
.cmd = hmp_delvm,
.command_completion = delvm_completion,
},
STEXI
-@item delvm @var{tag}|@var{id}
+@item delvm @var{tag}
@findex delvm
-Delete the snapshot identified by @var{tag} or @var{id}.
+Delete the snapshot identified by @var{tag}.
+
+Since 4.0, delvm stopped deleting snapshots by snapshot id, accepting
+only @var{tag} as parameter.
ETEXI
{
@@ -931,6 +939,22 @@
ETEXI
{
+ .name = "announce_self",
+ .args_type = "",
+ .params = "",
+ .help = "Trigger GARP/RARP announcements",
+ .cmd = hmp_announce_self,
+ },
+
+STEXI
+@item announce_self
+@findex announce_self
+Trigger a round of GARP/RARP broadcasts; this is useful for explicitly updating the
+network infrastructure after a reconfiguration or some forms of migration.
+The timings of the round are set by the migration announce parameters.
+ETEXI
+
+ {
.name = "migrate",
.args_type = "detach:-d,blk:-b,inc:-i,resume:-r,uri:s",
.params = "[-d] [-b] [-i] [-r] uri",
diff --git a/hmp.c b/hmp.c
index 1e006ee..c2ad3f8 100644
--- a/hmp.c
+++ b/hmp.c
@@ -166,6 +166,27 @@
qapi_free_MouseInfoList(mice_list);
}
+static char *SocketAddress_to_str(SocketAddress *addr)
+{
+ switch (addr->type) {
+ case SOCKET_ADDRESS_TYPE_INET:
+ return g_strdup_printf("tcp:%s:%s",
+ addr->u.inet.host,
+ addr->u.inet.port);
+ case SOCKET_ADDRESS_TYPE_UNIX:
+ return g_strdup_printf("unix:%s",
+ addr->u.q_unix.path);
+ case SOCKET_ADDRESS_TYPE_FD:
+ return g_strdup_printf("fd:%s", addr->u.fd.str);
+ case SOCKET_ADDRESS_TYPE_VSOCK:
+ return g_strdup_printf("tcp:%s:%s",
+ addr->u.vsock.cid,
+ addr->u.vsock.port);
+ default:
+ return g_strdup("unknown address type");
+ }
+}
+
void hmp_info_migrate(Monitor *mon, const QDict *qdict)
{
MigrationInfo *info;
@@ -306,6 +327,18 @@
g_free(str);
visit_free(v);
}
+ if (info->has_socket_address) {
+ SocketAddressList *addr;
+
+ monitor_printf(mon, "socket address: [\n");
+
+ for (addr = info->socket_address; addr; addr = addr->next) {
+ char *s = SocketAddress_to_str(addr->value);
+ monitor_printf(mon, "\t%s\n", s);
+ g_free(s);
+ }
+ monitor_printf(mon, "]\n");
+ }
qapi_free_MigrationInfo(info);
qapi_free_MigrationCapabilityStatusList(caps);
}
@@ -334,6 +367,18 @@
params = qmp_query_migrate_parameters(NULL);
if (params) {
+ monitor_printf(mon, "%s: %" PRIu64 " ms\n",
+ MigrationParameter_str(MIGRATION_PARAMETER_ANNOUNCE_INITIAL),
+ params->announce_initial);
+ monitor_printf(mon, "%s: %" PRIu64 " ms\n",
+ MigrationParameter_str(MIGRATION_PARAMETER_ANNOUNCE_MAX),
+ params->announce_max);
+ monitor_printf(mon, "%s: %" PRIu64 "\n",
+ MigrationParameter_str(MIGRATION_PARAMETER_ANNOUNCE_ROUNDS),
+ params->announce_rounds);
+ monitor_printf(mon, "%s: %" PRIu64 " ms\n",
+ MigrationParameter_str(MIGRATION_PARAMETER_ANNOUNCE_STEP),
+ params->announce_step);
assert(params->has_compress_level);
monitor_printf(mon, "%s: %u\n",
MigrationParameter_str(MIGRATION_PARAMETER_COMPRESS_LEVEL),
@@ -1558,6 +1603,11 @@
}
+void hmp_announce_self(Monitor *mon, const QDict *qdict)
+{
+ qmp_announce_self(migrate_announce_params(), NULL);
+}
+
void hmp_migrate_cancel(Monitor *mon, const QDict *qdict)
{
qmp_migrate_cancel(NULL);
@@ -1757,6 +1807,22 @@
p->has_max_postcopy_bandwidth = true;
visit_type_size(v, param, &p->max_postcopy_bandwidth, &err);
break;
+ case MIGRATION_PARAMETER_ANNOUNCE_INITIAL:
+ p->has_announce_initial = true;
+ visit_type_size(v, param, &p->announce_initial, &err);
+ break;
+ case MIGRATION_PARAMETER_ANNOUNCE_MAX:
+ p->has_announce_max = true;
+ visit_type_size(v, param, &p->announce_max, &err);
+ break;
+ case MIGRATION_PARAMETER_ANNOUNCE_ROUNDS:
+ p->has_announce_rounds = true;
+ visit_type_size(v, param, &p->announce_rounds, &err);
+ break;
+ case MIGRATION_PARAMETER_ANNOUNCE_STEP:
+ p->has_announce_step = true;
+ visit_type_size(v, param, &p->announce_step, &err);
+ break;
default:
assert(0);
}
diff --git a/hmp.h b/hmp.h
index 5f1addc..e0f32f0 100644
--- a/hmp.h
+++ b/hmp.h
@@ -46,6 +46,7 @@
void hmp_system_reset(Monitor *mon, const QDict *qdict);
void hmp_system_powerdown(Monitor *mon, const QDict *qdict);
void hmp_exit_preconfig(Monitor *mon, const QDict *qdict);
+void hmp_announce_self(Monitor *mon, const QDict *qdict);
void hmp_cpu(Monitor *mon, const QDict *qdict);
void hmp_memsave(Monitor *mon, const QDict *qdict);
void hmp_pmemsave(Monitor *mon, const QDict *qdict);
diff --git a/hw/acpi/core.c b/hw/acpi/core.c
index 47877c0..9ed1629 100644
--- a/hw/acpi/core.c
+++ b/hw/acpi/core.c
@@ -307,14 +307,6 @@
error_propagate(errp, err);
}
-static bool acpi_table_builtin = false;
-
-void acpi_table_add_builtin(const QemuOpts *opts, Error **errp)
-{
- acpi_table_builtin = true;
- acpi_table_add(opts, errp);
-}
-
unsigned acpi_table_len(void *current)
{
struct acpi_table_header *hdr = current - sizeof(hdr->_length);
@@ -330,7 +322,7 @@
uint8_t *acpi_table_first(void)
{
- if (acpi_table_builtin || !acpi_tables) {
+ if (!acpi_tables) {
return NULL;
}
return acpi_table_hdr(acpi_tables + ACPI_TABLE_PFX_SIZE);
diff --git a/hw/acpi/cpu.c b/hw/acpi/cpu.c
index a0a43fe..7a90c8f 100644
--- a/hw/acpi/cpu.c
+++ b/hw/acpi/cpu.c
@@ -126,6 +126,7 @@
dev = DEVICE(cdev->cpu);
hotplug_ctrl = qdev_get_hotplug_handler(dev);
hotplug_handler_unplug(hotplug_ctrl, dev, NULL);
+ object_unparent(OBJECT(dev));
}
break;
case ACPI_CPU_CMD_OFFSET_WR:
diff --git a/hw/acpi/memory_hotplug.c b/hw/acpi/memory_hotplug.c
index 921cad2..297812d 100644
--- a/hw/acpi/memory_hotplug.c
+++ b/hw/acpi/memory_hotplug.c
@@ -189,6 +189,7 @@
error_free(local_err);
break;
}
+ object_unparent(OBJECT(dev));
trace_mhp_acpi_pc_dimm_deleted(mem_st->selector);
}
break;
diff --git a/hw/acpi/pcihp.c b/hw/acpi/pcihp.c
index 9429181..88e4ae1 100644
--- a/hw/acpi/pcihp.c
+++ b/hw/acpi/pcihp.c
@@ -174,6 +174,7 @@
if (!acpi_pcihp_pc_no_hotplug(s, dev)) {
hotplug_ctrl = qdev_get_hotplug_handler(qdev);
hotplug_handler_unplug(hotplug_ctrl, qdev, &error_abort);
+ object_unparent(OBJECT(qdev));
}
}
}
@@ -269,7 +270,7 @@
void acpi_pcihp_device_unplug_cb(HotplugHandler *hotplug_dev, AcpiPciHpState *s,
DeviceState *dev, Error **errp)
{
- object_unparent(OBJECT(dev));
+ object_property_set_bool(OBJECT(dev), false, "realized", NULL);
}
void acpi_pcihp_device_unplug_request_cb(HotplugHandler *hotplug_dev,
diff --git a/hw/acpi/piix4.c b/hw/acpi/piix4.c
index df8c0db..8fd25a5 100644
--- a/hw/acpi/piix4.c
+++ b/hw/acpi/piix4.c
@@ -302,6 +302,11 @@
}
};
+static bool piix4_vmstate_need_smbus(void *opaque, int version_id)
+{
+ return pm_smbus_vmstate_needed();
+}
+
/* qemu-kvm 1.2 uses version 3 but advertised as 2
* To support incoming qemu-kvm 1.2 migration, change version_id
* and minimum_version_id to 2 below (which breaks migration from
@@ -321,6 +326,8 @@
VMSTATE_UINT16(ar.pm1.evt.en, PIIX4PMState),
VMSTATE_UINT16(ar.pm1.cnt.cnt, PIIX4PMState),
VMSTATE_STRUCT(apm, PIIX4PMState, 0, vmstate_apm, APMState),
+ VMSTATE_STRUCT_TEST(smb, PIIX4PMState, piix4_vmstate_need_smbus, 3,
+ pmsmb_vmstate, PMSMBus),
VMSTATE_TIMER_PTR(ar.tmr.timer, PIIX4PMState),
VMSTATE_INT64(ar.tmr.overflow_time, PIIX4PMState),
VMSTATE_STRUCT(ar.gpe, PIIX4PMState, 2, vmstate_gpe, ACPIGPE),
diff --git a/hw/arm/armsse.c b/hw/arm/armsse.c
index 129e7ea..76cc690 100644
--- a/hw/arm/armsse.c
+++ b/hw/arm/armsse.c
@@ -11,6 +11,7 @@
#include "qemu/osdep.h"
#include "qemu/log.h"
+#include "qemu/bitops.h"
#include "qapi/error.h"
#include "trace.h"
#include "hw/sysbus.h"
@@ -29,6 +30,7 @@
int sram_banks;
int num_cpus;
uint32_t sys_version;
+ uint32_t cpuwait_rst;
SysConfigFormat sys_config_format;
bool has_mhus;
bool has_ppus;
@@ -43,6 +45,7 @@
.sram_banks = 1,
.num_cpus = 1,
.sys_version = 0x41743,
+ .cpuwait_rst = 0,
.sys_config_format = IoTKitFormat,
.has_mhus = false,
.has_ppus = false,
@@ -55,6 +58,7 @@
.sram_banks = 4,
.num_cpus = 2,
.sys_version = 0x22041743,
+ .cpuwait_rst = 2,
.sys_config_format = SSE200Format,
.has_mhus = true,
.has_ppus = true,
@@ -282,9 +286,9 @@
sizeof(s->sysinfo), TYPE_IOTKIT_SYSINFO);
if (info->has_mhus) {
sysbus_init_child_obj(obj, "mhu0", &s->mhu[0], sizeof(s->mhu[0]),
- TYPE_UNIMPLEMENTED_DEVICE);
+ TYPE_ARMSSE_MHU);
sysbus_init_child_obj(obj, "mhu1", &s->mhu[1], sizeof(s->mhu[1]),
- TYPE_UNIMPLEMENTED_DEVICE);
+ TYPE_ARMSSE_MHU);
}
if (info->has_ppus) {
for (i = 0; i < info->num_cpus; i++) {
@@ -495,30 +499,33 @@
qdev_prop_set_uint32(cpudev, "num-irq", s->exp_numirq + 32);
/*
- * In real hardware the initial Secure VTOR is set from the INITSVTOR0
- * register in the IoT Kit System Control Register block, and the
- * initial value of that is in turn specifiable by the FPGA that
- * instantiates the IoT Kit. In QEMU we don't implement this wrinkle,
- * and simply set the CPU's init-svtor to the IoT Kit default value.
- * In SSE-200 the situation is similar, except that the default value
- * is a reset-time signal input. Typically a board using the SSE-200
- * will have a system control processor whose boot firmware initializes
- * the INITSVTOR* registers before powering up the CPUs in any case,
- * so the hardware's default value doesn't matter. QEMU doesn't emulate
+ * In real hardware the initial Secure VTOR is set from the INITSVTOR*
+ * registers in the IoT Kit System Control Register block. In QEMU
+ * we set the initial value here, and also the reset value of the
+ * sysctl register, from this object's QOM init-svtor property.
+ * If the guest changes the INITSVTOR* registers at runtime then the
+ * code in iotkit-sysctl.c will update the CPU init-svtor property
+ * (which will then take effect on the next CPU warm-reset).
+ *
+ * Note that typically a board using the SSE-200 will have a system
+ * control processor whose boot firmware initializes the INITSVTOR*
+ * registers before powering up the CPUs. QEMU doesn't emulate
* the control processor, so instead we behave in the way that the
- * firmware does. The initial value is configurable by the board code
- * to match whatever its firmware does.
+ * firmware does: the initial value should be set by the board code
+ * (using the init-svtor property on the ARMSSE object) to match
+ * whatever its firmware does.
*/
qdev_prop_set_uint32(cpudev, "init-svtor", s->init_svtor);
/*
- * Start all CPUs except CPU0 powered down. In real hardware it is
- * a configurable property of the SSE-200 which CPUs start powered up
- * (via the CPUWAIT0_RST and CPUWAIT1_RST parameters), but since all
- * the boards we care about start CPU0 and leave CPU1 powered off,
- * we hard-code that for now. We can add QOM properties for this
+ * CPUs start powered down if the corresponding bit in the CPUWAIT
+ * register is 1. In real hardware the CPUWAIT register reset value is
+ * a configurable property of the SSE-200 (via the CPUWAIT0_RST and
+ * CPUWAIT1_RST parameters), but since all the boards we care about
+ * start CPU0 and leave CPU1 powered off, we hard-code that in
+ * info->cpuwait_rst for now. We can add QOM properties for this
* later if necessary.
*/
- if (i > 0) {
+ if (extract32(info->cpuwait_rst, i, 1)) {
object_property_set_bool(cpuobj, true, "start-powered-off", &err);
if (err) {
error_propagate(errp, err);
@@ -766,22 +773,28 @@
}
if (info->has_mhus) {
- for (i = 0; i < ARRAY_SIZE(s->mhu); i++) {
- char *name;
- char *port;
+ /*
+ * An SSE-200 with only one CPU should have only one MHU created,
+ * with the region where the second MHU usually is being RAZ/WI.
+ * We don't implement that SSE-200 config; if we want to support
+ * it then this code needs to be enhanced to handle creating the
+ * RAZ/WI region instead of the second MHU.
+ */
+ assert(info->num_cpus == ARRAY_SIZE(s->mhu));
- name = g_strdup_printf("MHU%d", i);
- qdev_prop_set_string(DEVICE(&s->mhu[i]), "name", name);
- qdev_prop_set_uint64(DEVICE(&s->mhu[i]), "size", 0x1000);
+ for (i = 0; i < ARRAY_SIZE(s->mhu); i++) {
+ char *port;
+ int cpunum;
+ SysBusDevice *mhu_sbd = SYS_BUS_DEVICE(&s->mhu[i]);
+
object_property_set_bool(OBJECT(&s->mhu[i]), true,
"realized", &err);
- g_free(name);
if (err) {
error_propagate(errp, err);
return;
}
port = g_strdup_printf("port[%d]", i + 3);
- mr = sysbus_mmio_get_region(SYS_BUS_DEVICE(&s->mhu[i]), 0);
+ mr = sysbus_mmio_get_region(mhu_sbd, 0);
object_property_set_link(OBJECT(&s->apb_ppc0), OBJECT(mr),
port, &err);
g_free(port);
@@ -789,6 +802,20 @@
error_propagate(errp, err);
return;
}
+
+ /*
+ * Each MHU has an irq line for each CPU:
+ * MHU 0 irq line 0 -> CPU 0 IRQ 6
+ * MHU 0 irq line 1 -> CPU 1 IRQ 6
+ * MHU 1 irq line 0 -> CPU 0 IRQ 7
+ * MHU 1 irq line 1 -> CPU 1 IRQ 7
+ */
+ for (cpunum = 0; cpunum < info->num_cpus; cpunum++) {
+ DeviceState *cpudev = DEVICE(&s->armv7m[cpunum]);
+
+ sysbus_connect_irq(mhu_sbd, cpunum,
+ qdev_get_gpio_in(cpudev, 6 + i));
+ }
}
}
@@ -977,6 +1004,14 @@
/* System information registers */
sysbus_mmio_map(SYS_BUS_DEVICE(&s->sysinfo), 0, 0x40020000);
/* System control registers */
+ object_property_set_int(OBJECT(&s->sysctl), info->sys_version,
+ "SYS_VERSION", &err);
+ object_property_set_int(OBJECT(&s->sysctl), info->cpuwait_rst,
+ "CPUWAIT_RST", &err);
+ object_property_set_int(OBJECT(&s->sysctl), s->init_svtor,
+ "INITSVTOR0_RST", &err);
+ object_property_set_int(OBJECT(&s->sysctl), s->init_svtor,
+ "INITSVTOR1_RST", &err);
object_property_set_bool(OBJECT(&s->sysctl), true, "realized", &err);
if (err) {
error_propagate(errp, err);
diff --git a/hw/arm/aspeed.c b/hw/arm/aspeed.c
index 5158985..9968124 100644
--- a/hw/arm/aspeed.c
+++ b/hw/arm/aspeed.c
@@ -18,7 +18,7 @@
#include "hw/arm/aspeed.h"
#include "hw/arm/aspeed_soc.h"
#include "hw/boards.h"
-#include "hw/i2c/smbus.h"
+#include "hw/i2c/smbus_eeprom.h"
#include "qemu/log.h"
#include "sysemu/block-backend.h"
#include "hw/loader.h"
diff --git a/hw/arm/boot.c b/hw/arm/boot.c
index d90af2f..a830655 100644
--- a/hw/arm/boot.c
+++ b/hw/arm/boot.c
@@ -423,6 +423,32 @@
}
}
+static int fdt_add_memory_node(void *fdt, uint32_t acells, hwaddr mem_base,
+ uint32_t scells, hwaddr mem_len,
+ int numa_node_id)
+{
+ char *nodename;
+ int ret;
+
+ nodename = g_strdup_printf("/memory@%" PRIx64, mem_base);
+ qemu_fdt_add_subnode(fdt, nodename);
+ qemu_fdt_setprop_string(fdt, nodename, "device_type", "memory");
+ ret = qemu_fdt_setprop_sized_cells(fdt, nodename, "reg", acells, mem_base,
+ scells, mem_len);
+ if (ret < 0) {
+ goto out;
+ }
+
+ /* only set the NUMA ID if it is specified */
+ if (numa_node_id >= 0) {
+ ret = qemu_fdt_setprop_cell(fdt, nodename,
+ "numa-node-id", numa_node_id);
+ }
+out:
+ g_free(nodename);
+ return ret;
+}
+
static void fdt_add_psci_node(void *fdt)
{
uint32_t cpu_suspend_fn;
@@ -502,7 +528,6 @@
void *fdt = NULL;
int size, rc, n = 0;
uint32_t acells, scells;
- char *nodename;
unsigned int i;
hwaddr mem_base, mem_len;
char **node_path;
@@ -576,35 +601,24 @@
mem_base = binfo->loader_start;
for (i = 0; i < nb_numa_nodes; i++) {
mem_len = numa_info[i].node_mem;
- nodename = g_strdup_printf("/memory@%" PRIx64, mem_base);
- qemu_fdt_add_subnode(fdt, nodename);
- qemu_fdt_setprop_string(fdt, nodename, "device_type", "memory");
- rc = qemu_fdt_setprop_sized_cells(fdt, nodename, "reg",
- acells, mem_base,
- scells, mem_len);
+ rc = fdt_add_memory_node(fdt, acells, mem_base,
+ scells, mem_len, i);
if (rc < 0) {
- fprintf(stderr, "couldn't set %s/reg for node %d\n", nodename,
- i);
+ fprintf(stderr, "couldn't add /memory@%"PRIx64" node\n",
+ mem_base);
goto fail;
}
- qemu_fdt_setprop_cell(fdt, nodename, "numa-node-id", i);
mem_base += mem_len;
- g_free(nodename);
}
} else {
- nodename = g_strdup_printf("/memory@%" PRIx64, binfo->loader_start);
- qemu_fdt_add_subnode(fdt, nodename);
- qemu_fdt_setprop_string(fdt, nodename, "device_type", "memory");
-
- rc = qemu_fdt_setprop_sized_cells(fdt, nodename, "reg",
- acells, binfo->loader_start,
- scells, binfo->ram_size);
+ rc = fdt_add_memory_node(fdt, acells, binfo->loader_start,
+ scells, binfo->ram_size, -1);
if (rc < 0) {
- fprintf(stderr, "couldn't set %s reg\n", nodename);
+ fprintf(stderr, "couldn't add /memory@%"PRIx64" node\n",
+ binfo->loader_start);
goto fail;
}
- g_free(nodename);
}
rc = fdt_path_offset(fdt, "/chosen");
diff --git a/hw/arm/pxa2xx.c b/hw/arm/pxa2xx.c
index f598a1c..3d7c889 100644
--- a/hw/arm/pxa2xx.c
+++ b/hw/arm/pxa2xx.c
@@ -1286,7 +1286,7 @@
return 0;
}
-static int pxa2xx_i2c_rx(I2CSlave *i2c)
+static uint8_t pxa2xx_i2c_rx(I2CSlave *i2c)
{
PXA2xxI2CSlaveState *slave = PXA2XX_I2C_SLAVE(i2c);
PXA2xxI2CState *s = slave->host;
diff --git a/hw/arm/stellaris.c b/hw/arm/stellaris.c
index 442529c..05f8674 100644
--- a/hw/arm/stellaris.c
+++ b/hw/arm/stellaris.c
@@ -22,6 +22,7 @@
#include "sysemu/sysemu.h"
#include "hw/arm/armv7m.h"
#include "hw/char/pl011.h"
+#include "hw/watchdog/cmsdk-apb-watchdog.h"
#include "hw/misc/unimp.h"
#include "cpu.h"
@@ -811,7 +812,7 @@
/* TODO: Handle errors. */
if (s->msa & 1) {
/* Recv */
- s->mdr = i2c_recv(s->bus) & 0xff;
+ s->mdr = i2c_recv(s->bus);
} else {
/* Send */
i2c_send(s->bus, s->mdr);
@@ -1243,7 +1244,7 @@
* Stellaris LM3S6965 Microcontroller Data Sheet (rev I)
* http://www.ti.com/lit/ds/symlink/lm3s6965.pdf
*
- * 40000000 wdtimer (unimplemented)
+ * 40000000 wdtimer
* 40002000 i2c (unimplemented)
* 40004000 GPIO
* 40005000 GPIO
@@ -1338,6 +1339,24 @@
stellaris_sys_init(0x400fe000, qdev_get_gpio_in(nvic, 28),
board, nd_table[0].macaddr.a);
+
+ if (board->dc1 & (1 << 3)) { /* watchdog present */
+ dev = qdev_create(NULL, TYPE_LUMINARY_WATCHDOG);
+
+ /* system_clock_scale is valid now */
+ uint32_t mainclk = NANOSECONDS_PER_SECOND / system_clock_scale;
+ qdev_prop_set_uint32(dev, "wdogclk-frq", mainclk);
+
+ qdev_init_nofail(dev);
+ sysbus_mmio_map(SYS_BUS_DEVICE(dev),
+ 0,
+ 0x40000000u);
+ sysbus_connect_irq(SYS_BUS_DEVICE(dev),
+ 0,
+ qdev_get_gpio_in(nvic, 18));
+ }
+
+
for (i = 0; i < 7; i++) {
if (board->dc4 & (1 << i)) {
gpio_dev[i] = sysbus_create_simple("pl061_luminary", gpio_addr[i],
@@ -1431,7 +1450,6 @@
/* Add dummy regions for the devices we don't implement yet,
* so guest accesses don't cause unlogged crashes.
*/
- create_unimplemented_device("wdtimer", 0x40000000, 0x1000);
create_unimplemented_device("i2c-0", 0x40002000, 0x1000);
create_unimplemented_device("i2c-2", 0x40021000, 0x1000);
create_unimplemented_device("PWM", 0x40028000, 0x1000);
diff --git a/hw/arm/tosa.c b/hw/arm/tosa.c
index 7a925fa..eef9d42 100644
--- a/hw/arm/tosa.c
+++ b/hw/arm/tosa.c
@@ -197,10 +197,10 @@
return 0;
}
-static int tosa_dac_recv(I2CSlave *s)
+static uint8_t tosa_dac_recv(I2CSlave *s)
{
printf("%s: recv not supported!!!\n", __func__);
- return -1;
+ return 0xff;
}
static void tosa_tg_init(PXA2xxState *cpu)
diff --git a/hw/arm/virt-acpi-build.c b/hw/arm/virt-acpi-build.c
index 04b62c7..d7e2e48 100644
--- a/hw/arm/virt-acpi-build.c
+++ b/hw/arm/virt-acpi-build.c
@@ -229,8 +229,8 @@
size_pio));
if (use_highmem) {
- hwaddr base_mmio_high = memmap[VIRT_PCIE_MMIO_HIGH].base;
- hwaddr size_mmio_high = memmap[VIRT_PCIE_MMIO_HIGH].size;
+ hwaddr base_mmio_high = memmap[VIRT_HIGH_PCIE_MMIO].base;
+ hwaddr size_mmio_high = memmap[VIRT_HIGH_PCIE_MMIO].size;
aml_append(rbuf,
aml_qword_memory(AML_POS_DECODE, AML_MIN_FIXED, AML_MAX_FIXED,
@@ -663,8 +663,10 @@
gicr = acpi_data_push(table_data, sizeof(*gicr));
gicr->type = ACPI_APIC_GENERIC_REDISTRIBUTOR;
gicr->length = sizeof(*gicr);
- gicr->base_address = cpu_to_le64(memmap[VIRT_GIC_REDIST2].base);
- gicr->range_length = cpu_to_le32(memmap[VIRT_GIC_REDIST2].size);
+ gicr->base_address =
+ cpu_to_le64(memmap[VIRT_HIGH_GIC_REDIST2].base);
+ gicr->range_length =
+ cpu_to_le32(memmap[VIRT_HIGH_GIC_REDIST2].size);
}
if (its_class_name() && !vmc->no_its) {
diff --git a/hw/arm/virt.c b/hw/arm/virt.c
index 99c2b6e..c7fb534 100644
--- a/hw/arm/virt.c
+++ b/hw/arm/virt.c
@@ -29,6 +29,7 @@
*/
#include "qemu/osdep.h"
+#include "qemu/units.h"
#include "qapi/error.h"
#include "hw/sysbus.h"
#include "hw/arm/arm.h"
@@ -58,6 +59,8 @@
#include "qapi/visitor.h"
#include "standard-headers/linux/input.h"
#include "hw/arm/smmuv3.h"
+#include "hw/acpi/acpi.h"
+#include "target/arm/internals.h"
#define DEFINE_VIRT_MACHINE_LATEST(major, minor, latest) \
static void virt_##major##_##minor##_class_init(ObjectClass *oc, \
@@ -92,22 +95,9 @@
#define PLATFORM_BUS_NUM_IRQS 64
-/* RAM limit in GB. Since VIRT_MEM starts at the 1GB mark, this means
- * RAM can go up to the 256GB mark, leaving 256GB of the physical
- * address space unallocated and free for future use between 256G and 512G.
- * If we need to provide more RAM to VMs in the future then we need to:
- * * allocate a second bank of RAM starting at 2TB and working up
- * * fix the DT and ACPI table generation code in QEMU to correctly
- * report two split lumps of RAM to the guest
- * * fix KVM in the host kernel to allow guests with >40 bit address spaces
- * (We don't want to fill all the way up to 512GB with RAM because
- * we might want it for non-RAM purposes later. Conversely it seems
- * reasonable to assume that anybody configuring a VM with a quarter
- * of a terabyte of RAM will be doing it on a host with more than a
- * terabyte of physical address space.)
- */
-#define RAMLIMIT_GB 255
-#define RAMLIMIT_BYTES (RAMLIMIT_GB * 1024ULL * 1024 * 1024)
+/* Legacy RAM limit in GB (< version 4.0) */
+#define LEGACY_RAMLIMIT_GB 255
+#define LEGACY_RAMLIMIT_BYTES (LEGACY_RAMLIMIT_GB * GiB)
/* Addresses and sizes of our components.
* 0..128MB is space for a flash device so we can run bootrom code such as UEFI.
@@ -121,7 +111,7 @@
* Note that devices should generally be placed at multiples of 0x10000,
* to accommodate guests using 64K pages.
*/
-static const MemMapEntry a15memmap[] = {
+static const MemMapEntry base_memmap[] = {
/* Space up to 0x8000000 is reserved for a boot ROM */
[VIRT_FLASH] = { 0, 0x08000000 },
[VIRT_CPUPERIPHS] = { 0x08000000, 0x00020000 },
@@ -148,12 +138,26 @@
[VIRT_PCIE_MMIO] = { 0x10000000, 0x2eff0000 },
[VIRT_PCIE_PIO] = { 0x3eff0000, 0x00010000 },
[VIRT_PCIE_ECAM] = { 0x3f000000, 0x01000000 },
- [VIRT_MEM] = { 0x40000000, RAMLIMIT_BYTES },
+ /* Actual RAM size depends on initial RAM and device memory settings */
+ [VIRT_MEM] = { GiB, LEGACY_RAMLIMIT_BYTES },
+};
+
+/*
+ * Highmem IO Regions: This memory map is floating, located after the RAM.
+ * Each MemMapEntry base (GPA) will be dynamically computed, depending on the
+ * top of the RAM, so that its base get the same alignment as the size,
+ * ie. a 512GiB entry will be aligned on a 512GiB boundary. If there is
+ * less than 256GiB of RAM, the floating area starts at the 256GiB mark.
+ * Note the extended_memmap is sized so that it eventually also includes the
+ * base_memmap entries (VIRT_HIGH_GIC_REDIST2 index is greater than the last
+ * index of base_memmap).
+ */
+static MemMapEntry extended_memmap[] = {
/* Additional 64 MB redist region (can contain up to 512 redistributors) */
- [VIRT_GIC_REDIST2] = { 0x4000000000ULL, 0x4000000 },
- [VIRT_PCIE_ECAM_HIGH] = { 0x4010000000ULL, 0x10000000 },
- /* Second PCIe window, 512GB wide at the 512GB boundary */
- [VIRT_PCIE_MMIO_HIGH] = { 0x8000000000ULL, 0x8000000000ULL },
+ [VIRT_HIGH_GIC_REDIST2] = { 0x0, 64 * MiB },
+ [VIRT_HIGH_PCIE_ECAM] = { 0x0, 256 * MiB },
+ /* Second PCIe window */
+ [VIRT_HIGH_PCIE_MMIO] = { 0x0, 512 * GiB },
};
static const int a15irqmap[] = {
@@ -431,12 +435,12 @@
2, vms->memmap[VIRT_GIC_REDIST].size);
} else {
qemu_fdt_setprop_sized_cells(vms->fdt, nodename, "reg",
- 2, vms->memmap[VIRT_GIC_DIST].base,
- 2, vms->memmap[VIRT_GIC_DIST].size,
- 2, vms->memmap[VIRT_GIC_REDIST].base,
- 2, vms->memmap[VIRT_GIC_REDIST].size,
- 2, vms->memmap[VIRT_GIC_REDIST2].base,
- 2, vms->memmap[VIRT_GIC_REDIST2].size);
+ 2, vms->memmap[VIRT_GIC_DIST].base,
+ 2, vms->memmap[VIRT_GIC_DIST].size,
+ 2, vms->memmap[VIRT_GIC_REDIST].base,
+ 2, vms->memmap[VIRT_GIC_REDIST].size,
+ 2, vms->memmap[VIRT_HIGH_GIC_REDIST2].base,
+ 2, vms->memmap[VIRT_HIGH_GIC_REDIST2].size);
}
if (vms->virt) {
@@ -584,7 +588,7 @@
if (nb_redist_regions == 2) {
uint32_t redist1_capacity =
- vms->memmap[VIRT_GIC_REDIST2].size / GICV3_REDIST_SIZE;
+ vms->memmap[VIRT_HIGH_GIC_REDIST2].size / GICV3_REDIST_SIZE;
qdev_prop_set_uint32(gicdev, "redist-region-count[1]",
MIN(smp_cpus - redist0_count, redist1_capacity));
@@ -601,7 +605,8 @@
if (type == 3) {
sysbus_mmio_map(gicbusdev, 1, vms->memmap[VIRT_GIC_REDIST].base);
if (nb_redist_regions == 2) {
- sysbus_mmio_map(gicbusdev, 2, vms->memmap[VIRT_GIC_REDIST2].base);
+ sysbus_mmio_map(gicbusdev, 2,
+ vms->memmap[VIRT_HIGH_GIC_REDIST2].base);
}
} else {
sysbus_mmio_map(gicbusdev, 1, vms->memmap[VIRT_GIC_CPU].base);
@@ -1088,8 +1093,8 @@
{
hwaddr base_mmio = vms->memmap[VIRT_PCIE_MMIO].base;
hwaddr size_mmio = vms->memmap[VIRT_PCIE_MMIO].size;
- hwaddr base_mmio_high = vms->memmap[VIRT_PCIE_MMIO_HIGH].base;
- hwaddr size_mmio_high = vms->memmap[VIRT_PCIE_MMIO_HIGH].size;
+ hwaddr base_mmio_high = vms->memmap[VIRT_HIGH_PCIE_MMIO].base;
+ hwaddr size_mmio_high = vms->memmap[VIRT_HIGH_PCIE_MMIO].size;
hwaddr base_pio = vms->memmap[VIRT_PCIE_PIO].base;
hwaddr size_pio = vms->memmap[VIRT_PCIE_PIO].size;
hwaddr base_ecam, size_ecam;
@@ -1353,6 +1358,62 @@
return arm_cpu_mp_affinity(idx, clustersz);
}
+static void virt_set_memmap(VirtMachineState *vms)
+{
+ MachineState *ms = MACHINE(vms);
+ hwaddr base, device_memory_base, device_memory_size;
+ int i;
+
+ vms->memmap = extended_memmap;
+
+ for (i = 0; i < ARRAY_SIZE(base_memmap); i++) {
+ vms->memmap[i] = base_memmap[i];
+ }
+
+ if (ms->ram_slots > ACPI_MAX_RAM_SLOTS) {
+ error_report("unsupported number of memory slots: %"PRIu64,
+ ms->ram_slots);
+ exit(EXIT_FAILURE);
+ }
+
+ /*
+ * We compute the base of the high IO region depending on the
+ * amount of initial and device memory. The device memory start/size
+ * is aligned on 1GiB. We never put the high IO region below 256GiB
+ * so that if maxram_size is < 255GiB we keep the legacy memory map.
+ * The device region size assumes 1GiB page max alignment per slot.
+ */
+ device_memory_base =
+ ROUND_UP(vms->memmap[VIRT_MEM].base + ms->ram_size, GiB);
+ device_memory_size = ms->maxram_size - ms->ram_size + ms->ram_slots * GiB;
+
+ /* Base address of the high IO region */
+ base = device_memory_base + ROUND_UP(device_memory_size, GiB);
+ if (base < device_memory_base) {
+ error_report("maxmem/slots too huge");
+ exit(EXIT_FAILURE);
+ }
+ if (base < vms->memmap[VIRT_MEM].base + LEGACY_RAMLIMIT_BYTES) {
+ base = vms->memmap[VIRT_MEM].base + LEGACY_RAMLIMIT_BYTES;
+ }
+
+ for (i = VIRT_LOWMEMMAP_LAST; i < ARRAY_SIZE(extended_memmap); i++) {
+ hwaddr size = extended_memmap[i].size;
+
+ base = ROUND_UP(base, size);
+ vms->memmap[i].base = base;
+ vms->memmap[i].size = size;
+ base += size;
+ }
+ vms->highest_gpa = base - 1;
+ if (device_memory_size > 0) {
+ ms->device_memory = g_malloc0(sizeof(*ms->device_memory));
+ ms->device_memory->base = device_memory_base;
+ memory_region_init(&ms->device_memory->mr, OBJECT(vms),
+ "device-memory", device_memory_size);
+ }
+}
+
static void machvirt_init(MachineState *machine)
{
VirtMachineState *vms = VIRT_MACHINE(machine);
@@ -1367,6 +1428,14 @@
bool firmware_loaded = bios_name || drive_get(IF_PFLASH, 0, 0);
bool aarch64 = true;
+ /*
+ * In accelerated mode, the memory map is computed earlier in kvm_type()
+ * to create a VM with the right number of IPA bits.
+ */
+ if (!vms->memmap) {
+ virt_set_memmap(vms);
+ }
+
/* We can probe only here because during property set
* KVM is not available yet
*/
@@ -1417,8 +1486,10 @@
* many redistributors we can fit into the memory map.
*/
if (vms->gic_version == 3) {
- virt_max_cpus = vms->memmap[VIRT_GIC_REDIST].size / GICV3_REDIST_SIZE;
- virt_max_cpus += vms->memmap[VIRT_GIC_REDIST2].size / GICV3_REDIST_SIZE;
+ virt_max_cpus =
+ vms->memmap[VIRT_GIC_REDIST].size / GICV3_REDIST_SIZE;
+ virt_max_cpus +=
+ vms->memmap[VIRT_HIGH_GIC_REDIST2].size / GICV3_REDIST_SIZE;
} else {
virt_max_cpus = GIC_NCPU;
}
@@ -1432,11 +1503,6 @@
vms->smp_cpus = smp_cpus;
- if (machine->ram_size > vms->memmap[VIRT_MEM].size) {
- error_report("mach-virt: cannot model more than %dGB RAM", RAMLIMIT_GB);
- exit(1);
- }
-
if (vms->virt && kvm_enabled()) {
error_report("mach-virt: KVM does not support providing "
"Virtualization extensions to the guest CPU");
@@ -1524,9 +1590,29 @@
fdt_add_timer_nodes(vms);
fdt_add_cpu_nodes(vms);
+ if (!kvm_enabled()) {
+ ARMCPU *cpu = ARM_CPU(first_cpu);
+ bool aarch64 = object_property_get_bool(OBJECT(cpu), "aarch64", NULL);
+
+ if (aarch64 && vms->highmem) {
+ int requested_pa_size, pamax = arm_pamax(cpu);
+
+ requested_pa_size = 64 - clz64(vms->highest_gpa);
+ if (pamax < requested_pa_size) {
+ error_report("VCPU supports less PA bits (%d) than requested "
+ "by the memory map (%d)", pamax, requested_pa_size);
+ exit(1);
+ }
+ }
+ }
+
memory_region_allocate_system_memory(ram, NULL, "mach-virt.ram",
machine->ram_size);
memory_region_add_subregion(sysmem, vms->memmap[VIRT_MEM].base, ram);
+ if (machine->device_memory) {
+ memory_region_add_subregion(sysmem, machine->device_memory->base,
+ &machine->device_memory->mr);
+ }
create_flash(vms, sysmem, secure_sysmem ? secure_sysmem : sysmem);
@@ -1747,6 +1833,36 @@
return NULL;
}
+/*
+ * for arm64 kvm_type [7-0] encodes the requested number of bits
+ * in the IPA address space
+ */
+static int virt_kvm_type(MachineState *ms, const char *type_str)
+{
+ VirtMachineState *vms = VIRT_MACHINE(ms);
+ int max_vm_pa_size = kvm_arm_get_max_vm_ipa_size(ms);
+ int requested_pa_size;
+
+ /* we freeze the memory map to compute the highest gpa */
+ virt_set_memmap(vms);
+
+ requested_pa_size = 64 - clz64(vms->highest_gpa);
+
+ if (requested_pa_size > max_vm_pa_size) {
+ error_report("-m and ,maxmem option values "
+ "require an IPA range (%d bits) larger than "
+ "the one supported by the host (%d bits)",
+ requested_pa_size, max_vm_pa_size);
+ exit(1);
+ }
+ /*
+ * By default we return 0 which corresponds to an implicit legacy
+ * 40b IPA setting. Otherwise we return the actual requested PA
+ * logsize
+ */
+ return requested_pa_size > 40 ? requested_pa_size : 0;
+}
+
static void virt_machine_class_init(ObjectClass *oc, void *data)
{
MachineClass *mc = MACHINE_CLASS(oc);
@@ -1771,6 +1887,7 @@
mc->cpu_index_to_instance_props = virt_cpu_index_to_props;
mc->default_cpu_type = ARM_CPU_TYPE_NAME("cortex-a15");
mc->get_default_cpu_node_id = virt_get_default_cpu_node_id;
+ mc->kvm_type = virt_kvm_type;
assert(!mc->get_hotplug_handler);
mc->get_hotplug_handler = virt_machine_get_hotplug_handler;
hc->plug = virt_machine_device_plug_cb;
@@ -1842,7 +1959,6 @@
"Valid values are none and smmuv3",
NULL);
- vms->memmap = a15memmap;
vms->irqmap = a15irqmap;
}
diff --git a/hw/arm/z2.c b/hw/arm/z2.c
index 697a822..6f18d92 100644
--- a/hw/arm/z2.c
+++ b/hw/arm/z2.c
@@ -243,7 +243,7 @@
return 0;
}
-static int aer915_recv(I2CSlave *slave)
+static uint8_t aer915_recv(I2CSlave *slave)
{
AER915State *s = AER915(slave);
int retval = 0x00;
diff --git a/hw/audio/wm8750.c b/hw/audio/wm8750.c
index f4aa838..169b006 100644
--- a/hw/audio/wm8750.c
+++ b/hw/audio/wm8750.c
@@ -561,7 +561,7 @@
return 0;
}
-static int wm8750_rx(I2CSlave *i2c)
+static uint8_t wm8750_rx(I2CSlave *i2c)
{
return 0x00;
}
diff --git a/hw/block/dataplane/xen-block.c b/hw/block/dataplane/xen-block.c
index c6a15da..f1523c5 100644
--- a/hw/block/dataplane/xen-block.c
+++ b/hw/block/dataplane/xen-block.c
@@ -281,10 +281,6 @@
break;
case BLKIF_OP_WRITE:
case BLKIF_OP_FLUSH_DISKCACHE:
- if (!request->req.nr_segments) {
- break;
- }
- break;
default:
break;
}
@@ -298,6 +294,7 @@
if (!request->req.nr_segments) {
break;
}
+ /* fall through */
case BLKIF_OP_READ:
if (request->status == BLKIF_RSP_OKAY) {
block_acct_done(blk_get_stats(dataplane->blk), &request->acct);
diff --git a/hw/block/pflash_cfi02.c b/hw/block/pflash_cfi02.c
index 0f8b7b8..1588aef 100644
--- a/hw/block/pflash_cfi02.c
+++ b/hw/block/pflash_cfi02.c
@@ -84,7 +84,7 @@
uint16_t unlock_addr0;
uint16_t unlock_addr1;
uint8_t cfi_table[0x52];
- QEMUTimer *timer;
+ QEMUTimer timer;
/* The device replicates the flash memory across its memory space. Emulate
* that by having a container (.mem) filled with an array of aliases
* (.mem_mappings) pointing to the flash memory (.orig_mem).
@@ -429,7 +429,7 @@
}
pfl->status = 0x00;
/* Let's wait 5 seconds before chip erase is done */
- timer_mod(pfl->timer, qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) +
+ timer_mod(&pfl->timer, qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) +
(NANOSECONDS_PER_SECOND * 5));
break;
case 0x30:
@@ -444,7 +444,7 @@
}
pfl->status = 0x00;
/* Let's wait 1/2 second before sector erase is done */
- timer_mod(pfl->timer, qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) +
+ timer_mod(&pfl->timer, qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) +
(NANOSECONDS_PER_SECOND / 2));
break;
default:
@@ -596,7 +596,7 @@
pfl->rom_mode = 1;
sysbus_init_mmio(SYS_BUS_DEVICE(dev), &pfl->mem);
- pfl->timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, pflash_timer, pfl);
+ timer_init_ns(&pfl->timer, QEMU_CLOCK_VIRTUAL, pflash_timer, pfl);
pfl->wcycle = 0;
pfl->cmd = 0;
pfl->status = 0;
@@ -695,11 +695,18 @@
DEFINE_PROP_END_OF_LIST(),
};
+static void pflash_cfi02_unrealize(DeviceState *dev, Error **errp)
+{
+ pflash_t *pfl = CFI_PFLASH02(dev);
+ timer_del(&pfl->timer);
+}
+
static void pflash_cfi02_class_init(ObjectClass *klass, void *data)
{
DeviceClass *dc = DEVICE_CLASS(klass);
dc->realize = pflash_cfi02_realize;
+ dc->unrealize = pflash_cfi02_unrealize;
dc->props = pflash_cfi02_properties;
set_bit(DEVICE_CATEGORY_STORAGE, dc->categories);
}
diff --git a/hw/block/virtio-blk.c b/hw/block/virtio-blk.c
index cf7f47e..0cc3c59 100644
--- a/hw/block/virtio-blk.c
+++ b/hw/block/virtio-blk.c
@@ -28,9 +28,28 @@
#include "hw/virtio/virtio-bus.h"
#include "hw/virtio/virtio-access.h"
-/* We don't support discard yet, hide associated config fields. */
+/* Config size before the discard support (hide associated config fields) */
#define VIRTIO_BLK_CFG_SIZE offsetof(struct virtio_blk_config, \
max_discard_sectors)
+/*
+ * Starting from the discard feature, we can use this array to properly
+ * set the config size depending on the features enabled.
+ */
+static VirtIOFeature feature_sizes[] = {
+ {.flags = 1ULL << VIRTIO_BLK_F_DISCARD,
+ .end = virtio_endof(struct virtio_blk_config, discard_sector_alignment)},
+ {.flags = 1ULL << VIRTIO_BLK_F_WRITE_ZEROES,
+ .end = virtio_endof(struct virtio_blk_config, write_zeroes_may_unmap)},
+ {}
+};
+
+static void virtio_blk_set_config_size(VirtIOBlock *s, uint64_t host_features)
+{
+ s->config_size = MAX(VIRTIO_BLK_CFG_SIZE,
+ virtio_feature_get_config_size(feature_sizes, host_features));
+
+ assert(s->config_size <= sizeof(struct virtio_blk_config));
+}
static void virtio_blk_init_request(VirtIOBlock *s, VirtQueue *vq,
VirtIOBlockReq *req)
@@ -65,7 +84,7 @@
}
static int virtio_blk_handle_rw_error(VirtIOBlockReq *req, int error,
- bool is_read)
+ bool is_read, bool acct_failed)
{
VirtIOBlock *s = req->dev;
BlockErrorAction action = blk_get_error_action(s->blk, is_read, error);
@@ -78,7 +97,9 @@
s->rq = req;
} else if (action == BLOCK_ERROR_ACTION_REPORT) {
virtio_blk_req_complete(req, VIRTIO_BLK_S_IOERR);
- block_acct_failed(blk_get_stats(s->blk), &req->acct);
+ if (acct_failed) {
+ block_acct_failed(blk_get_stats(s->blk), &req->acct);
+ }
virtio_blk_free_request(req);
}
@@ -116,7 +137,7 @@
* the memory until the request is completed (which will
* happen on the other side of the migration).
*/
- if (virtio_blk_handle_rw_error(req, -ret, is_read)) {
+ if (virtio_blk_handle_rw_error(req, -ret, is_read, true)) {
continue;
}
}
@@ -135,7 +156,7 @@
aio_context_acquire(blk_get_aio_context(s->conf.conf.blk));
if (ret) {
- if (virtio_blk_handle_rw_error(req, -ret, 0)) {
+ if (virtio_blk_handle_rw_error(req, -ret, 0, true)) {
goto out;
}
}
@@ -148,6 +169,30 @@
aio_context_release(blk_get_aio_context(s->conf.conf.blk));
}
+static void virtio_blk_discard_write_zeroes_complete(void *opaque, int ret)
+{
+ VirtIOBlockReq *req = opaque;
+ VirtIOBlock *s = req->dev;
+ bool is_write_zeroes = (virtio_ldl_p(VIRTIO_DEVICE(s), &req->out.type) &
+ ~VIRTIO_BLK_T_BARRIER) == VIRTIO_BLK_T_WRITE_ZEROES;
+
+ aio_context_acquire(blk_get_aio_context(s->conf.conf.blk));
+ if (ret) {
+ if (virtio_blk_handle_rw_error(req, -ret, false, is_write_zeroes)) {
+ goto out;
+ }
+ }
+
+ virtio_blk_req_complete(req, VIRTIO_BLK_S_OK);
+ if (is_write_zeroes) {
+ block_acct_done(blk_get_stats(s->blk), &req->acct);
+ }
+ virtio_blk_free_request(req);
+
+out:
+ aio_context_release(blk_get_aio_context(s->conf.conf.blk));
+}
+
#ifdef __linux__
typedef struct {
@@ -243,7 +288,7 @@
*/
scsi = (void *)elem->in_sg[elem->in_num - 2].iov_base;
- if (!blk->conf.scsi) {
+ if (!virtio_has_feature(blk->host_features, VIRTIO_BLK_F_SCSI)) {
status = VIRTIO_BLK_S_UNSUPP;
goto fail;
}
@@ -481,6 +526,84 @@
return true;
}
+static uint8_t virtio_blk_handle_discard_write_zeroes(VirtIOBlockReq *req,
+ struct virtio_blk_discard_write_zeroes *dwz_hdr, bool is_write_zeroes)
+{
+ VirtIOBlock *s = req->dev;
+ VirtIODevice *vdev = VIRTIO_DEVICE(s);
+ uint64_t sector;
+ uint32_t num_sectors, flags, max_sectors;
+ uint8_t err_status;
+ int bytes;
+
+ sector = virtio_ldq_p(vdev, &dwz_hdr->sector);
+ num_sectors = virtio_ldl_p(vdev, &dwz_hdr->num_sectors);
+ flags = virtio_ldl_p(vdev, &dwz_hdr->flags);
+ max_sectors = is_write_zeroes ? s->conf.max_write_zeroes_sectors :
+ s->conf.max_discard_sectors;
+
+ /*
+ * max_sectors is at most BDRV_REQUEST_MAX_SECTORS, this check
+ * make us sure that "num_sectors << BDRV_SECTOR_BITS" can fit in
+ * the integer variable.
+ */
+ if (unlikely(num_sectors > max_sectors)) {
+ err_status = VIRTIO_BLK_S_IOERR;
+ goto err;
+ }
+
+ bytes = num_sectors << BDRV_SECTOR_BITS;
+
+ if (unlikely(!virtio_blk_sect_range_ok(s, sector, bytes))) {
+ err_status = VIRTIO_BLK_S_IOERR;
+ goto err;
+ }
+
+ /*
+ * The device MUST set the status byte to VIRTIO_BLK_S_UNSUPP for discard
+ * and write zeroes commands if any unknown flag is set.
+ */
+ if (unlikely(flags & ~VIRTIO_BLK_WRITE_ZEROES_FLAG_UNMAP)) {
+ err_status = VIRTIO_BLK_S_UNSUPP;
+ goto err;
+ }
+
+ if (is_write_zeroes) { /* VIRTIO_BLK_T_WRITE_ZEROES */
+ int blk_aio_flags = 0;
+
+ if (flags & VIRTIO_BLK_WRITE_ZEROES_FLAG_UNMAP) {
+ blk_aio_flags |= BDRV_REQ_MAY_UNMAP;
+ }
+
+ block_acct_start(blk_get_stats(s->blk), &req->acct, bytes,
+ BLOCK_ACCT_WRITE);
+
+ blk_aio_pwrite_zeroes(s->blk, sector << BDRV_SECTOR_BITS,
+ bytes, blk_aio_flags,
+ virtio_blk_discard_write_zeroes_complete, req);
+ } else { /* VIRTIO_BLK_T_DISCARD */
+ /*
+ * The device MUST set the status byte to VIRTIO_BLK_S_UNSUPP for
+ * discard commands if the unmap flag is set.
+ */
+ if (unlikely(flags & VIRTIO_BLK_WRITE_ZEROES_FLAG_UNMAP)) {
+ err_status = VIRTIO_BLK_S_UNSUPP;
+ goto err;
+ }
+
+ blk_aio_pdiscard(s->blk, sector << BDRV_SECTOR_BITS, bytes,
+ virtio_blk_discard_write_zeroes_complete, req);
+ }
+
+ return VIRTIO_BLK_S_OK;
+
+err:
+ if (is_write_zeroes) {
+ block_acct_invalid(blk_get_stats(s->blk), BLOCK_ACCT_WRITE);
+ }
+ return err_status;
+}
+
static int virtio_blk_handle_request(VirtIOBlockReq *req, MultiReqBuffer *mrb)
{
uint32_t type;
@@ -582,6 +705,47 @@
virtio_blk_free_request(req);
break;
}
+ /*
+ * VIRTIO_BLK_T_DISCARD and VIRTIO_BLK_T_WRITE_ZEROES are defined with
+ * VIRTIO_BLK_T_OUT flag set. We masked this flag in the switch statement,
+ * so we must mask it for these requests, then we will check if it is set.
+ */
+ case VIRTIO_BLK_T_DISCARD & ~VIRTIO_BLK_T_OUT:
+ case VIRTIO_BLK_T_WRITE_ZEROES & ~VIRTIO_BLK_T_OUT:
+ {
+ struct virtio_blk_discard_write_zeroes dwz_hdr;
+ size_t out_len = iov_size(out_iov, out_num);
+ bool is_write_zeroes = (type & ~VIRTIO_BLK_T_BARRIER) ==
+ VIRTIO_BLK_T_WRITE_ZEROES;
+ uint8_t err_status;
+
+ /*
+ * Unsupported if VIRTIO_BLK_T_OUT is not set or the request contains
+ * more than one segment.
+ */
+ if (unlikely(!(type & VIRTIO_BLK_T_OUT) ||
+ out_len > sizeof(dwz_hdr))) {
+ virtio_blk_req_complete(req, VIRTIO_BLK_S_UNSUPP);
+ virtio_blk_free_request(req);
+ return 0;
+ }
+
+ if (unlikely(iov_to_buf(out_iov, out_num, 0, &dwz_hdr,
+ sizeof(dwz_hdr)) != sizeof(dwz_hdr))) {
+ virtio_error(vdev, "virtio-blk discard/write_zeroes header"
+ " too short");
+ return -1;
+ }
+
+ err_status = virtio_blk_handle_discard_write_zeroes(req, &dwz_hdr,
+ is_write_zeroes);
+ if (err_status != VIRTIO_BLK_S_OK) {
+ virtio_blk_req_complete(req, err_status);
+ virtio_blk_free_request(req);
+ }
+
+ break;
+ }
default:
virtio_blk_req_complete(req, VIRTIO_BLK_S_UNSUPP);
virtio_blk_free_request(req);
@@ -675,6 +839,7 @@
if (mrb.num_reqs) {
virtio_blk_submit_multireq(s->blk, &mrb);
}
+ blk_dec_in_flight(s->conf.conf.blk);
aio_context_release(blk_get_aio_context(s->conf.conf.blk));
}
@@ -688,8 +853,11 @@
}
if (!s->bh) {
+ /* FIXME The data plane is not started yet, so these requests are
+ * processed in the main thread. */
s->bh = aio_bh_new(blk_get_aio_context(s->conf.conf.blk),
virtio_blk_dma_restart_bh, s);
+ blk_inc_in_flight(s->conf.conf.blk);
qemu_bh_schedule(s->bh);
}
}
@@ -761,8 +929,25 @@
blkcfg.alignment_offset = 0;
blkcfg.wce = blk_enable_write_cache(s->blk);
virtio_stw_p(vdev, &blkcfg.num_queues, s->conf.num_queues);
- memcpy(config, &blkcfg, VIRTIO_BLK_CFG_SIZE);
- QEMU_BUILD_BUG_ON(VIRTIO_BLK_CFG_SIZE > sizeof(blkcfg));
+ if (virtio_has_feature(s->host_features, VIRTIO_BLK_F_DISCARD)) {
+ virtio_stl_p(vdev, &blkcfg.max_discard_sectors,
+ s->conf.max_discard_sectors);
+ virtio_stl_p(vdev, &blkcfg.discard_sector_alignment,
+ blk_size >> BDRV_SECTOR_BITS);
+ /*
+ * We support only one segment per request since multiple segments
+ * are not widely used and there are no userspace APIs that allow
+ * applications to submit multiple segments in a single call.
+ */
+ virtio_stl_p(vdev, &blkcfg.max_discard_seg, 1);
+ }
+ if (virtio_has_feature(s->host_features, VIRTIO_BLK_F_WRITE_ZEROES)) {
+ virtio_stl_p(vdev, &blkcfg.max_write_zeroes_sectors,
+ s->conf.max_write_zeroes_sectors);
+ blkcfg.write_zeroes_may_unmap = 1;
+ virtio_stl_p(vdev, &blkcfg.max_write_zeroes_seg, 1);
+ }
+ memcpy(config, &blkcfg, s->config_size);
}
static void virtio_blk_set_config(VirtIODevice *vdev, const uint8_t *config)
@@ -770,8 +955,7 @@
VirtIOBlock *s = VIRTIO_BLK(vdev);
struct virtio_blk_config blkcfg;
- memcpy(&blkcfg, config, VIRTIO_BLK_CFG_SIZE);
- QEMU_BUILD_BUG_ON(VIRTIO_BLK_CFG_SIZE > sizeof(blkcfg));
+ memcpy(&blkcfg, config, s->config_size);
aio_context_acquire(blk_get_aio_context(s->blk));
blk_set_enable_write_cache(s->blk, blkcfg.wce != 0);
@@ -783,12 +967,15 @@
{
VirtIOBlock *s = VIRTIO_BLK(vdev);
+ /* Firstly sync all virtio-blk possible supported features */
+ features |= s->host_features;
+
virtio_add_feature(&features, VIRTIO_BLK_F_SEG_MAX);
virtio_add_feature(&features, VIRTIO_BLK_F_GEOMETRY);
virtio_add_feature(&features, VIRTIO_BLK_F_TOPOLOGY);
virtio_add_feature(&features, VIRTIO_BLK_F_BLK_SIZE);
if (virtio_has_feature(features, VIRTIO_F_VERSION_1)) {
- if (s->conf.scsi) {
+ if (virtio_has_feature(s->host_features, VIRTIO_BLK_F_SCSI)) {
error_setg(errp, "Please set scsi=off for virtio-blk devices in order to use virtio 1.0");
return 0;
}
@@ -797,9 +984,6 @@
virtio_add_feature(&features, VIRTIO_BLK_F_SCSI);
}
- if (s->conf.config_wce) {
- virtio_add_feature(&features, VIRTIO_BLK_F_CONFIG_WCE);
- }
if (blk_enable_write_cache(s->blk)) {
virtio_add_feature(&features, VIRTIO_BLK_F_WCE);
}
@@ -954,7 +1138,28 @@
return;
}
- virtio_init(vdev, "virtio-blk", VIRTIO_ID_BLOCK, VIRTIO_BLK_CFG_SIZE);
+ if (virtio_has_feature(s->host_features, VIRTIO_BLK_F_DISCARD) &&
+ (!conf->max_discard_sectors ||
+ conf->max_discard_sectors > BDRV_REQUEST_MAX_SECTORS)) {
+ error_setg(errp, "invalid max-discard-sectors property (%" PRIu32 ")"
+ ", must be between 1 and %d",
+ conf->max_discard_sectors, (int)BDRV_REQUEST_MAX_SECTORS);
+ return;
+ }
+
+ if (virtio_has_feature(s->host_features, VIRTIO_BLK_F_WRITE_ZEROES) &&
+ (!conf->max_write_zeroes_sectors ||
+ conf->max_write_zeroes_sectors > BDRV_REQUEST_MAX_SECTORS)) {
+ error_setg(errp, "invalid max-write-zeroes-sectors property (%" PRIu32
+ "), must be between 1 and %d",
+ conf->max_write_zeroes_sectors,
+ (int)BDRV_REQUEST_MAX_SECTORS);
+ return;
+ }
+
+ virtio_blk_set_config_size(s, s->host_features);
+
+ virtio_init(vdev, "virtio-blk", VIRTIO_ID_BLOCK, s->config_size);
s->blk = conf->conf.blk;
s->rq = NULL;
@@ -1013,9 +1218,11 @@
DEFINE_BLOCK_ERROR_PROPERTIES(VirtIOBlock, conf.conf),
DEFINE_BLOCK_CHS_PROPERTIES(VirtIOBlock, conf.conf),
DEFINE_PROP_STRING("serial", VirtIOBlock, conf.serial),
- DEFINE_PROP_BIT("config-wce", VirtIOBlock, conf.config_wce, 0, true),
+ DEFINE_PROP_BIT64("config-wce", VirtIOBlock, host_features,
+ VIRTIO_BLK_F_CONFIG_WCE, true),
#ifdef __linux__
- DEFINE_PROP_BIT("scsi", VirtIOBlock, conf.scsi, 0, false),
+ DEFINE_PROP_BIT64("scsi", VirtIOBlock, host_features,
+ VIRTIO_BLK_F_SCSI, false),
#endif
DEFINE_PROP_BIT("request-merging", VirtIOBlock, conf.request_merging, 0,
true),
@@ -1023,6 +1230,14 @@
DEFINE_PROP_UINT16("queue-size", VirtIOBlock, conf.queue_size, 128),
DEFINE_PROP_LINK("iothread", VirtIOBlock, conf.iothread, TYPE_IOTHREAD,
IOThread *),
+ DEFINE_PROP_BIT64("discard", VirtIOBlock, host_features,
+ VIRTIO_BLK_F_DISCARD, true),
+ DEFINE_PROP_BIT64("write-zeroes", VirtIOBlock, host_features,
+ VIRTIO_BLK_F_WRITE_ZEROES, true),
+ DEFINE_PROP_UINT32("max-discard-sectors", VirtIOBlock,
+ conf.max_discard_sectors, BDRV_REQUEST_MAX_SECTORS),
+ DEFINE_PROP_UINT32("max-write-zeroes-sectors", VirtIOBlock,
+ conf.max_write_zeroes_sectors, BDRV_REQUEST_MAX_SECTORS),
DEFINE_PROP_END_OF_LIST(),
};
diff --git a/hw/block/xen-block.c b/hw/block/xen-block.c
index 5012af9..70fc245 100644
--- a/hw/block/xen-block.c
+++ b/hw/block/xen-block.c
@@ -351,21 +351,28 @@
g_free(str);
}
-static unsigned int vbd_name_to_disk(const char *name, const char **endp)
+static int vbd_name_to_disk(const char *name, const char **endp,
+ unsigned long *disk)
{
- unsigned int disk = 0;
+ unsigned int n = 0;
while (*name != '\0') {
if (!g_ascii_isalpha(*name) || !g_ascii_islower(*name)) {
break;
}
- disk *= 26;
- disk += *name++ - 'a' + 1;
+ n *= 26;
+ n += *name++ - 'a' + 1;
}
*endp = name;
- return disk - 1;
+ if (!n) {
+ return -1;
+ }
+
+ *disk = n - 1;
+
+ return 0;
}
static void xen_block_set_vdev(Object *obj, Visitor *v, const char *name,
@@ -413,13 +420,14 @@
}
if (*end == 'p') {
- p = (char *) ++end;
- if (*end == '\0') {
+ if (*(++end) == '\0') {
goto invalid;
}
}
} else {
- vdev->disk = vbd_name_to_disk(p, &end);
+ if (vbd_name_to_disk(p, &end, &vdev->disk)) {
+ goto invalid;
+ }
}
if (*end != '\0') {
@@ -735,12 +743,12 @@
}
g_strfreev(v);
- }
-
- if (!filename) {
- error_setg(errp, "no filename");
+ } else {
+ error_setg(errp, "no params");
goto done;
}
+
+ assert(filename);
assert(driver);
drive = g_new0(XenBlockDrive, 1);
@@ -750,6 +758,7 @@
qdict_put_str(file_layer, "driver", "file");
qdict_put_str(file_layer, "filename", filename);
+ g_free(filename);
if (mode && *mode != 'w') {
qdict_put_bool(file_layer, "read-only", true);
@@ -785,16 +794,17 @@
driver_layer = qdict_new();
qdict_put_str(driver_layer, "driver", driver);
+ g_free(driver);
+
qdict_put_obj(driver_layer, "file", QOBJECT(file_layer));
g_assert(!drive->node_name);
drive->node_name = xen_block_blockdev_add(drive->id, driver_layer,
&local_err);
-done:
- g_free(driver);
- g_free(filename);
+ qobject_unref(driver_layer);
+done:
if (local_err) {
error_propagate(errp, local_err);
xen_block_drive_destroy(drive, NULL);
diff --git a/hw/core/machine.c b/hw/core/machine.c
index 077fbd1..766ca58 100644
--- a/hw/core/machine.c
+++ b/hw/core/machine.c
@@ -33,6 +33,8 @@
{ "usb-kbd", "serial", "42" },
{ "usb-mouse", "serial", "42" },
{ "usb-kbd", "serial", "42" },
+ { "virtio-blk-device", "discard", "false" },
+ { "virtio-blk-device", "write-zeroes", "false" },
};
const size_t hw_compat_3_1_len = G_N_ELEMENTS(hw_compat_3_1);
diff --git a/hw/core/qdev.c b/hw/core/qdev.c
index d59071b..512ce7c 100644
--- a/hw/core/qdev.c
+++ b/hw/core/qdev.c
@@ -59,6 +59,8 @@
snprintf(name, sizeof(name), "child[%d]", kid->index);
QTAILQ_REMOVE(&bus->children, kid, sibling);
+ bus->num_children--;
+
/* This gives back ownership of kid->child back to us. */
object_property_del(OBJECT(bus), name, NULL);
object_unref(OBJECT(kid->child));
@@ -73,6 +75,7 @@
char name[32];
BusChild *kid = g_malloc0(sizeof(*kid));
+ bus->num_children++;
kid->index = bus->max_index++;
kid->child = child;
object_ref(OBJECT(kid->child));
@@ -233,14 +236,20 @@
return NULL;
}
+HotplugHandler *qdev_get_bus_hotplug_handler(DeviceState *dev)
+{
+ if (dev->parent_bus) {
+ return dev->parent_bus->hotplug_handler;
+ }
+ return NULL;
+}
+
HotplugHandler *qdev_get_hotplug_handler(DeviceState *dev)
{
- HotplugHandler *hotplug_ctrl;
+ HotplugHandler *hotplug_ctrl = qdev_get_machine_hotplug_handler(dev);
- if (dev->parent_bus && dev->parent_bus->hotplug_handler) {
- hotplug_ctrl = dev->parent_bus->hotplug_handler;
- } else {
- hotplug_ctrl = qdev_get_machine_hotplug_handler(dev);
+ if (hotplug_ctrl == NULL && dev->parent_bus) {
+ hotplug_ctrl = qdev_get_bus_hotplug_handler(dev);
}
return hotplug_ctrl;
}
@@ -286,8 +295,7 @@
void qdev_simple_device_unplug_cb(HotplugHandler *hotplug_dev,
DeviceState *dev, Error **errp)
{
- /* just zap it */
- object_unparent(OBJECT(dev));
+ object_property_set_bool(OBJECT(dev), false, "realized", NULL);
}
/*
diff --git a/hw/display/qxl.c b/hw/display/qxl.c
index da8fd5a..c8ce578 100644
--- a/hw/display/qxl.c
+++ b/hw/display/qxl.c
@@ -276,7 +276,8 @@
QXL_COOKIE_TYPE_POST_LOAD_MONITORS_CONFIG,
0));
} else {
-#if SPICE_SERVER_VERSION >= 0x000c06 /* release 0.12.6 */
+/* >= release 0.12.6, < release 0.14.2 */
+#if SPICE_SERVER_VERSION >= 0x000c06 && SPICE_SERVER_VERSION < 0x000e02
if (qxl->max_outputs) {
spice_qxl_set_max_monitors(&qxl->ssd.qxl, qxl->max_outputs);
}
@@ -2188,6 +2189,17 @@
SPICE_INTERFACE_QXL_MAJOR, SPICE_INTERFACE_QXL_MINOR);
return;
}
+
+#if SPICE_SERVER_VERSION >= 0x000e02 /* release 0.14.2 */
+ char device_address[256] = "";
+ if (qemu_spice_fill_device_address(qxl->vga.con, device_address, 256)) {
+ spice_qxl_set_device_info(&qxl->ssd.qxl,
+ device_address,
+ 0,
+ qxl->max_outputs);
+ }
+#endif
+
qemu_add_vm_change_state_handler(qxl_vm_change_state_handler, qxl);
qxl->update_irq = qemu_bh_new(qxl_update_irq_bh, qxl);
diff --git a/hw/display/sii9022.c b/hw/display/sii9022.c
index eaf11a6..9994385 100644
--- a/hw/display/sii9022.c
+++ b/hw/display/sii9022.c
@@ -79,7 +79,7 @@
return 0;
}
-static int sii9022_rx(I2CSlave *i2c)
+static uint8_t sii9022_rx(I2CSlave *i2c)
{
sii9022_state *s = SII9022(i2c);
uint8_t res = 0x00;
diff --git a/hw/display/ssd0303.c b/hw/display/ssd0303.c
index eb90ba2..8edf349 100644
--- a/hw/display/ssd0303.c
+++ b/hw/display/ssd0303.c
@@ -62,10 +62,10 @@
uint8_t framebuffer[132*8];
} ssd0303_state;
-static int ssd0303_recv(I2CSlave *i2c)
+static uint8_t ssd0303_recv(I2CSlave *i2c)
{
BADF("Reads not implemented\n");
- return -1;
+ return 0xff;
}
static int ssd0303_send(I2CSlave *i2c, uint8_t data)
diff --git a/hw/display/trace-events b/hw/display/trace-events
index 387c6b8..37d3264 100644
--- a/hw/display/trace-events
+++ b/hw/display/trace-events
@@ -35,6 +35,7 @@
# hw/display/virtio-gpu.c
virtio_gpu_features(bool virgl) "virgl %d"
virtio_gpu_cmd_get_display_info(void) ""
+virtio_gpu_cmd_get_edid(uint32_t scanout) "scanout %d"
virtio_gpu_cmd_set_scanout(uint32_t id, uint32_t res, uint32_t w, uint32_t h, uint32_t x, uint32_t y) "id %d, res 0x%x, w %d, h %d, x %d, y %d"
virtio_gpu_cmd_res_create_2d(uint32_t res, uint32_t fmt, uint32_t w, uint32_t h) "res 0x%x, fmt 0x%x, w %d, h %d"
virtio_gpu_cmd_res_create_3d(uint32_t res, uint32_t fmt, uint32_t w, uint32_t h, uint32_t d) "res 0x%x, fmt 0x%x, w %d, h %d, d %d"
diff --git a/hw/display/virtio-gpu-3d.c b/hw/display/virtio-gpu-3d.c
index bc6e99c..2d30252 100644
--- a/hw/display/virtio-gpu-3d.c
+++ b/hw/display/virtio-gpu-3d.c
@@ -404,11 +404,6 @@
{
VIRTIO_GPU_FILL_CMD(cmd->cmd_hdr);
- cmd->waiting = g->renderer_blocked;
- if (cmd->waiting) {
- return;
- }
-
virgl_renderer_force_ctx_0();
switch (cmd->cmd_hdr.type) {
case VIRTIO_GPU_CMD_CTX_CREATE:
@@ -468,6 +463,9 @@
case VIRTIO_GPU_CMD_GET_DISPLAY_INFO:
virtio_gpu_get_display_info(g, cmd);
break;
+ case VIRTIO_GPU_CMD_GET_EDID:
+ virtio_gpu_get_edid(g, cmd);
+ break;
default:
cmd->error = VIRTIO_GPU_RESP_ERR_UNSPEC;
break;
@@ -604,22 +602,6 @@
}
}
-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) {
- virtio_gpu_process_cmdq(g);
- }
-}
-
int virtio_gpu_virgl_init(VirtIOGPU *g)
{
int ret;
diff --git a/hw/display/virtio-gpu.c b/hw/display/virtio-gpu.c
index c6fab56..a3627f5 100644
--- a/hw/display/virtio-gpu.c
+++ b/hw/display/virtio-gpu.c
@@ -21,6 +21,7 @@
#include "hw/virtio/virtio.h"
#include "hw/virtio/virtio-gpu.h"
#include "hw/virtio/virtio-bus.h"
+#include "hw/display/edid.h"
#include "migration/blocker.h"
#include "qemu/log.h"
#include "qapi/error.h"
@@ -207,6 +208,9 @@
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;
}
@@ -301,6 +305,40 @@
sizeof(display_info));
}
+static void
+virtio_gpu_generate_edid(VirtIOGPU *g, int scanout,
+ struct virtio_gpu_resp_edid *edid)
+{
+ qemu_edid_info info = {
+ .prefx = g->req_state[scanout].width,
+ .prefy = g->req_state[scanout].height,
+ };
+
+ edid->size = cpu_to_le32(sizeof(edid->edid));
+ qemu_edid_generate(edid->edid, sizeof(edid->edid), &info);
+}
+
+void virtio_gpu_get_edid(VirtIOGPU *g,
+ struct virtio_gpu_ctrl_command *cmd)
+{
+ struct virtio_gpu_resp_edid edid;
+ struct virtio_gpu_cmd_get_edid get_edid;
+
+ VIRTIO_GPU_FILL_CMD(get_edid);
+ virtio_gpu_bswap_32(&get_edid, sizeof(get_edid));
+
+ if (get_edid.scanout >= g->conf.max_outputs) {
+ cmd->error = VIRTIO_GPU_RESP_ERR_INVALID_PARAMETER;
+ return;
+ }
+
+ trace_virtio_gpu_cmd_get_edid(get_edid.scanout);
+ memset(&edid, 0, sizeof(edid));
+ edid.hdr.type = VIRTIO_GPU_RESP_OK_EDID;
+ virtio_gpu_generate_edid(g, get_edid.scanout, &edid);
+ 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) {
@@ -839,6 +877,9 @@
case VIRTIO_GPU_CMD_GET_DISPLAY_INFO:
virtio_gpu_get_display_info(g, cmd);
break;
+ case VIRTIO_GPU_CMD_GET_EDID:
+ virtio_gpu_get_edid(g, cmd);
+ break;
case VIRTIO_GPU_CMD_RESOURCE_CREATE_2D:
virtio_gpu_resource_create_2d(g, cmd);
break;
@@ -889,12 +930,14 @@
while (!QTAILQ_EMPTY(&g->cmdq)) {
cmd = QTAILQ_FIRST(&g->cmdq);
+ if (g->renderer_blocked) {
+ break;
+ }
+
/* process command */
VIRGL(g, virtio_gpu_virgl_process_cmd, virtio_gpu_simple_process_cmd,
g, cmd);
- if (cmd->waiting) {
- break;
- }
+
QTAILQ_REMOVE(&g->cmdq, cmd, next);
if (virtio_gpu_stats_enabled(g->conf)) {
g->stats.requests++;
@@ -936,7 +979,6 @@
cmd->vq = vq;
cmd->error = 0;
cmd->finished = false;
- cmd->waiting = false;
QTAILQ_INSERT_TAIL(&g->cmdq, cmd, next);
cmd = virtqueue_pop(vq, sizeof(struct virtio_gpu_ctrl_command));
}
@@ -1030,14 +1072,28 @@
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) {
+ 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,
-#ifdef CONFIG_VIRGL
.gl_block = virtio_gpu_gl_block,
-#endif
};
static const VMStateDescription vmstate_virtio_gpu_scanout = {
@@ -1238,10 +1294,9 @@
}
}
- g->config_size = sizeof(struct virtio_gpu_config);
g->virtio_config.num_scanouts = cpu_to_le32(g->conf.max_outputs);
virtio_init(VIRTIO_DEVICE(g), "virtio-gpu", VIRTIO_ID_GPU,
- g->config_size);
+ sizeof(struct virtio_gpu_config));
g->req_state[0].width = g->conf.xres;
g->req_state[0].height = g->conf.yres;
@@ -1268,7 +1323,6 @@
QTAILQ_INIT(&g->fenceq);
g->enabled_output_bitmask = 1;
- g->qdev = qdev;
for (i = 0; i < g->conf.max_outputs; i++) {
g->scanout[i].con =
@@ -1356,6 +1410,8 @@
DEFINE_PROP_BIT("stats", VirtIOGPU, 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(),
diff --git a/hw/gpio/max7310.c b/hw/gpio/max7310.c
index 1a2478b..c6f686c 100644
--- a/hw/gpio/max7310.c
+++ b/hw/gpio/max7310.c
@@ -39,7 +39,7 @@
s->command = 0x00;
}
-static int max7310_rx(I2CSlave *i2c)
+static uint8_t max7310_rx(I2CSlave *i2c)
{
MAX7310State *s = MAX7310(i2c);
diff --git a/hw/i2c/Makefile.objs b/hw/i2c/Makefile.objs
index cecee48..9205cbe 100644
--- a/hw/i2c/Makefile.objs
+++ b/hw/i2c/Makefile.objs
@@ -1,4 +1,4 @@
-common-obj-$(CONFIG_I2C) += core.o smbus.o
+common-obj-$(CONFIG_I2C) += core.o smbus_slave.o smbus_master.o
common-obj-$(CONFIG_SMBUS_EEPROM) += smbus_eeprom.o
common-obj-$(CONFIG_DDC) += i2c-ddc.o
common-obj-$(CONFIG_VERSATILE_I2C) += versatile_i2c.o
diff --git a/hw/i2c/aspeed_i2c.c b/hw/i2c/aspeed_i2c.c
index a2dfa82..a085510 100644
--- a/hw/i2c/aspeed_i2c.c
+++ b/hw/i2c/aspeed_i2c.c
@@ -189,16 +189,11 @@
static void aspeed_i2c_handle_rx_cmd(AspeedI2CBus *bus)
{
- int ret;
+ uint8_t ret;
aspeed_i2c_set_state(bus, I2CD_MRXD);
ret = i2c_recv(bus->bus);
- if (ret < 0) {
- qemu_log_mask(LOG_GUEST_ERROR, "%s: read failed\n", __func__);
- ret = 0xff;
- } else {
- bus->intr_status |= I2CD_INTR_RX_DONE;
- }
+ bus->intr_status |= I2CD_INTR_RX_DONE;
bus->buf = (ret & I2CD_BYTE_BUF_RX_MASK) << I2CD_BYTE_BUF_RX_SHIFT;
if (bus->cmd & I2CD_M_S_RX_CMD_LAST) {
i2c_nack(bus->bus);
diff --git a/hw/i2c/core.c b/hw/i2c/core.c
index b547259..15237ad 100644
--- a/hw/i2c/core.c
+++ b/hw/i2c/core.c
@@ -191,23 +191,17 @@
}
return ret ? -1 : 0;
} else {
- if ((QLIST_EMPTY(&bus->current_devs)) || (bus->broadcast)) {
- return -1;
- }
-
- sc = I2C_SLAVE_GET_CLASS(QLIST_FIRST(&bus->current_devs)->elt);
- if (sc->recv) {
- s = QLIST_FIRST(&bus->current_devs)->elt;
- ret = sc->recv(s);
- trace_i2c_recv(s->address, ret);
- if (ret < 0) {
- return ret;
- } else {
- *data = ret;
- return 0;
+ ret = 0xff;
+ if (!QLIST_EMPTY(&bus->current_devs) && !bus->broadcast) {
+ sc = I2C_SLAVE_GET_CLASS(QLIST_FIRST(&bus->current_devs)->elt);
+ if (sc->recv) {
+ s = QLIST_FIRST(&bus->current_devs)->elt;
+ ret = sc->recv(s);
+ trace_i2c_recv(s->address, ret);
}
}
- return -1;
+ *data = ret;
+ return 0;
}
}
@@ -216,12 +210,12 @@
return i2c_send_recv(bus, &data, true);
}
-int i2c_recv(I2CBus *bus)
+uint8_t i2c_recv(I2CBus *bus)
{
- uint8_t data;
- int ret = i2c_send_recv(bus, &data, false);
+ uint8_t data = 0xff;
- return ret < 0 ? ret : data;
+ i2c_send_recv(bus, &data, false);
+ return data;
}
void i2c_nack(I2CBus *bus)
diff --git a/hw/i2c/exynos4210_i2c.c b/hw/i2c/exynos4210_i2c.c
index c96fa7d..d154b05 100644
--- a/hw/i2c/exynos4210_i2c.c
+++ b/hw/i2c/exynos4210_i2c.c
@@ -106,16 +106,10 @@
static void exynos4210_i2c_data_receive(void *opaque)
{
Exynos4210I2CState *s = (Exynos4210I2CState *)opaque;
- int ret;
s->i2cstat &= ~I2CSTAT_LAST_BIT;
s->scl_free = false;
- ret = i2c_recv(s->bus);
- if (ret < 0 && (s->i2ccon & I2CCON_ACK_GEN)) {
- s->i2cstat |= I2CSTAT_LAST_BIT; /* Data is not acknowledged */
- } else {
- s->i2cds = ret;
- }
+ s->i2cds = i2c_recv(s->bus);
exynos4210_i2c_raise_interrupt(s);
}
diff --git a/hw/i2c/i2c-ddc.c b/hw/i2c/i2c-ddc.c
index 0a0367f..7aa8727 100644
--- a/hw/i2c/i2c-ddc.c
+++ b/hw/i2c/i2c-ddc.c
@@ -51,7 +51,7 @@
return 0;
}
-static int i2c_ddc_rx(I2CSlave *i2c)
+static uint8_t i2c_ddc_rx(I2CSlave *i2c)
{
I2CDDCState *s = I2CDDC(i2c);
diff --git a/hw/i2c/imx_i2c.c b/hw/i2c/imx_i2c.c
index 6c81b98..6da5224 100644
--- a/hw/i2c/imx_i2c.c
+++ b/hw/i2c/imx_i2c.c
@@ -120,7 +120,7 @@
value = s->i2dr_read;
if (imx_i2c_is_master(s)) {
- int ret = 0xff;
+ uint8_t ret = 0xff;
if (s->address == ADDR_RESET) {
/* something is wrong as the address is not set */
@@ -133,15 +133,7 @@
} else {
/* get the next byte */
ret = i2c_recv(s->bus);
-
- if (ret >= 0) {
- imx_i2c_raise_interrupt(s);
- } else {
- qemu_log_mask(LOG_GUEST_ERROR, "[%s]%s: read failed "
- "for device 0x%02x\n", TYPE_IMX_I2C,
- __func__, s->address);
- ret = 0xff;
- }
+ imx_i2c_raise_interrupt(s);
}
s->i2dr_read = ret;
diff --git a/hw/i2c/pm_smbus.c b/hw/i2c/pm_smbus.c
index 0306274..e48544f 100644
--- a/hw/i2c/pm_smbus.c
+++ b/hw/i2c/pm_smbus.c
@@ -19,8 +19,9 @@
*/
#include "qemu/osdep.h"
#include "hw/hw.h"
+#include "hw/boards.h"
#include "hw/i2c/pm_smbus.h"
-#include "hw/i2c/smbus.h"
+#include "hw/i2c/smbus_master.h"
#define SMBHSTSTS 0x00
#define SMBHSTCNT 0x02
@@ -118,19 +119,30 @@
}
break;
case PROT_I2C_BLOCK_READ:
- if (read) {
- int xfersize = s->smb_data0;
- if (xfersize > sizeof(s->smb_data)) {
- xfersize = sizeof(s->smb_data);
- }
- ret = smbus_read_block(bus, addr, s->smb_data1, s->smb_data,
- xfersize, false, true);
- goto data8;
- } else {
- /* The manual says the behavior is undefined, just set DEV_ERR. */
+ /* According to the Linux i2c-i801 driver:
+ * NB: page 240 of ICH5 datasheet shows that the R/#W
+ * bit should be cleared here, even when reading.
+ * However if SPD Write Disable is set (Lynx Point and later),
+ * the read will fail if we don't set the R/#W bit.
+ * So at least Linux may or may not set the read bit here.
+ * So just ignore the read bit for this command.
+ */
+ if (i2c_start_transfer(bus, addr, 0)) {
goto error;
}
- break;
+ ret = i2c_send(bus, s->smb_data1);
+ if (ret) {
+ goto error;
+ }
+ if (i2c_start_transfer(bus, addr, 1)) {
+ goto error;
+ }
+ s->in_i2c_block_read = true;
+ s->smb_blkdata = i2c_recv(s->smbus);
+ s->op_done = false;
+ s->smb_stat |= STS_HOST_BUSY | STS_BYTE_DONE;
+ goto out;
+
case PROT_BLOCK_DATA:
if (read) {
ret = smbus_read_block(bus, addr, cmd, s->smb_data,
@@ -208,6 +220,7 @@
{
if (s->smb_ctl & CTL_INTREN) {
smb_transaction(s);
+ s->start_transaction_on_status_read = false;
} else {
/* Do not execute immediately the command; it will be
* executed when guest will read SMB_STAT register. This
@@ -217,6 +230,7 @@
* checking for status. If STS_HOST_BUSY doesn't get
* set, it gets stuck. */
s->smb_stat |= STS_HOST_BUSY;
+ s->start_transaction_on_status_read = true;
}
}
@@ -226,19 +240,38 @@
return ((s->smb_stat & ~STS_HOST_BUSY) != 0) && (s->smb_ctl & CTL_INTREN);
}
+static bool
+smb_byte_by_byte(PMSMBus *s)
+{
+ if (s->op_done) {
+ return false;
+ }
+ if (s->in_i2c_block_read) {
+ return true;
+ }
+ return !(s->smb_auxctl & AUX_BLK);
+}
+
static void smb_ioport_writeb(void *opaque, hwaddr addr, uint64_t val,
unsigned width)
{
PMSMBus *s = opaque;
+ uint8_t clear_byte_done;
SMBUS_DPRINTF("SMB writeb port=0x%04" HWADDR_PRIx
" val=0x%02" PRIx64 "\n", addr, val);
switch(addr) {
case SMBHSTSTS:
+ clear_byte_done = s->smb_stat & val & STS_BYTE_DONE;
s->smb_stat &= ~(val & ~STS_HOST_BUSY);
- if (!s->op_done && !(s->smb_auxctl & AUX_BLK)) {
+ if (clear_byte_done && smb_byte_by_byte(s)) {
uint8_t read = s->smb_addr & 0x01;
+ if (s->in_i2c_block_read) {
+ /* See comment below PROT_I2C_BLOCK_READ above. */
+ read = 1;
+ }
+
s->smb_index++;
if (s->smb_index >= PM_SMBUS_MAX_MSG_SIZE) {
s->smb_index = 0;
@@ -268,12 +301,23 @@
s->smb_stat |= STS_BYTE_DONE;
} else if (s->smb_ctl & CTL_LAST_BYTE) {
s->op_done = true;
- s->smb_blkdata = s->smb_data[s->smb_index];
+ if (s->in_i2c_block_read) {
+ s->in_i2c_block_read = false;
+ s->smb_blkdata = i2c_recv(s->smbus);
+ i2c_nack(s->smbus);
+ i2c_end_transfer(s->smbus);
+ } else {
+ s->smb_blkdata = s->smb_data[s->smb_index];
+ }
s->smb_index = 0;
s->smb_stat |= STS_INTR;
s->smb_stat &= ~STS_HOST_BUSY;
} else {
- s->smb_blkdata = s->smb_data[s->smb_index];
+ if (s->in_i2c_block_read) {
+ s->smb_blkdata = i2c_recv(s->smbus);
+ } else {
+ s->smb_blkdata = s->smb_data[s->smb_index];
+ }
s->smb_stat |= STS_BYTE_DONE;
}
}
@@ -284,6 +328,10 @@
if (!s->op_done) {
s->smb_index = 0;
s->op_done = true;
+ if (s->in_i2c_block_read) {
+ s->in_i2c_block_read = false;
+ i2c_end_transfer(s->smbus);
+ }
}
smb_transaction_start(s);
}
@@ -337,8 +385,9 @@
switch(addr) {
case SMBHSTSTS:
val = s->smb_stat;
- if (s->smb_stat & STS_HOST_BUSY) {
+ if (s->start_transaction_on_status_read) {
/* execute command now */
+ s->start_transaction_on_status_read = false;
s->smb_stat &= ~STS_HOST_BUSY;
smb_transaction(s);
}
@@ -359,10 +408,10 @@
val = s->smb_data1;
break;
case SMBBLKDAT:
- if (s->smb_index >= PM_SMBUS_MAX_MSG_SIZE) {
- s->smb_index = 0;
- }
- if (s->smb_auxctl & AUX_BLK) {
+ if (s->smb_auxctl & AUX_BLK && !s->in_i2c_block_read) {
+ if (s->smb_index >= PM_SMBUS_MAX_MSG_SIZE) {
+ s->smb_index = 0;
+ }
val = s->smb_data[s->smb_index++];
if (!s->op_done && s->smb_index == s->smb_data0) {
s->op_done = true;
@@ -405,6 +454,36 @@
.endianness = DEVICE_LITTLE_ENDIAN,
};
+bool pm_smbus_vmstate_needed(void)
+{
+ MachineClass *mc = MACHINE_GET_CLASS(qdev_get_machine());
+
+ return !mc->smbus_no_migration_support;
+}
+
+const VMStateDescription pmsmb_vmstate = {
+ .name = "pmsmb",
+ .version_id = 1,
+ .minimum_version_id = 1,
+ .fields = (VMStateField[]) {
+ VMSTATE_UINT8(smb_stat, PMSMBus),
+ VMSTATE_UINT8(smb_ctl, PMSMBus),
+ VMSTATE_UINT8(smb_cmd, PMSMBus),
+ VMSTATE_UINT8(smb_addr, PMSMBus),
+ VMSTATE_UINT8(smb_data0, PMSMBus),
+ VMSTATE_UINT8(smb_data1, PMSMBus),
+ VMSTATE_UINT32(smb_index, PMSMBus),
+ VMSTATE_UINT8_ARRAY(smb_data, PMSMBus, PM_SMBUS_MAX_MSG_SIZE),
+ VMSTATE_UINT8(smb_auxctl, PMSMBus),
+ VMSTATE_UINT8(smb_blkdata, PMSMBus),
+ VMSTATE_BOOL(i2c_enable, PMSMBus),
+ VMSTATE_BOOL(op_done, PMSMBus),
+ VMSTATE_BOOL(in_i2c_block_read, PMSMBus),
+ VMSTATE_BOOL(start_transaction_on_status_read, PMSMBus),
+ VMSTATE_END_OF_LIST()
+ }
+};
+
void pm_smbus_init(DeviceState *parent, PMSMBus *smb, bool force_aux_blk)
{
smb->op_done = true;
diff --git a/hw/i2c/smbus.c b/hw/i2c/smbus.c
deleted file mode 100644
index 30028bf..0000000
--- a/hw/i2c/smbus.c
+++ /dev/null
@@ -1,379 +0,0 @@
-/*
- * QEMU SMBus device emulation.
- *
- * Copyright (c) 2007 CodeSourcery.
- * Written by Paul Brook
- *
- * This code is licensed under the LGPL.
- */
-
-/* TODO: Implement PEC. */
-
-#include "qemu/osdep.h"
-#include "hw/hw.h"
-#include "hw/i2c/i2c.h"
-#include "hw/i2c/smbus.h"
-
-//#define DEBUG_SMBUS 1
-
-#ifdef DEBUG_SMBUS
-#define DPRINTF(fmt, ...) \
-do { printf("smbus(%02x): " fmt , dev->i2c.address, ## __VA_ARGS__); } while (0)
-#define BADF(fmt, ...) \
-do { fprintf(stderr, "smbus: error: " fmt , ## __VA_ARGS__); exit(1);} while (0)
-#else
-#define DPRINTF(fmt, ...) do {} while(0)
-#define BADF(fmt, ...) \
-do { fprintf(stderr, "smbus: error: " fmt , ## __VA_ARGS__);} while (0)
-#endif
-
-enum {
- SMBUS_IDLE,
- SMBUS_WRITE_DATA,
- SMBUS_RECV_BYTE,
- SMBUS_READ_DATA,
- SMBUS_DONE,
- SMBUS_CONFUSED = -1
-};
-
-static void smbus_do_quick_cmd(SMBusDevice *dev, int recv)
-{
- SMBusDeviceClass *sc = SMBUS_DEVICE_GET_CLASS(dev);
-
- DPRINTF("Quick Command %d\n", recv);
- if (sc->quick_cmd) {
- sc->quick_cmd(dev, recv);
- }
-}
-
-static void smbus_do_write(SMBusDevice *dev)
-{
- SMBusDeviceClass *sc = SMBUS_DEVICE_GET_CLASS(dev);
-
- if (dev->data_len == 0) {
- smbus_do_quick_cmd(dev, 0);
- } else if (dev->data_len == 1) {
- DPRINTF("Send Byte\n");
- if (sc->send_byte) {
- sc->send_byte(dev, dev->data_buf[0]);
- }
- } else {
- dev->command = dev->data_buf[0];
- DPRINTF("Command %d len %d\n", dev->command, dev->data_len - 1);
- if (sc->write_data) {
- sc->write_data(dev, dev->command, dev->data_buf + 1,
- dev->data_len - 1);
- }
- }
-}
-
-static int smbus_i2c_event(I2CSlave *s, enum i2c_event event)
-{
- SMBusDevice *dev = SMBUS_DEVICE(s);
-
- switch (event) {
- case I2C_START_SEND:
- switch (dev->mode) {
- case SMBUS_IDLE:
- DPRINTF("Incoming data\n");
- dev->mode = SMBUS_WRITE_DATA;
- break;
- default:
- BADF("Unexpected send start condition in state %d\n", dev->mode);
- dev->mode = SMBUS_CONFUSED;
- break;
- }
- break;
-
- case I2C_START_RECV:
- switch (dev->mode) {
- case SMBUS_IDLE:
- DPRINTF("Read mode\n");
- dev->mode = SMBUS_RECV_BYTE;
- break;
- case SMBUS_WRITE_DATA:
- if (dev->data_len == 0) {
- BADF("Read after write with no data\n");
- dev->mode = SMBUS_CONFUSED;
- } else {
- if (dev->data_len > 1) {
- smbus_do_write(dev);
- } else {
- dev->command = dev->data_buf[0];
- DPRINTF("%02x: Command %d\n", dev->i2c.address,
- dev->command);
- }
- DPRINTF("Read mode\n");
- dev->data_len = 0;
- dev->mode = SMBUS_READ_DATA;
- }
- break;
- default:
- BADF("Unexpected recv start condition in state %d\n", dev->mode);
- dev->mode = SMBUS_CONFUSED;
- break;
- }
- break;
-
- case I2C_FINISH:
- switch (dev->mode) {
- case SMBUS_WRITE_DATA:
- smbus_do_write(dev);
- break;
- case SMBUS_RECV_BYTE:
- smbus_do_quick_cmd(dev, 1);
- break;
- case SMBUS_READ_DATA:
- BADF("Unexpected stop during receive\n");
- break;
- default:
- /* Nothing to do. */
- break;
- }
- dev->mode = SMBUS_IDLE;
- dev->data_len = 0;
- break;
-
- case I2C_NACK:
- switch (dev->mode) {
- case SMBUS_DONE:
- /* Nothing to do. */
- break;
- case SMBUS_READ_DATA:
- dev->mode = SMBUS_DONE;
- break;
- default:
- BADF("Unexpected NACK in state %d\n", dev->mode);
- dev->mode = SMBUS_CONFUSED;
- break;
- }
- }
-
- return 0;
-}
-
-static int smbus_i2c_recv(I2CSlave *s)
-{
- SMBusDevice *dev = SMBUS_DEVICE(s);
- SMBusDeviceClass *sc = SMBUS_DEVICE_GET_CLASS(dev);
- int ret;
-
- switch (dev->mode) {
- case SMBUS_RECV_BYTE:
- if (sc->receive_byte) {
- ret = sc->receive_byte(dev);
- } else {
- ret = 0;
- }
- DPRINTF("Receive Byte %02x\n", ret);
- dev->mode = SMBUS_DONE;
- break;
- case SMBUS_READ_DATA:
- if (sc->read_data) {
- ret = sc->read_data(dev, dev->command, dev->data_len);
- dev->data_len++;
- } else {
- ret = 0;
- }
- DPRINTF("Read data %02x\n", ret);
- break;
- default:
- BADF("Unexpected read in state %d\n", dev->mode);
- dev->mode = SMBUS_CONFUSED;
- ret = 0;
- break;
- }
- return ret;
-}
-
-static int smbus_i2c_send(I2CSlave *s, uint8_t data)
-{
- SMBusDevice *dev = SMBUS_DEVICE(s);
-
- switch (dev->mode) {
- case SMBUS_WRITE_DATA:
- DPRINTF("Write data %02x\n", data);
- if (dev->data_len >= sizeof(dev->data_buf)) {
- BADF("Too many bytes sent\n");
- } else {
- dev->data_buf[dev->data_len++] = data;
- }
- break;
- default:
- BADF("Unexpected write in state %d\n", dev->mode);
- break;
- }
- return 0;
-}
-
-/* Master device commands. */
-int smbus_quick_command(I2CBus *bus, uint8_t addr, int read)
-{
- if (i2c_start_transfer(bus, addr, read)) {
- return -1;
- }
- i2c_end_transfer(bus);
- return 0;
-}
-
-int smbus_receive_byte(I2CBus *bus, uint8_t addr)
-{
- uint8_t data;
-
- if (i2c_start_transfer(bus, addr, 1)) {
- return -1;
- }
- data = i2c_recv(bus);
- i2c_nack(bus);
- i2c_end_transfer(bus);
- return data;
-}
-
-int smbus_send_byte(I2CBus *bus, uint8_t addr, uint8_t data)
-{
- if (i2c_start_transfer(bus, addr, 0)) {
- return -1;
- }
- i2c_send(bus, data);
- i2c_end_transfer(bus);
- return 0;
-}
-
-int smbus_read_byte(I2CBus *bus, uint8_t addr, uint8_t command)
-{
- uint8_t data;
- if (i2c_start_transfer(bus, addr, 0)) {
- return -1;
- }
- i2c_send(bus, command);
- if (i2c_start_transfer(bus, addr, 1)) {
- i2c_end_transfer(bus);
- return -1;
- }
- data = i2c_recv(bus);
- i2c_nack(bus);
- i2c_end_transfer(bus);
- return data;
-}
-
-int smbus_write_byte(I2CBus *bus, uint8_t addr, uint8_t command, uint8_t data)
-{
- if (i2c_start_transfer(bus, addr, 0)) {
- return -1;
- }
- i2c_send(bus, command);
- i2c_send(bus, data);
- i2c_end_transfer(bus);
- return 0;
-}
-
-int smbus_read_word(I2CBus *bus, uint8_t addr, uint8_t command)
-{
- uint16_t data;
- if (i2c_start_transfer(bus, addr, 0)) {
- return -1;
- }
- i2c_send(bus, command);
- if (i2c_start_transfer(bus, addr, 1)) {
- i2c_end_transfer(bus);
- return -1;
- }
- data = i2c_recv(bus);
- data |= i2c_recv(bus) << 8;
- i2c_nack(bus);
- i2c_end_transfer(bus);
- return data;
-}
-
-int smbus_write_word(I2CBus *bus, uint8_t addr, uint8_t command, uint16_t data)
-{
- if (i2c_start_transfer(bus, addr, 0)) {
- return -1;
- }
- i2c_send(bus, command);
- i2c_send(bus, data & 0xff);
- i2c_send(bus, data >> 8);
- i2c_end_transfer(bus);
- return 0;
-}
-
-int smbus_read_block(I2CBus *bus, uint8_t addr, uint8_t command, uint8_t *data,
- int len, bool recv_len, bool send_cmd)
-{
- int rlen;
- int i;
-
- if (send_cmd) {
- if (i2c_start_transfer(bus, addr, 0)) {
- return -1;
- }
- i2c_send(bus, command);
- }
- if (i2c_start_transfer(bus, addr, 1)) {
- if (send_cmd) {
- i2c_end_transfer(bus);
- }
- return -1;
- }
- if (recv_len) {
- rlen = i2c_recv(bus);
- } else {
- rlen = len;
- }
- if (rlen > len) {
- rlen = 0;
- }
- for (i = 0; i < rlen; i++) {
- data[i] = i2c_recv(bus);
- }
- i2c_nack(bus);
- i2c_end_transfer(bus);
- return rlen;
-}
-
-int smbus_write_block(I2CBus *bus, uint8_t addr, uint8_t command, uint8_t *data,
- int len, bool send_len)
-{
- int i;
-
- if (len > 32)
- len = 32;
-
- if (i2c_start_transfer(bus, addr, 0)) {
- return -1;
- }
- i2c_send(bus, command);
- if (send_len) {
- i2c_send(bus, len);
- }
- for (i = 0; i < len; i++) {
- i2c_send(bus, data[i]);
- }
- i2c_end_transfer(bus);
- return 0;
-}
-
-static void smbus_device_class_init(ObjectClass *klass, void *data)
-{
- I2CSlaveClass *sc = I2C_SLAVE_CLASS(klass);
-
- sc->event = smbus_i2c_event;
- sc->recv = smbus_i2c_recv;
- sc->send = smbus_i2c_send;
-}
-
-static const TypeInfo smbus_device_type_info = {
- .name = TYPE_SMBUS_DEVICE,
- .parent = TYPE_I2C_SLAVE,
- .instance_size = sizeof(SMBusDevice),
- .abstract = true,
- .class_size = sizeof(SMBusDeviceClass),
- .class_init = smbus_device_class_init,
-};
-
-static void smbus_device_register_types(void)
-{
- type_register_static(&smbus_device_type_info);
-}
-
-type_init(smbus_device_register_types)
diff --git a/hw/i2c/smbus_eeprom.c b/hw/i2c/smbus_eeprom.c
index 01b9439..37167e7 100644
--- a/hw/i2c/smbus_eeprom.c
+++ b/hw/i2c/smbus_eeprom.c
@@ -26,39 +26,35 @@
#include "qemu/units.h"
#include "qapi/error.h"
#include "hw/hw.h"
+#include "hw/boards.h"
#include "hw/i2c/i2c.h"
-#include "hw/i2c/smbus.h"
+#include "hw/i2c/smbus_slave.h"
+#include "hw/i2c/smbus_eeprom.h"
//#define DEBUG
+#define TYPE_SMBUS_EEPROM "smbus-eeprom"
+
+#define SMBUS_EEPROM(obj) \
+ OBJECT_CHECK(SMBusEEPROMDevice, (obj), TYPE_SMBUS_EEPROM)
+
+#define SMBUS_EEPROM_SIZE 256
+
typedef struct SMBusEEPROMDevice {
SMBusDevice smbusdev;
- void *data;
+ uint8_t data[SMBUS_EEPROM_SIZE];
+ void *init_data;
uint8_t offset;
+ bool accessed;
} SMBusEEPROMDevice;
-static void eeprom_quick_cmd(SMBusDevice *dev, uint8_t read)
-{
-#ifdef DEBUG
- printf("eeprom_quick_cmd: addr=0x%02x read=%d\n", dev->i2c.address, read);
-#endif
-}
-
-static void eeprom_send_byte(SMBusDevice *dev, uint8_t val)
-{
- SMBusEEPROMDevice *eeprom = (SMBusEEPROMDevice *) dev;
-#ifdef DEBUG
- printf("eeprom_send_byte: addr=0x%02x val=0x%02x\n",
- dev->i2c.address, val);
-#endif
- eeprom->offset = val;
-}
-
static uint8_t eeprom_receive_byte(SMBusDevice *dev)
{
- SMBusEEPROMDevice *eeprom = (SMBusEEPROMDevice *) dev;
+ SMBusEEPROMDevice *eeprom = SMBUS_EEPROM(dev);
uint8_t *data = eeprom->data;
uint8_t val = data[eeprom->offset++];
+
+ eeprom->accessed = true;
#ifdef DEBUG
printf("eeprom_receive_byte: addr=0x%02x val=0x%02x\n",
dev->i2c.address, val);
@@ -66,48 +62,77 @@
return val;
}
-static void eeprom_write_data(SMBusDevice *dev, uint8_t cmd, uint8_t *buf, int len)
+static int eeprom_write_data(SMBusDevice *dev, uint8_t *buf, uint8_t len)
{
- SMBusEEPROMDevice *eeprom = (SMBusEEPROMDevice *) dev;
- int n;
+ SMBusEEPROMDevice *eeprom = SMBUS_EEPROM(dev);
+ uint8_t *data = eeprom->data;
+
+ eeprom->accessed = true;
#ifdef DEBUG
printf("eeprom_write_byte: addr=0x%02x cmd=0x%02x val=0x%02x\n",
- dev->i2c.address, cmd, buf[0]);
+ dev->i2c.address, buf[0], buf[1]);
#endif
- /* A page write operation is not a valid SMBus command.
- It is a block write without a length byte. Fortunately we
- get the full block anyway. */
- /* TODO: Should this set the current location? */
- if (cmd + len > 256)
- n = 256 - cmd;
- else
- n = len;
- memcpy(eeprom->data + cmd, buf, n);
- len -= n;
- if (len)
- memcpy(eeprom->data, buf + n, len);
+ /* len is guaranteed to be > 0 */
+ eeprom->offset = buf[0];
+ buf++;
+ len--;
+
+ for (; len > 0; len--) {
+ data[eeprom->offset] = *buf++;
+ eeprom->offset = (eeprom->offset + 1) % SMBUS_EEPROM_SIZE;
+ }
+
+ return 0;
}
-static uint8_t eeprom_read_data(SMBusDevice *dev, uint8_t cmd, int n)
+static bool smbus_eeprom_vmstate_needed(void *opaque)
{
- SMBusEEPROMDevice *eeprom = (SMBusEEPROMDevice *) dev;
- /* If this is the first byte then set the current position. */
- if (n == 0)
- eeprom->offset = cmd;
- /* As with writes, we implement block reads without the
- SMBus length byte. */
- return eeprom_receive_byte(dev);
+ MachineClass *mc = MACHINE_GET_CLASS(qdev_get_machine());
+ SMBusEEPROMDevice *eeprom = opaque;
+
+ return (eeprom->accessed || smbus_vmstate_needed(&eeprom->smbusdev)) &&
+ !mc->smbus_no_migration_support;
+}
+
+static const VMStateDescription vmstate_smbus_eeprom = {
+ .name = "smbus-eeprom",
+ .version_id = 1,
+ .minimum_version_id = 1,
+ .needed = smbus_eeprom_vmstate_needed,
+ .fields = (VMStateField[]) {
+ VMSTATE_SMBUS_DEVICE(smbusdev, SMBusEEPROMDevice),
+ VMSTATE_UINT8_ARRAY(data, SMBusEEPROMDevice, SMBUS_EEPROM_SIZE),
+ VMSTATE_UINT8(offset, SMBusEEPROMDevice),
+ VMSTATE_BOOL(accessed, SMBusEEPROMDevice),
+ VMSTATE_END_OF_LIST()
+ }
+};
+
+/*
+ * Reset the EEPROM contents to the initial state on a reset. This
+ * isn't really how an EEPROM works, of course, but the general
+ * principle of QEMU is to restore function on reset to what it would
+ * be if QEMU was stopped and started.
+ *
+ * The proper thing to do would be to have a backing blockdev to hold
+ * the contents and restore that on startup, and not do this on reset.
+ * But until that time, act as if we had been stopped and restarted.
+ */
+static void smbus_eeprom_reset(DeviceState *dev)
+{
+ SMBusEEPROMDevice *eeprom = SMBUS_EEPROM(dev);
+
+ memcpy(eeprom->data, eeprom->init_data, SMBUS_EEPROM_SIZE);
+ eeprom->offset = 0;
}
static void smbus_eeprom_realize(DeviceState *dev, Error **errp)
{
- SMBusEEPROMDevice *eeprom = (SMBusEEPROMDevice *)dev;
-
- eeprom->offset = 0;
+ smbus_eeprom_reset(dev);
}
static Property smbus_eeprom_properties[] = {
- DEFINE_PROP_PTR("data", SMBusEEPROMDevice, data),
+ DEFINE_PROP_PTR("data", SMBusEEPROMDevice, init_data),
DEFINE_PROP_END_OF_LIST(),
};
@@ -117,18 +142,17 @@
SMBusDeviceClass *sc = SMBUS_DEVICE_CLASS(klass);
dc->realize = smbus_eeprom_realize;
- sc->quick_cmd = eeprom_quick_cmd;
- sc->send_byte = eeprom_send_byte;
+ dc->reset = smbus_eeprom_reset;
sc->receive_byte = eeprom_receive_byte;
sc->write_data = eeprom_write_data;
- sc->read_data = eeprom_read_data;
dc->props = smbus_eeprom_properties;
+ dc->vmsd = &vmstate_smbus_eeprom;
/* Reason: pointer property "data" */
dc->user_creatable = false;
}
static const TypeInfo smbus_eeprom_info = {
- .name = "smbus-eeprom",
+ .name = TYPE_SMBUS_EEPROM,
.parent = TYPE_SMBUS_DEVICE,
.instance_size = sizeof(SMBusEEPROMDevice),
.class_init = smbus_eeprom_class_initfn,
@@ -145,7 +169,7 @@
{
DeviceState *dev;
- dev = qdev_create((BusState *) smbus, "smbus-eeprom");
+ dev = qdev_create((BusState *) smbus, TYPE_SMBUS_EEPROM);
qdev_prop_set_uint8(dev, "address", address);
qdev_prop_set_ptr(dev, "data", eeprom_buf);
qdev_init_nofail(dev);
@@ -155,13 +179,17 @@
const uint8_t *eeprom_spd, int eeprom_spd_size)
{
int i;
- uint8_t *eeprom_buf = g_malloc0(8 * 256); /* XXX: make this persistent */
+ /* XXX: make this persistent */
+
+ assert(nb_eeprom <= 8);
+ uint8_t *eeprom_buf = g_malloc0(8 * SMBUS_EEPROM_SIZE);
if (eeprom_spd_size > 0) {
memcpy(eeprom_buf, eeprom_spd, eeprom_spd_size);
}
for (i = 0; i < nb_eeprom; i++) {
- smbus_eeprom_init_one(smbus, 0x50 + i, eeprom_buf + (i * 256));
+ smbus_eeprom_init_one(smbus, 0x50 + i,
+ eeprom_buf + (i * SMBUS_EEPROM_SIZE));
}
}
diff --git a/hw/i2c/smbus_ich9.c b/hw/i2c/smbus_ich9.c
index 2a8b49e..7b24be8 100644
--- a/hw/i2c/smbus_ich9.c
+++ b/hw/i2c/smbus_ich9.c
@@ -29,8 +29,6 @@
#include "hw/i2c/pm_smbus.h"
#include "hw/pci/pci.h"
#include "sysemu/sysemu.h"
-#include "hw/i2c/i2c.h"
-#include "hw/i2c/smbus.h"
#include "hw/i386/ich9.h"
@@ -45,12 +43,20 @@
PMSMBus smb;
} ICH9SMBState;
+static bool ich9_vmstate_need_smbus(void *opaque, int version_id)
+{
+ return pm_smbus_vmstate_needed();
+}
+
static const VMStateDescription vmstate_ich9_smbus = {
.name = "ich9_smb",
.version_id = 1,
.minimum_version_id = 1,
.fields = (VMStateField[]) {
- VMSTATE_PCI_DEVICE(dev, struct ICH9SMBState),
+ VMSTATE_PCI_DEVICE(dev, ICH9SMBState),
+ VMSTATE_BOOL_TEST(irq_enabled, ICH9SMBState, ich9_vmstate_need_smbus),
+ VMSTATE_STRUCT_TEST(smb, ICH9SMBState, ich9_vmstate_need_smbus, 1,
+ pmsmb_vmstate, PMSMBus),
VMSTATE_END_OF_LIST()
}
};
diff --git a/hw/i2c/smbus_master.c b/hw/i2c/smbus_master.c
new file mode 100644
index 0000000..0a62237
--- /dev/null
+++ b/hw/i2c/smbus_master.c
@@ -0,0 +1,165 @@
+/*
+ * QEMU SMBus host (master) emulation.
+ *
+ * This code emulates SMBus transactions from the master point of view,
+ * it runs the individual I2C transaction to do the SMBus protocol
+ * over I2C.
+ *
+ * Copyright (c) 2007 CodeSourcery.
+ * Written by Paul Brook
+ *
+ * This code is licensed under the LGPL.
+ */
+
+#include "qemu/osdep.h"
+#include "hw/hw.h"
+#include "hw/i2c/i2c.h"
+#include "hw/i2c/smbus_master.h"
+
+/* Master device commands. */
+int smbus_quick_command(I2CBus *bus, uint8_t addr, int read)
+{
+ if (i2c_start_transfer(bus, addr, read)) {
+ return -1;
+ }
+ i2c_end_transfer(bus);
+ return 0;
+}
+
+int smbus_receive_byte(I2CBus *bus, uint8_t addr)
+{
+ uint8_t data;
+
+ if (i2c_start_transfer(bus, addr, 1)) {
+ return -1;
+ }
+ data = i2c_recv(bus);
+ i2c_nack(bus);
+ i2c_end_transfer(bus);
+ return data;
+}
+
+int smbus_send_byte(I2CBus *bus, uint8_t addr, uint8_t data)
+{
+ if (i2c_start_transfer(bus, addr, 0)) {
+ return -1;
+ }
+ i2c_send(bus, data);
+ i2c_end_transfer(bus);
+ return 0;
+}
+
+int smbus_read_byte(I2CBus *bus, uint8_t addr, uint8_t command)
+{
+ uint8_t data;
+ if (i2c_start_transfer(bus, addr, 0)) {
+ return -1;
+ }
+ i2c_send(bus, command);
+ if (i2c_start_transfer(bus, addr, 1)) {
+ i2c_end_transfer(bus);
+ return -1;
+ }
+ data = i2c_recv(bus);
+ i2c_nack(bus);
+ i2c_end_transfer(bus);
+ return data;
+}
+
+int smbus_write_byte(I2CBus *bus, uint8_t addr, uint8_t command, uint8_t data)
+{
+ if (i2c_start_transfer(bus, addr, 0)) {
+ return -1;
+ }
+ i2c_send(bus, command);
+ i2c_send(bus, data);
+ i2c_end_transfer(bus);
+ return 0;
+}
+
+int smbus_read_word(I2CBus *bus, uint8_t addr, uint8_t command)
+{
+ uint16_t data;
+ if (i2c_start_transfer(bus, addr, 0)) {
+ return -1;
+ }
+ i2c_send(bus, command);
+ if (i2c_start_transfer(bus, addr, 1)) {
+ i2c_end_transfer(bus);
+ return -1;
+ }
+ data = i2c_recv(bus);
+ data |= i2c_recv(bus) << 8;
+ i2c_nack(bus);
+ i2c_end_transfer(bus);
+ return data;
+}
+
+int smbus_write_word(I2CBus *bus, uint8_t addr, uint8_t command, uint16_t data)
+{
+ if (i2c_start_transfer(bus, addr, 0)) {
+ return -1;
+ }
+ i2c_send(bus, command);
+ i2c_send(bus, data & 0xff);
+ i2c_send(bus, data >> 8);
+ i2c_end_transfer(bus);
+ return 0;
+}
+
+int smbus_read_block(I2CBus *bus, uint8_t addr, uint8_t command, uint8_t *data,
+ int len, bool recv_len, bool send_cmd)
+{
+ int rlen;
+ int i;
+
+ if (send_cmd) {
+ if (i2c_start_transfer(bus, addr, 0)) {
+ return -1;
+ }
+ i2c_send(bus, command);
+ }
+ if (i2c_start_transfer(bus, addr, 1)) {
+ if (send_cmd) {
+ i2c_end_transfer(bus);
+ }
+ return -1;
+ }
+ if (recv_len) {
+ rlen = i2c_recv(bus);
+ } else {
+ rlen = len;
+ }
+ if (rlen > len) {
+ rlen = 0;
+ }
+ for (i = 0; i < rlen; i++) {
+ data[i] = i2c_recv(bus);
+ }
+ i2c_nack(bus);
+ i2c_end_transfer(bus);
+ return rlen;
+}
+
+int smbus_write_block(I2CBus *bus, uint8_t addr, uint8_t command, uint8_t *data,
+ int len, bool send_len)
+{
+ int i;
+
+ if (len > 32) {
+ len = 32;
+ }
+
+ if (i2c_start_transfer(bus, addr, 0)) {
+ return -1;
+ }
+ i2c_send(bus, command);
+ if (send_len) {
+ i2c_send(bus, len);
+ }
+ for (i = 0; i < len; i++) {
+ i2c_send(bus, data[i]);
+ }
+ i2c_end_transfer(bus);
+ return 0;
+}
diff --git a/hw/i2c/smbus_slave.c b/hw/i2c/smbus_slave.c
new file mode 100644
index 0000000..9a2d314
--- /dev/null
+++ b/hw/i2c/smbus_slave.c
@@ -0,0 +1,236 @@
+/*
+ * QEMU SMBus device emulation.
+ *
+ * This code is a helper for SMBus device emulation. It implements an
+ * I2C device inteface and runs the SMBus protocol from the device
+ * point of view and maps those to simple calls to emulate.
+ *
+ * Copyright (c) 2007 CodeSourcery.
+ * Written by Paul Brook
+ *
+ * This code is licensed under the LGPL.
+ */
+
+/* TODO: Implement PEC. */
+
+#include "qemu/osdep.h"
+#include "hw/hw.h"
+#include "hw/i2c/i2c.h"
+#include "hw/i2c/smbus_slave.h"
+
+//#define DEBUG_SMBUS 1
+
+#ifdef DEBUG_SMBUS
+#define DPRINTF(fmt, ...) \
+do { printf("smbus(%02x): " fmt , dev->i2c.address, ## __VA_ARGS__); } while (0)
+#define BADF(fmt, ...) \
+do { fprintf(stderr, "smbus: error: " fmt , ## __VA_ARGS__); exit(1);} while (0)
+#else
+#define DPRINTF(fmt, ...) do {} while(0)
+#define BADF(fmt, ...) \
+do { fprintf(stderr, "smbus: error: " fmt , ## __VA_ARGS__);} while (0)
+#endif
+
+enum {
+ SMBUS_IDLE,
+ SMBUS_WRITE_DATA,
+ SMBUS_READ_DATA,
+ SMBUS_DONE,
+ SMBUS_CONFUSED = -1
+};
+
+static void smbus_do_quick_cmd(SMBusDevice *dev, int recv)
+{
+ SMBusDeviceClass *sc = SMBUS_DEVICE_GET_CLASS(dev);
+
+ DPRINTF("Quick Command %d\n", recv);
+ if (sc->quick_cmd) {
+ sc->quick_cmd(dev, recv);
+ }
+}
+
+static void smbus_do_write(SMBusDevice *dev)
+{
+ SMBusDeviceClass *sc = SMBUS_DEVICE_GET_CLASS(dev);
+
+ DPRINTF("Command %d len %d\n", dev->data_buf[0], dev->data_len);
+ if (sc->write_data) {
+ sc->write_data(dev, dev->data_buf, dev->data_len);
+ }
+}
+
+static int smbus_i2c_event(I2CSlave *s, enum i2c_event event)
+{
+ SMBusDevice *dev = SMBUS_DEVICE(s);
+
+ switch (event) {
+ case I2C_START_SEND:
+ switch (dev->mode) {
+ case SMBUS_IDLE:
+ DPRINTF("Incoming data\n");
+ dev->mode = SMBUS_WRITE_DATA;
+ break;
+
+ default:
+ BADF("Unexpected send start condition in state %d\n", dev->mode);
+ dev->mode = SMBUS_CONFUSED;
+ break;
+ }
+ break;
+
+ case I2C_START_RECV:
+ switch (dev->mode) {
+ case SMBUS_IDLE:
+ DPRINTF("Read mode\n");
+ dev->mode = SMBUS_READ_DATA;
+ break;
+
+ case SMBUS_WRITE_DATA:
+ if (dev->data_len == 0) {
+ BADF("Read after write with no data\n");
+ dev->mode = SMBUS_CONFUSED;
+ } else {
+ smbus_do_write(dev);
+ DPRINTF("Read mode\n");
+ dev->mode = SMBUS_READ_DATA;
+ }
+ break;
+
+ default:
+ BADF("Unexpected recv start condition in state %d\n", dev->mode);
+ dev->mode = SMBUS_CONFUSED;
+ break;
+ }
+ break;
+
+ case I2C_FINISH:
+ if (dev->data_len == 0) {
+ if (dev->mode == SMBUS_WRITE_DATA || dev->mode == SMBUS_READ_DATA) {
+ smbus_do_quick_cmd(dev, dev->mode == SMBUS_READ_DATA);
+ }
+ } else {
+ switch (dev->mode) {
+ case SMBUS_WRITE_DATA:
+ smbus_do_write(dev);
+ break;
+
+ case SMBUS_READ_DATA:
+ BADF("Unexpected stop during receive\n");
+ break;
+
+ default:
+ /* Nothing to do. */
+ break;
+ }
+ }
+ dev->mode = SMBUS_IDLE;
+ dev->data_len = 0;
+ break;
+
+ case I2C_NACK:
+ switch (dev->mode) {
+ case SMBUS_DONE:
+ /* Nothing to do. */
+ break;
+
+ case SMBUS_READ_DATA:
+ dev->mode = SMBUS_DONE;
+ break;
+
+ default:
+ BADF("Unexpected NACK in state %d\n", dev->mode);
+ dev->mode = SMBUS_CONFUSED;
+ break;
+ }
+ }
+
+ return 0;
+}
+
+static uint8_t smbus_i2c_recv(I2CSlave *s)
+{
+ SMBusDevice *dev = SMBUS_DEVICE(s);
+ SMBusDeviceClass *sc = SMBUS_DEVICE_GET_CLASS(dev);
+ uint8_t ret = 0xff;
+
+ switch (dev->mode) {
+ case SMBUS_READ_DATA:
+ if (sc->receive_byte) {
+ ret = sc->receive_byte(dev);
+ }
+ DPRINTF("Read data %02x\n", ret);
+ break;
+
+ default:
+ BADF("Unexpected read in state %d\n", dev->mode);
+ dev->mode = SMBUS_CONFUSED;
+ break;
+ }
+
+ return ret;
+}
+
+static int smbus_i2c_send(I2CSlave *s, uint8_t data)
+{
+ SMBusDevice *dev = SMBUS_DEVICE(s);
+
+ switch (dev->mode) {
+ case SMBUS_WRITE_DATA:
+ DPRINTF("Write data %02x\n", data);
+ if (dev->data_len >= sizeof(dev->data_buf)) {
+ BADF("Too many bytes sent\n");
+ } else {
+ dev->data_buf[dev->data_len++] = data;
+ }
+ break;
+
+ default:
+ BADF("Unexpected write in state %d\n", dev->mode);
+ break;
+ }
+
+ return 0;
+}
+
+static void smbus_device_class_init(ObjectClass *klass, void *data)
+{
+ I2CSlaveClass *sc = I2C_SLAVE_CLASS(klass);
+
+ sc->event = smbus_i2c_event;
+ sc->recv = smbus_i2c_recv;
+ sc->send = smbus_i2c_send;
+}
+
+bool smbus_vmstate_needed(SMBusDevice *dev)
+{
+ return dev->mode != SMBUS_IDLE;
+}
+
+const VMStateDescription vmstate_smbus_device = {
+ .name = TYPE_SMBUS_DEVICE,
+ .version_id = 1,
+ .minimum_version_id = 1,
+ .fields = (VMStateField[]) {
+ VMSTATE_I2C_SLAVE(i2c, SMBusDevice),
+ VMSTATE_INT32(mode, SMBusDevice),
+ VMSTATE_INT32(data_len, SMBusDevice),
+ VMSTATE_UINT8_ARRAY(data_buf, SMBusDevice, SMBUS_DATA_MAX_LEN),
+ VMSTATE_END_OF_LIST()
+ }
+};
+
+static const TypeInfo smbus_device_type_info = {
+ .name = TYPE_SMBUS_DEVICE,
+ .parent = TYPE_I2C_SLAVE,
+ .instance_size = sizeof(SMBusDevice),
+ .abstract = true,
+ .class_size = sizeof(SMBusDeviceClass),
+ .class_init = smbus_device_class_init,
+};
+
+static void smbus_device_register_types(void)
+{
+ type_register_static(&smbus_device_type_info);
+}
+
+type_init(smbus_device_register_types)
diff --git a/hw/i386/pc.c b/hw/i386/pc.c
index 3889ecc..4212818 100644
--- a/hw/i386/pc.c
+++ b/hw/i386/pc.c
@@ -1688,33 +1688,6 @@
pci_address_space, -1);
}
-void pc_acpi_init(const char *default_dsdt)
-{
- char *filename;
-
- if (acpi_tables != NULL) {
- /* manually set via -acpitable, leave it alone */
- return;
- }
-
- filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, default_dsdt);
- if (filename == NULL) {
- warn_report("failed to find %s", default_dsdt);
- } else {
- QemuOpts *opts = qemu_opts_create(qemu_find_opts("acpi"), NULL, 0,
- &error_abort);
- Error *err = NULL;
-
- qemu_opt_set(opts, "file", filename, &error_abort);
-
- acpi_table_add_builtin(opts, &err);
- if (err) {
- warn_reportf_err(err, "failed to load %s: ", filename);
- }
- g_free(filename);
- }
-}
-
void xen_load_linux(PCMachineState *pcms)
{
int i;
@@ -2181,8 +2154,7 @@
}
pc_dimm_unplug(PC_DIMM(dev), MACHINE(pcms));
- object_unparent(OBJECT(dev));
-
+ object_property_set_bool(OBJECT(dev), false, "realized", NULL);
out:
error_propagate(errp, local_err);
}
@@ -2288,7 +2260,7 @@
found_cpu = pc_find_cpu_slot(MACHINE(pcms), cpu->apic_id, NULL);
found_cpu->cpu = NULL;
- object_unparent(OBJECT(dev));
+ object_property_set_bool(OBJECT(dev), false, "realized", NULL);
/* decrement the number of CPUs */
pcms->boot_cpus--;
diff --git a/hw/i386/pc_piix.c b/hw/i386/pc_piix.c
index fd0f2c2..8770eca 100644
--- a/hw/i386/pc_piix.c
+++ b/hw/i386/pc_piix.c
@@ -42,7 +42,7 @@
#include "sysemu/sysemu.h"
#include "hw/sysbus.h"
#include "sysemu/arch_init.h"
-#include "hw/i2c/smbus.h"
+#include "hw/i2c/smbus_eeprom.h"
#include "hw/xen/xen.h"
#include "exec/memory.h"
#include "exec/address-spaces.h"
@@ -444,6 +444,7 @@
pc_i440fx_4_0_machine_options(m);
m->is_default = 0;
+ m->smbus_no_migration_support = true;
m->alias = NULL;
pcmc->pvh_enabled = false;
compat_props_add(m->compat_props, hw_compat_3_1, hw_compat_3_1_len);
diff --git a/hw/i386/pc_q35.c b/hw/i386/pc_q35.c
index 4a175ea..cfb9043 100644
--- a/hw/i386/pc_q35.c
+++ b/hw/i386/pc_q35.c
@@ -33,7 +33,7 @@
#include "hw/hw.h"
#include "hw/loader.h"
#include "sysemu/arch_init.h"
-#include "hw/i2c/smbus.h"
+#include "hw/i2c/smbus_eeprom.h"
#include "hw/boards.h"
#include "hw/timer/mc146818rtc.h"
#include "hw/xen/xen.h"
@@ -380,6 +380,7 @@
pc_q35_4_0_machine_options(m);
m->default_kernel_irqchip_split = false;
+ m->smbus_no_migration_support = true;
m->alias = NULL;
pcmc->pvh_enabled = false;
compat_props_add(m->compat_props, hw_compat_3_1, hw_compat_3_1_len);
diff --git a/hw/ide/atapi.c b/hw/ide/atapi.c
index 39e473f..1b0f66c 100644
--- a/hw/ide/atapi.c
+++ b/hw/ide/atapi.c
@@ -174,16 +174,15 @@
static int cd_read_sector(IDEState *s)
{
+ void *buf;
+
if (s->cd_sector_size != 2048 && s->cd_sector_size != 2352) {
block_acct_invalid(blk_get_stats(s->blk), BLOCK_ACCT_READ);
return -EINVAL;
}
- s->iov.iov_base = (s->cd_sector_size == 2352) ?
- s->io_buffer + 16 : s->io_buffer;
-
- s->iov.iov_len = ATAPI_SECTOR_SIZE;
- qemu_iovec_init_external(&s->qiov, &s->iov, 1);
+ buf = (s->cd_sector_size == 2352) ? s->io_buffer + 16 : s->io_buffer;
+ qemu_iovec_init_buf(&s->qiov, buf, ATAPI_SECTOR_SIZE);
trace_cd_read_sector(s->lba);
@@ -421,9 +420,8 @@
data_offset = 0;
}
trace_ide_atapi_cmd_read_dma_cb_aio(s, s->lba, n);
- s->bus->dma->iov.iov_base = (void *)(s->io_buffer + data_offset);
- s->bus->dma->iov.iov_len = n * ATAPI_SECTOR_SIZE;
- qemu_iovec_init_external(&s->bus->dma->qiov, &s->bus->dma->iov, 1);
+ qemu_iovec_init_buf(&s->bus->dma->qiov, s->io_buffer + data_offset,
+ n * ATAPI_SECTOR_SIZE);
s->bus->dma->aiocb = ide_buffered_readv(s, (int64_t)s->lba << 2,
&s->bus->dma->qiov, n * 4,
diff --git a/hw/ide/core.c b/hw/ide/core.c
index 8483200..6afadf8 100644
--- a/hw/ide/core.c
+++ b/hw/ide/core.c
@@ -629,13 +629,15 @@
IDEBufferedRequest *req = opaque;
if (!req->orphaned) {
if (!ret) {
- qemu_iovec_from_buf(req->original_qiov, 0, req->iov.iov_base,
+ assert(req->qiov.size == req->original_qiov->size);
+ qemu_iovec_from_buf(req->original_qiov, 0,
+ req->qiov.local_iov.iov_base,
req->original_qiov->size);
}
req->original_cb(req->original_opaque, ret);
}
QLIST_REMOVE(req, list);
- qemu_vfree(req->iov.iov_base);
+ qemu_vfree(qemu_iovec_buf(&req->qiov));
g_free(req);
}
@@ -660,9 +662,8 @@
req->original_qiov = iov;
req->original_cb = cb;
req->original_opaque = opaque;
- req->iov.iov_base = qemu_blockalign(blk_bs(s->blk), iov->size);
- req->iov.iov_len = iov->size;
- qemu_iovec_init_external(&req->qiov, &req->iov, 1);
+ qemu_iovec_init_buf(&req->qiov, blk_blockalign(s->blk, iov->size),
+ iov->size);
aioreq = blk_aio_preadv(s->blk, sector_num << BDRV_SECTOR_BITS,
&req->qiov, 0, ide_buffered_readv_cb, req);
@@ -774,9 +775,7 @@
return;
}
- s->iov.iov_base = s->io_buffer;
- s->iov.iov_len = n * BDRV_SECTOR_SIZE;
- qemu_iovec_init_external(&s->qiov, &s->iov, 1);
+ qemu_iovec_init_buf(&s->qiov, s->io_buffer, n * BDRV_SECTOR_SIZE);
block_acct_start(blk_get_stats(s->blk), &s->acct,
n * BDRV_SECTOR_SIZE, BLOCK_ACCT_READ);
@@ -1045,9 +1044,7 @@
return;
}
- s->iov.iov_base = s->io_buffer;
- s->iov.iov_len = n * BDRV_SECTOR_SIZE;
- qemu_iovec_init_external(&s->qiov, &s->iov, 1);
+ qemu_iovec_init_buf(&s->qiov, s->io_buffer, n * BDRV_SECTOR_SIZE);
block_acct_start(blk_get_stats(s->blk), &s->acct,
n * BDRV_SECTOR_SIZE, BLOCK_ACCT_WRITE);
diff --git a/hw/input/lm832x.c b/hw/input/lm832x.c
index cffbf58..1fc7b86 100644
--- a/hw/input/lm832x.c
+++ b/hw/input/lm832x.c
@@ -401,7 +401,7 @@
return 0;
}
-static int lm_i2c_rx(I2CSlave *i2c)
+static uint8_t lm_i2c_rx(I2CSlave *i2c)
{
LM823KbdState *s = LM8323(i2c);
diff --git a/hw/intc/spapr_xive.c b/hw/intc/spapr_xive.c
index 290a290..e0e5cb5 100644
--- a/hw/intc/spapr_xive.c
+++ b/hw/intc/spapr_xive.c
@@ -244,13 +244,12 @@
{
sPAPRXive *xive = SPAPR_XIVE(obj);
- object_initialize(&xive->source, sizeof(xive->source), TYPE_XIVE_SOURCE);
- object_property_add_child(obj, "source", OBJECT(&xive->source), NULL);
+ object_initialize_child(obj, "source", &xive->source, sizeof(xive->source),
+ TYPE_XIVE_SOURCE, &error_abort, NULL);
- object_initialize(&xive->end_source, sizeof(xive->end_source),
- TYPE_XIVE_END_SOURCE);
- object_property_add_child(obj, "end_source", OBJECT(&xive->end_source),
- NULL);
+ object_initialize_child(obj, "end_source", &xive->end_source,
+ sizeof(xive->end_source), TYPE_XIVE_END_SOURCE,
+ &error_abort, NULL);
}
static void spapr_xive_realize(DeviceState *dev, Error **errp)
@@ -317,6 +316,9 @@
/* Map all regions */
spapr_xive_map_mmio(xive);
+ 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);
}
@@ -1448,7 +1450,6 @@
cpu_to_be32(7), /* start */
cpu_to_be32(0xf8), /* count */
};
- gchar *nodename;
/* Thread Interrupt Management Area : User (ring 3) and OS (ring 2) */
timas[0] = cpu_to_be64(xive->tm_base +
@@ -1458,10 +1459,7 @@
XIVE_TM_OS_PAGE * (1ull << TM_SHIFT));
timas[3] = cpu_to_be64(1ull << TM_SHIFT);
- nodename = g_strdup_printf("interrupt-controller@%" PRIx64,
- xive->tm_base + XIVE_TM_USER_PAGE * (1 << TM_SHIFT));
- _FDT(node = fdt_add_subnode(fdt, 0, nodename));
- g_free(nodename);
+ _FDT(node = fdt_add_subnode(fdt, 0, xive->nodename));
_FDT(fdt_setprop_string(fdt, node, "device_type", "power-ivpe"));
_FDT(fdt_setprop(fdt, node, "reg", timas, sizeof(timas)));
diff --git a/hw/intc/xics.c b/hw/intc/xics.c
index 3009fa7..af7dc70 100644
--- a/hw/intc/xics.c
+++ b/hw/intc/xics.c
@@ -338,6 +338,9 @@
case PPC_FLAGS_INPUT_POWER7:
icp->output = env->irq_inputs[POWER7_INPUT_INT];
break;
+ case PPC_FLAGS_INPUT_POWER9: /* For SPAPR xics emulation */
+ icp->output = env->irq_inputs[POWER9_INPUT_INT];
+ break;
case PPC_FLAGS_INPUT_970:
icp->output = env->irq_inputs[PPC970_INPUT_INT];
@@ -755,6 +758,10 @@
ics->irqs[srcno].flags |=
lsi ? XICS_FLAGS_IRQ_LSI : XICS_FLAGS_IRQ_MSI;
+
+ if (kvm_irqchip_in_kernel()) {
+ ics_set_kvm_state_one(ics, srcno);
+ }
}
static void xics_register_types(void)
diff --git a/hw/intc/xics_kvm.c b/hw/intc/xics_kvm.c
index a00d0a7..c6e1b63 100644
--- a/hw/intc/xics_kvm.c
+++ b/hw/intc/xics_kvm.c
@@ -213,45 +213,57 @@
ics_get_kvm_state(ics);
}
-int ics_set_kvm_state(ICSState *ics)
+int ics_set_kvm_state_one(ICSState *ics, int srcno)
{
uint64_t state;
- int i;
Error *local_err = NULL;
+ ICSIRQState *irq = &ics->irqs[srcno];
+ int ret;
+
+ state = irq->server;
+ state |= (uint64_t)(irq->saved_priority & KVM_XICS_PRIORITY_MASK)
+ << KVM_XICS_PRIORITY_SHIFT;
+ if (irq->priority != irq->saved_priority) {
+ assert(irq->priority == 0xff);
+ state |= KVM_XICS_MASKED;
+ }
+
+ if (irq->flags & XICS_FLAGS_IRQ_LSI) {
+ state |= KVM_XICS_LEVEL_SENSITIVE;
+ if (irq->status & XICS_STATUS_ASSERTED) {
+ state |= KVM_XICS_PENDING;
+ }
+ } else {
+ if (irq->status & XICS_STATUS_MASKED_PENDING) {
+ state |= KVM_XICS_PENDING;
+ }
+ }
+ if (irq->status & XICS_STATUS_PRESENTED) {
+ state |= KVM_XICS_PRESENTED;
+ }
+ if (irq->status & XICS_STATUS_QUEUED) {
+ state |= KVM_XICS_QUEUED;
+ }
+
+ ret = kvm_device_access(kernel_xics_fd, KVM_DEV_XICS_GRP_SOURCES,
+ srcno + ics->offset, &state, true, &local_err);
+ if (local_err) {
+ error_report_err(local_err);
+ return ret;
+ }
+
+ return 0;
+}
+
+int ics_set_kvm_state(ICSState *ics)
+{
+ int i;
for (i = 0; i < ics->nr_irqs; i++) {
- ICSIRQState *irq = &ics->irqs[i];
int ret;
- state = irq->server;
- state |= (uint64_t)(irq->saved_priority & KVM_XICS_PRIORITY_MASK)
- << KVM_XICS_PRIORITY_SHIFT;
- if (irq->priority != irq->saved_priority) {
- assert(irq->priority == 0xff);
- state |= KVM_XICS_MASKED;
- }
-
- if (ics->irqs[i].flags & XICS_FLAGS_IRQ_LSI) {
- state |= KVM_XICS_LEVEL_SENSITIVE;
- if (irq->status & XICS_STATUS_ASSERTED) {
- state |= KVM_XICS_PENDING;
- }
- } else {
- if (irq->status & XICS_STATUS_MASKED_PENDING) {
- state |= KVM_XICS_PENDING;
- }
- }
- if (irq->status & XICS_STATUS_PRESENTED) {
- state |= KVM_XICS_PRESENTED;
- }
- if (irq->status & XICS_STATUS_QUEUED) {
- state |= KVM_XICS_QUEUED;
- }
-
- ret = kvm_device_access(kernel_xics_fd, KVM_DEV_XICS_GRP_SOURCES,
- i + ics->offset, &state, true, &local_err);
- if (local_err) {
- error_report_err(local_err);
+ ret = ics_set_kvm_state_one(ics, i);
+ if (ret) {
return ret;
}
}
diff --git a/hw/intc/xics_spapr.c b/hw/intc/xics_spapr.c
index e2d8b38..53bda66 100644
--- a/hw/intc/xics_spapr.c
+++ b/hw/intc/xics_spapr.c
@@ -254,7 +254,7 @@
};
int node;
- _FDT(node = fdt_add_subnode(fdt, 0, "interrupt-controller"));
+ _FDT(node = fdt_add_subnode(fdt, 0, XICS_NODENAME));
_FDT(fdt_setprop_string(fdt, node, "device_type",
"PowerPC-External-Interrupt-Presentation"));
diff --git a/hw/intc/xive.c b/hw/intc/xive.c
index 2e9b8ef..daa7bad 100644
--- a/hw/intc/xive.c
+++ b/hw/intc/xive.c
@@ -481,8 +481,8 @@
env = &cpu->env;
switch (PPC_INPUT(env)) {
- case PPC_FLAGS_INPUT_POWER7:
- tctx->output = env->irq_inputs[POWER7_INPUT_INT];
+ case PPC_FLAGS_INPUT_POWER9:
+ tctx->output = env->irq_inputs[POWER9_INPUT_INT];
break;
default:
diff --git a/hw/isa/vt82c686.c b/hw/isa/vt82c686.c
index 7302f6d..85d0532 100644
--- a/hw/isa/vt82c686.c
+++ b/hw/isa/vt82c686.c
@@ -14,7 +14,6 @@
#include "hw/hw.h"
#include "hw/isa/vt82c686.h"
#include "hw/i2c/i2c.h"
-#include "hw/i2c/smbus.h"
#include "hw/pci/pci.h"
#include "hw/isa/isa.h"
#include "hw/isa/superio.h"
diff --git a/hw/m68k/mcf5208.c b/hw/m68k/mcf5208.c
index 8531e07..6f6efae 100644
--- a/hw/m68k/mcf5208.c
+++ b/hw/m68k/mcf5208.c
@@ -27,6 +27,8 @@
#define SYS_FREQ 166666666
+#define ROM_SIZE 0x200000
+
#define PCSR_EN 0x0001
#define PCSR_RLD 0x0002
#define PCSR_PIF 0x0004
@@ -227,6 +229,7 @@
hwaddr entry;
qemu_irq *pic;
MemoryRegion *address_space_mem = get_system_memory();
+ MemoryRegion *rom = g_new(MemoryRegion, 1);
MemoryRegion *ram = g_new(MemoryRegion, 1);
MemoryRegion *sram = g_new(MemoryRegion, 1);
@@ -237,6 +240,10 @@
env->vbr = 0;
/* TODO: Configure BARs. */
+ /* ROM at 0x00000000 */
+ memory_region_init_rom(rom, NULL, "mcf5208.rom", ROM_SIZE, &error_fatal);
+ memory_region_add_subregion(address_space_mem, 0x00000000, rom);
+
/* DRAM at 0x40000000 */
memory_region_allocate_system_memory(ram, NULL, "mcf5208.ram", ram_size);
memory_region_add_subregion(address_space_mem, 0x40000000, ram);
@@ -285,9 +292,30 @@
/* 0xfc0a4000 GPIO. */
/* 0xfc0a8000 SDRAM controller. */
+ /* Load firmware */
+ if (bios_name) {
+ char *fn;
+ uint8_t *ptr;
+
+ fn = qemu_find_file(QEMU_FILE_TYPE_BIOS, bios_name);
+ if (!fn) {
+ error_report("Could not find ROM image '%s'", bios_name);
+ exit(1);
+ }
+ if (load_image_targphys(fn, 0x0, ROM_SIZE) < 8) {
+ error_report("Could not load ROM image '%s'", bios_name);
+ exit(1);
+ }
+ g_free(fn);
+ /* Initial PC is always at offset 4 in firmware binaries */
+ ptr = rom_ptr(0x4, 4);
+ assert(ptr != NULL);
+ env->pc = ldl_p(ptr);
+ }
+
/* Load kernel. */
if (!kernel_filename) {
- if (qtest_enabled()) {
+ if (qtest_enabled() || bios_name) {
return;
}
error_report("Kernel image must be specified");
diff --git a/hw/mem/pc-dimm.c b/hw/mem/pc-dimm.c
index 0c9b9e8..152400b 100644
--- a/hw/mem/pc-dimm.c
+++ b/hw/mem/pc-dimm.c
@@ -204,9 +204,7 @@
static uint64_t pc_dimm_md_get_addr(const MemoryDeviceState *md)
{
- const PCDIMMDevice *dimm = PC_DIMM(md);
-
- return dimm->addr;
+ return object_property_get_uint(OBJECT(md), PC_DIMM_ADDR_PROP, &error_abort);
}
static void pc_dimm_md_set_addr(MemoryDeviceState *md, uint64_t addr,
diff --git a/hw/mips/mips_fulong2e.c b/hw/mips/mips_fulong2e.c
index eec6fd0..fbbc543 100644
--- a/hw/mips/mips_fulong2e.c
+++ b/hw/mips/mips_fulong2e.c
@@ -28,7 +28,7 @@
#include "hw/isa/superio.h"
#include "net/net.h"
#include "hw/boards.h"
-#include "hw/i2c/smbus.h"
+#include "hw/i2c/smbus_eeprom.h"
#include "hw/block/flash.h"
#include "hw/mips/mips.h"
#include "hw/mips/cpudevs.h"
diff --git a/hw/mips/mips_malta.c b/hw/mips/mips_malta.c
index 7a403ef..39aef4b 100644
--- a/hw/mips/mips_malta.c
+++ b/hw/mips/mips_malta.c
@@ -33,7 +33,7 @@
#include "hw/char/serial.h"
#include "net/net.h"
#include "hw/boards.h"
-#include "hw/i2c/smbus.h"
+#include "hw/i2c/smbus_eeprom.h"
#include "hw/block/flash.h"
#include "hw/mips/mips.h"
#include "hw/mips/cpudevs.h"
diff --git a/hw/misc/Makefile.objs b/hw/misc/Makefile.objs
index 74c91d2..c71e07a 100644
--- a/hw/misc/Makefile.objs
+++ b/hw/misc/Makefile.objs
@@ -70,6 +70,7 @@
obj-$(CONFIG_IOTKIT_SYSCTL) += iotkit-sysctl.o
obj-$(CONFIG_IOTKIT_SYSINFO) += iotkit-sysinfo.o
obj-$(CONFIG_ARMSSE_CPUID) += armsse-cpuid.o
+obj-$(CONFIG_ARMSSE_MHU) += armsse-mhu.o
obj-$(CONFIG_PVPANIC) += pvpanic.o
obj-$(CONFIG_AUX) += auxbus.o
diff --git a/hw/misc/armsse-mhu.c b/hw/misc/armsse-mhu.c
new file mode 100644
index 0000000..9ebca32
--- /dev/null
+++ b/hw/misc/armsse-mhu.c
@@ -0,0 +1,198 @@
+/*
+ * ARM SSE-200 Message Handling Unit (MHU)
+ *
+ * Copyright (c) 2019 Linaro Limited
+ * Written by Peter Maydell
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 or
+ * (at your option) any later version.
+ */
+
+/*
+ * This is a model of the Message Handling Unit (MHU) which is part of the
+ * Arm SSE-200 and documented in
+ * http://infocenter.arm.com/help/topic/com.arm.doc.101104_0100_00_en/corelink_sse200_subsystem_for_embedded_technical_reference_manual_101104_0100_00_en.pdf
+ */
+
+#include "qemu/osdep.h"
+#include "qemu/log.h"
+#include "trace.h"
+#include "qapi/error.h"
+#include "sysemu/sysemu.h"
+#include "hw/sysbus.h"
+#include "hw/registerfields.h"
+#include "hw/misc/armsse-mhu.h"
+
+REG32(CPU0INTR_STAT, 0x0)
+REG32(CPU0INTR_SET, 0x4)
+REG32(CPU0INTR_CLR, 0x8)
+REG32(CPU1INTR_STAT, 0x10)
+REG32(CPU1INTR_SET, 0x14)
+REG32(CPU1INTR_CLR, 0x18)
+REG32(PID4, 0xfd0)
+REG32(PID5, 0xfd4)
+REG32(PID6, 0xfd8)
+REG32(PID7, 0xfdc)
+REG32(PID0, 0xfe0)
+REG32(PID1, 0xfe4)
+REG32(PID2, 0xfe8)
+REG32(PID3, 0xfec)
+REG32(CID0, 0xff0)
+REG32(CID1, 0xff4)
+REG32(CID2, 0xff8)
+REG32(CID3, 0xffc)
+
+/* Valid bits in the interrupt registers. If any are set the IRQ is raised */
+#define INTR_MASK 0xf
+
+/* PID/CID values */
+static const int armsse_mhu_id[] = {
+ 0x04, 0x00, 0x00, 0x00, /* PID4..PID7 */
+ 0x56, 0xb8, 0x0b, 0x00, /* PID0..PID3 */
+ 0x0d, 0xf0, 0x05, 0xb1, /* CID0..CID3 */
+};
+
+static void armsse_mhu_update(ARMSSEMHU *s)
+{
+ qemu_set_irq(s->cpu0irq, s->cpu0intr != 0);
+ qemu_set_irq(s->cpu1irq, s->cpu1intr != 0);
+}
+
+static uint64_t armsse_mhu_read(void *opaque, hwaddr offset, unsigned size)
+{
+ ARMSSEMHU *s = ARMSSE_MHU(opaque);
+ uint64_t r;
+
+ switch (offset) {
+ case A_CPU0INTR_STAT:
+ r = s->cpu0intr;
+ break;
+
+ case A_CPU1INTR_STAT:
+ r = s->cpu1intr;
+ break;
+
+ case A_PID4 ... A_CID3:
+ r = armsse_mhu_id[(offset - A_PID4) / 4];
+ break;
+
+ case A_CPU0INTR_SET:
+ case A_CPU0INTR_CLR:
+ case A_CPU1INTR_SET:
+ case A_CPU1INTR_CLR:
+ qemu_log_mask(LOG_GUEST_ERROR,
+ "SSE MHU: read of write-only register at offset 0x%x\n",
+ (int)offset);
+ r = 0;
+ break;
+
+ default:
+ qemu_log_mask(LOG_GUEST_ERROR,
+ "SSE MHU read: bad offset 0x%x\n", (int)offset);
+ r = 0;
+ break;
+ }
+ trace_armsse_mhu_read(offset, r, size);
+ return r;
+}
+
+static void armsse_mhu_write(void *opaque, hwaddr offset,
+ uint64_t value, unsigned size)
+{
+ ARMSSEMHU *s = ARMSSE_MHU(opaque);
+
+ trace_armsse_mhu_write(offset, value, size);
+
+ switch (offset) {
+ case A_CPU0INTR_SET:
+ s->cpu0intr |= (value & INTR_MASK);
+ break;
+ case A_CPU0INTR_CLR:
+ s->cpu0intr &= ~(value & INTR_MASK);
+ break;
+ case A_CPU1INTR_SET:
+ s->cpu1intr |= (value & INTR_MASK);
+ break;
+ case A_CPU1INTR_CLR:
+ s->cpu1intr &= ~(value & INTR_MASK);
+ break;
+
+ case A_CPU0INTR_STAT:
+ case A_CPU1INTR_STAT:
+ case A_PID4 ... A_CID3:
+ qemu_log_mask(LOG_GUEST_ERROR,
+ "SSE MHU: write to read-only register at offset 0x%x\n",
+ (int)offset);
+ break;
+
+ default:
+ qemu_log_mask(LOG_GUEST_ERROR,
+ "SSE MHU write: bad offset 0x%x\n", (int)offset);
+ break;
+ }
+
+ armsse_mhu_update(s);
+}
+
+static const MemoryRegionOps armsse_mhu_ops = {
+ .read = armsse_mhu_read,
+ .write = armsse_mhu_write,
+ .endianness = DEVICE_LITTLE_ENDIAN,
+ .valid.min_access_size = 4,
+ .valid.max_access_size = 4,
+};
+
+static void armsse_mhu_reset(DeviceState *dev)
+{
+ ARMSSEMHU *s = ARMSSE_MHU(dev);
+
+ s->cpu0intr = 0;
+ s->cpu1intr = 0;
+}
+
+static const VMStateDescription armsse_mhu_vmstate = {
+ .name = "armsse-mhu",
+ .version_id = 1,
+ .minimum_version_id = 1,
+ .fields = (VMStateField[]) {
+ VMSTATE_UINT32(cpu0intr, ARMSSEMHU),
+ VMSTATE_UINT32(cpu1intr, ARMSSEMHU),
+ VMSTATE_END_OF_LIST()
+ },
+};
+
+static void armsse_mhu_init(Object *obj)
+{
+ SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
+ ARMSSEMHU *s = ARMSSE_MHU(obj);
+
+ memory_region_init_io(&s->iomem, obj, &armsse_mhu_ops,
+ s, "armsse-mhu", 0x1000);
+ sysbus_init_mmio(sbd, &s->iomem);
+ sysbus_init_irq(sbd, &s->cpu0irq);
+ sysbus_init_irq(sbd, &s->cpu1irq);
+}
+
+static void armsse_mhu_class_init(ObjectClass *klass, void *data)
+{
+ DeviceClass *dc = DEVICE_CLASS(klass);
+
+ dc->reset = armsse_mhu_reset;
+ dc->vmsd = &armsse_mhu_vmstate;
+}
+
+static const TypeInfo armsse_mhu_info = {
+ .name = TYPE_ARMSSE_MHU,
+ .parent = TYPE_SYS_BUS_DEVICE,
+ .instance_size = sizeof(ARMSSEMHU),
+ .instance_init = armsse_mhu_init,
+ .class_init = armsse_mhu_class_init,
+};
+
+static void armsse_mhu_register_types(void)
+{
+ type_register_static(&armsse_mhu_info);
+}
+
+type_init(armsse_mhu_register_types);
diff --git a/hw/misc/iotkit-sysctl.c b/hw/misc/iotkit-sysctl.c
index a21d8bd..54064a3 100644
--- a/hw/misc/iotkit-sysctl.c
+++ b/hw/misc/iotkit-sysctl.c
@@ -17,6 +17,7 @@
*/
#include "qemu/osdep.h"
+#include "qemu/bitops.h"
#include "qemu/log.h"
#include "trace.h"
#include "qapi/error.h"
@@ -24,19 +25,32 @@
#include "hw/sysbus.h"
#include "hw/registerfields.h"
#include "hw/misc/iotkit-sysctl.h"
+#include "target/arm/arm-powerctl.h"
+#include "target/arm/cpu.h"
REG32(SECDBGSTAT, 0x0)
REG32(SECDBGSET, 0x4)
REG32(SECDBGCLR, 0x8)
+REG32(SCSECCTRL, 0xc)
+REG32(FCLK_DIV, 0x10)
+REG32(SYSCLK_DIV, 0x14)
+REG32(CLOCK_FORCE, 0x18)
REG32(RESET_SYNDROME, 0x100)
REG32(RESET_MASK, 0x104)
REG32(SWRESET, 0x108)
FIELD(SWRESET, SWRESETREQ, 9, 1)
REG32(GRETREG, 0x10c)
-REG32(INITSVRTOR0, 0x110)
+REG32(INITSVTOR0, 0x110)
+REG32(INITSVTOR1, 0x114)
REG32(CPUWAIT, 0x118)
-REG32(BUSWAIT, 0x11c)
+REG32(NMI_ENABLE, 0x11c) /* BUSWAIT in IoTKit */
REG32(WICCTRL, 0x120)
+REG32(EWCTRL, 0x124)
+REG32(PDCM_PD_SYS_SENSE, 0x200)
+REG32(PDCM_PD_SRAM0_SENSE, 0x20c)
+REG32(PDCM_PD_SRAM1_SENSE, 0x210)
+REG32(PDCM_PD_SRAM2_SENSE, 0x214)
+REG32(PDCM_PD_SRAM3_SENSE, 0x218)
REG32(PID4, 0xfd0)
REG32(PID5, 0xfd4)
REG32(PID6, 0xfd8)
@@ -57,6 +71,21 @@
0x0d, 0xf0, 0x05, 0xb1, /* CID0..CID3 */
};
+/*
+ * Set the initial secure vector table offset address for the core.
+ * This will take effect when the CPU next resets.
+ */
+static void set_init_vtor(uint64_t cpuid, uint32_t vtor)
+{
+ Object *cpuobj = OBJECT(arm_get_cpu_by_id(cpuid));
+
+ if (cpuobj) {
+ if (object_property_find(cpuobj, "init-svtor", NULL)) {
+ object_property_set_uint(cpuobj, vtor, "init-svtor", &error_abort);
+ }
+ }
+}
+
static uint64_t iotkit_sysctl_read(void *opaque, hwaddr offset,
unsigned size)
{
@@ -67,6 +96,30 @@
case A_SECDBGSTAT:
r = s->secure_debug;
break;
+ case A_SCSECCTRL:
+ if (!s->is_sse200) {
+ goto bad_offset;
+ }
+ r = s->scsecctrl;
+ break;
+ case A_FCLK_DIV:
+ if (!s->is_sse200) {
+ goto bad_offset;
+ }
+ r = s->fclk_div;
+ break;
+ case A_SYSCLK_DIV:
+ if (!s->is_sse200) {
+ goto bad_offset;
+ }
+ r = s->sysclk_div;
+ break;
+ case A_CLOCK_FORCE:
+ if (!s->is_sse200) {
+ goto bad_offset;
+ }
+ r = s->clock_force;
+ break;
case A_RESET_SYNDROME:
r = s->reset_syndrome;
break;
@@ -76,19 +129,65 @@
case A_GRETREG:
r = s->gretreg;
break;
- case A_INITSVRTOR0:
- r = s->initsvrtor0;
+ case A_INITSVTOR0:
+ r = s->initsvtor0;
+ break;
+ case A_INITSVTOR1:
+ if (!s->is_sse200) {
+ goto bad_offset;
+ }
+ r = s->initsvtor1;
break;
case A_CPUWAIT:
r = s->cpuwait;
break;
- case A_BUSWAIT:
- /* In IoTKit BUSWAIT is reserved, R/O, zero */
- r = 0;
+ case A_NMI_ENABLE:
+ /* In IoTKit this is named BUSWAIT but is marked reserved, R/O, zero */
+ if (!s->is_sse200) {
+ r = 0;
+ break;
+ }
+ r = s->nmi_enable;
break;
case A_WICCTRL:
r = s->wicctrl;
break;
+ case A_EWCTRL:
+ if (!s->is_sse200) {
+ goto bad_offset;
+ }
+ r = s->ewctrl;
+ break;
+ case A_PDCM_PD_SYS_SENSE:
+ if (!s->is_sse200) {
+ goto bad_offset;
+ }
+ r = s->pdcm_pd_sys_sense;
+ break;
+ case A_PDCM_PD_SRAM0_SENSE:
+ if (!s->is_sse200) {
+ goto bad_offset;
+ }
+ r = s->pdcm_pd_sram0_sense;
+ break;
+ case A_PDCM_PD_SRAM1_SENSE:
+ if (!s->is_sse200) {
+ goto bad_offset;
+ }
+ r = s->pdcm_pd_sram1_sense;
+ break;
+ case A_PDCM_PD_SRAM2_SENSE:
+ if (!s->is_sse200) {
+ goto bad_offset;
+ }
+ r = s->pdcm_pd_sram2_sense;
+ break;
+ case A_PDCM_PD_SRAM3_SENSE:
+ if (!s->is_sse200) {
+ goto bad_offset;
+ }
+ r = s->pdcm_pd_sram3_sense;
+ break;
case A_PID4 ... A_CID3:
r = sysctl_id[(offset - A_PID4) / 4];
break;
@@ -101,6 +200,7 @@
r = 0;
break;
default:
+ bad_offset:
qemu_log_mask(LOG_GUEST_ERROR,
"IoTKit SysCtl read: bad offset %x\n", (int)offset);
r = 0;
@@ -145,12 +245,19 @@
*/
s->gretreg = value;
break;
- case A_INITSVRTOR0:
- qemu_log_mask(LOG_UNIMP, "IoTKit SysCtl INITSVRTOR0 unimplemented\n");
- s->initsvrtor0 = value;
+ case A_INITSVTOR0:
+ s->initsvtor0 = value;
+ set_init_vtor(0, s->initsvtor0);
break;
case A_CPUWAIT:
- qemu_log_mask(LOG_UNIMP, "IoTKit SysCtl CPUWAIT unimplemented\n");
+ if ((s->cpuwait & 1) && !(value & 1)) {
+ /* Powering up CPU 0 */
+ arm_set_cpu_on_and_reset(0);
+ }
+ if ((s->cpuwait & 2) && !(value & 2)) {
+ /* Powering up CPU 1 */
+ arm_set_cpu_on_and_reset(1);
+ }
s->cpuwait = value;
break;
case A_WICCTRL:
@@ -172,14 +279,105 @@
qemu_system_reset_request(SHUTDOWN_CAUSE_GUEST_RESET);
}
break;
- case A_BUSWAIT: /* In IoTKit BUSWAIT is reserved, R/O, zero */
+ case A_SCSECCTRL:
+ if (!s->is_sse200) {
+ goto bad_offset;
+ }
+ qemu_log_mask(LOG_UNIMP, "IoTKit SysCtl SCSECCTRL unimplemented\n");
+ s->scsecctrl = value;
+ break;
+ case A_FCLK_DIV:
+ if (!s->is_sse200) {
+ goto bad_offset;
+ }
+ qemu_log_mask(LOG_UNIMP, "IoTKit SysCtl FCLK_DIV unimplemented\n");
+ s->fclk_div = value;
+ break;
+ case A_SYSCLK_DIV:
+ if (!s->is_sse200) {
+ goto bad_offset;
+ }
+ qemu_log_mask(LOG_UNIMP, "IoTKit SysCtl SYSCLK_DIV unimplemented\n");
+ s->sysclk_div = value;
+ break;
+ case A_CLOCK_FORCE:
+ if (!s->is_sse200) {
+ goto bad_offset;
+ }
+ qemu_log_mask(LOG_UNIMP, "IoTKit SysCtl CLOCK_FORCE unimplemented\n");
+ s->clock_force = value;
+ break;
+ case A_INITSVTOR1:
+ if (!s->is_sse200) {
+ goto bad_offset;
+ }
+ s->initsvtor1 = value;
+ set_init_vtor(1, s->initsvtor1);
+ break;
+ case A_EWCTRL:
+ if (!s->is_sse200) {
+ goto bad_offset;
+ }
+ qemu_log_mask(LOG_UNIMP, "IoTKit SysCtl EWCTRL unimplemented\n");
+ s->ewctrl = value;
+ break;
+ case A_PDCM_PD_SYS_SENSE:
+ if (!s->is_sse200) {
+ goto bad_offset;
+ }
+ qemu_log_mask(LOG_UNIMP,
+ "IoTKit SysCtl PDCM_PD_SYS_SENSE unimplemented\n");
+ s->pdcm_pd_sys_sense = value;
+ break;
+ case A_PDCM_PD_SRAM0_SENSE:
+ if (!s->is_sse200) {
+ goto bad_offset;
+ }
+ qemu_log_mask(LOG_UNIMP,
+ "IoTKit SysCtl PDCM_PD_SRAM0_SENSE unimplemented\n");
+ s->pdcm_pd_sram0_sense = value;
+ break;
+ case A_PDCM_PD_SRAM1_SENSE:
+ if (!s->is_sse200) {
+ goto bad_offset;
+ }
+ qemu_log_mask(LOG_UNIMP,
+ "IoTKit SysCtl PDCM_PD_SRAM1_SENSE unimplemented\n");
+ s->pdcm_pd_sram1_sense = value;
+ break;
+ case A_PDCM_PD_SRAM2_SENSE:
+ if (!s->is_sse200) {
+ goto bad_offset;
+ }
+ qemu_log_mask(LOG_UNIMP,
+ "IoTKit SysCtl PDCM_PD_SRAM2_SENSE unimplemented\n");
+ s->pdcm_pd_sram2_sense = value;
+ break;
+ case A_PDCM_PD_SRAM3_SENSE:
+ if (!s->is_sse200) {
+ goto bad_offset;
+ }
+ qemu_log_mask(LOG_UNIMP,
+ "IoTKit SysCtl PDCM_PD_SRAM3_SENSE unimplemented\n");
+ s->pdcm_pd_sram3_sense = value;
+ break;
+ case A_NMI_ENABLE:
+ /* In IoTKit this is BUSWAIT: reserved, R/O, zero */
+ if (!s->is_sse200) {
+ goto ro_offset;
+ }
+ qemu_log_mask(LOG_UNIMP, "IoTKit SysCtl NMI_ENABLE unimplemented\n");
+ s->nmi_enable = value;
+ break;
case A_SECDBGSTAT:
case A_PID4 ... A_CID3:
+ ro_offset:
qemu_log_mask(LOG_GUEST_ERROR,
"IoTKit SysCtl write: write of RO offset %x\n",
(int)offset);
break;
default:
+ bad_offset:
qemu_log_mask(LOG_GUEST_ERROR,
"IoTKit SysCtl write: bad offset %x\n", (int)offset);
break;
@@ -206,9 +404,21 @@
s->reset_syndrome = 1;
s->reset_mask = 0;
s->gretreg = 0;
- s->initsvrtor0 = 0x10000000;
- s->cpuwait = 0;
+ s->initsvtor0 = s->initsvtor0_rst;
+ s->initsvtor1 = s->initsvtor1_rst;
+ s->cpuwait = s->cpuwait_rst;
s->wicctrl = 0;
+ s->scsecctrl = 0;
+ s->fclk_div = 0;
+ s->sysclk_div = 0;
+ s->clock_force = 0;
+ s->nmi_enable = 0;
+ s->ewctrl = 0;
+ s->pdcm_pd_sys_sense = 0x7f;
+ s->pdcm_pd_sram0_sense = 0;
+ s->pdcm_pd_sram1_sense = 0;
+ s->pdcm_pd_sram2_sense = 0;
+ s->pdcm_pd_sram3_sense = 0;
}
static void iotkit_sysctl_init(Object *obj)
@@ -221,6 +431,44 @@
sysbus_init_mmio(sbd, &s->iomem);
}
+static void iotkit_sysctl_realize(DeviceState *dev, Error **errp)
+{
+ IoTKitSysCtl *s = IOTKIT_SYSCTL(dev);
+
+ /* The top 4 bits of the SYS_VERSION register tell us if we're an SSE-200 */
+ if (extract32(s->sys_version, 28, 4) == 2) {
+ s->is_sse200 = true;
+ }
+}
+
+static bool sse200_needed(void *opaque)
+{
+ IoTKitSysCtl *s = IOTKIT_SYSCTL(opaque);
+
+ return s->is_sse200;
+}
+
+static const VMStateDescription iotkit_sysctl_sse200_vmstate = {
+ .name = "iotkit-sysctl/sse-200",
+ .version_id = 1,
+ .minimum_version_id = 1,
+ .needed = sse200_needed,
+ .fields = (VMStateField[]) {
+ VMSTATE_UINT32(scsecctrl, IoTKitSysCtl),
+ VMSTATE_UINT32(fclk_div, IoTKitSysCtl),
+ VMSTATE_UINT32(sysclk_div, IoTKitSysCtl),
+ VMSTATE_UINT32(clock_force, IoTKitSysCtl),
+ VMSTATE_UINT32(initsvtor1, IoTKitSysCtl),
+ VMSTATE_UINT32(nmi_enable, IoTKitSysCtl),
+ VMSTATE_UINT32(pdcm_pd_sys_sense, IoTKitSysCtl),
+ VMSTATE_UINT32(pdcm_pd_sram0_sense, IoTKitSysCtl),
+ VMSTATE_UINT32(pdcm_pd_sram1_sense, IoTKitSysCtl),
+ VMSTATE_UINT32(pdcm_pd_sram2_sense, IoTKitSysCtl),
+ VMSTATE_UINT32(pdcm_pd_sram3_sense, IoTKitSysCtl),
+ VMSTATE_END_OF_LIST()
+ }
+};
+
static const VMStateDescription iotkit_sysctl_vmstate = {
.name = "iotkit-sysctl",
.version_id = 1,
@@ -230,19 +478,35 @@
VMSTATE_UINT32(reset_syndrome, IoTKitSysCtl),
VMSTATE_UINT32(reset_mask, IoTKitSysCtl),
VMSTATE_UINT32(gretreg, IoTKitSysCtl),
- VMSTATE_UINT32(initsvrtor0, IoTKitSysCtl),
+ VMSTATE_UINT32(initsvtor0, IoTKitSysCtl),
VMSTATE_UINT32(cpuwait, IoTKitSysCtl),
VMSTATE_UINT32(wicctrl, IoTKitSysCtl),
VMSTATE_END_OF_LIST()
+ },
+ .subsections = (const VMStateDescription*[]) {
+ &iotkit_sysctl_sse200_vmstate,
+ NULL
}
};
+static Property iotkit_sysctl_props[] = {
+ DEFINE_PROP_UINT32("SYS_VERSION", IoTKitSysCtl, sys_version, 0),
+ DEFINE_PROP_UINT32("CPUWAIT_RST", IoTKitSysCtl, cpuwait_rst, 0),
+ DEFINE_PROP_UINT32("INITSVTOR0_RST", IoTKitSysCtl, initsvtor0_rst,
+ 0x10000000),
+ DEFINE_PROP_UINT32("INITSVTOR1_RST", IoTKitSysCtl, initsvtor1_rst,
+ 0x10000000),
+ DEFINE_PROP_END_OF_LIST()
+};
+
static void iotkit_sysctl_class_init(ObjectClass *klass, void *data)
{
DeviceClass *dc = DEVICE_CLASS(klass);
dc->vmsd = &iotkit_sysctl_vmstate;
dc->reset = iotkit_sysctl_reset;
+ dc->props = iotkit_sysctl_props;
+ dc->realize = iotkit_sysctl_realize;
}
static const TypeInfo iotkit_sysctl_info = {
diff --git a/hw/misc/pca9552.c b/hw/misc/pca9552.c
index 9775d52..7325d3f 100644
--- a/hw/misc/pca9552.c
+++ b/hw/misc/pca9552.c
@@ -115,7 +115,7 @@
}
}
-static int pca9552_recv(I2CSlave *i2c)
+static uint8_t pca9552_recv(I2CSlave *i2c)
{
PCA9552State *s = PCA9552(i2c);
uint8_t ret;
diff --git a/hw/misc/tmp105.c b/hw/misc/tmp105.c
index f6d7163..0c32f6f 100644
--- a/hw/misc/tmp105.c
+++ b/hw/misc/tmp105.c
@@ -147,7 +147,7 @@
}
}
-static int tmp105_rx(I2CSlave *i2c)
+static uint8_t tmp105_rx(I2CSlave *i2c)
{
TMP105State *s = TMP105(i2c);
diff --git a/hw/misc/tmp421.c b/hw/misc/tmp421.c
index eeb1100..ce6d40a 100644
--- a/hw/misc/tmp421.c
+++ b/hw/misc/tmp421.c
@@ -249,7 +249,7 @@
}
}
-static int tmp421_rx(I2CSlave *i2c)
+static uint8_t tmp421_rx(I2CSlave *i2c)
{
TMP421State *s = TMP421(i2c);
diff --git a/hw/misc/trace-events b/hw/misc/trace-events
index b0701bd..c1795bb 100644
--- a/hw/misc/trace-events
+++ b/hw/misc/trace-events
@@ -136,3 +136,7 @@
# hw/misc/armsse-cpuid.c
armsse_cpuid_read(uint64_t offset, uint64_t data, unsigned size) "SSE-200 CPU_IDENTITY read: offset 0x%" PRIx64 " data 0x%" PRIx64 " size %u"
armsse_cpuid_write(uint64_t offset, uint64_t data, unsigned size) "SSE-200 CPU_IDENTITY write: offset 0x%" PRIx64 " data 0x%" PRIx64 " size %u"
+
+# hw/misc/armsse-mhu.c
+armsse_mhu_read(uint64_t offset, uint64_t data, unsigned size) "SSE-200 MHU read: offset 0x%" PRIx64 " data 0x%" PRIx64 " size %u"
+armsse_mhu_write(uint64_t offset, uint64_t data, unsigned size) "SSE-200 MHU write: offset 0x%" PRIx64 " data 0x%" PRIx64 " size %u"
diff --git a/hw/net/Makefile.objs b/hw/net/Makefile.objs
index a43351a..ea63715 100644
--- a/hw/net/Makefile.objs
+++ b/hw/net/Makefile.objs
@@ -37,7 +37,9 @@
obj-$(CONFIG_XILINX_ETHLITE) += xilinx_ethlite.o
obj-$(CONFIG_VIRTIO_NET) += virtio-net.o
-obj-y += vhost_net.o
+common-obj-$(call land,$(CONFIG_VIRTIO_NET),$(CONFIG_VHOST_NET)) += vhost_net.o
+common-obj-$(call lnot,$(call land,$(CONFIG_VIRTIO_NET),$(CONFIG_VHOST_NET))) += vhost_net-stub.o
+common-obj-$(CONFIG_ALL) += vhost_net-stub.o
obj-$(CONFIG_ETSEC) += fsl_etsec/etsec.o fsl_etsec/registers.o \
fsl_etsec/rings.o fsl_etsec/miim.o
diff --git a/hw/net/trace-events b/hw/net/trace-events
index 9d49f62..3a86004 100644
--- a/hw/net/trace-events
+++ b/hw/net/trace-events
@@ -359,3 +359,9 @@
sunhme_rx_filter_accept(void) "accepting incoming frame"
sunhme_rx_desc(uint32_t addr, int offset, uint32_t status, int len, int cr, int nr) "addr 0x%"PRIx32"(+0x%x) status 0x%"PRIx32 " len %d (ring %d/%d)"
sunhme_rx_xsum_calc(uint16_t xsum) "calculated incoming xsum as 0x%x"
+
+# hw/net/virtio-net.c
+virtio_net_announce_notify(void) ""
+virtio_net_announce_timer(int round) "%d"
+virtio_net_handle_announce(int round) "%d"
+virtio_net_post_load_device(void)
diff --git a/hw/net/vhost_net-stub.c b/hw/net/vhost_net-stub.c
new file mode 100644
index 0000000..aac0e98
--- /dev/null
+++ b/hw/net/vhost_net-stub.c
@@ -0,0 +1,92 @@
+/*
+ * vhost-net support
+ *
+ * Copyright Red Hat, Inc. 2010
+ *
+ * Authors:
+ * Michael S. Tsirkin <mst@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 "net/net.h"
+#include "net/tap.h"
+#include "net/vhost-user.h"
+
+#include "hw/virtio/virtio-net.h"
+#include "net/vhost_net.h"
+#include "qemu/error-report.h"
+
+
+uint64_t vhost_net_get_max_queues(VHostNetState *net)
+{
+ return 1;
+}
+
+struct vhost_net *vhost_net_init(VhostNetOptions *options)
+{
+ error_report("vhost-net support is not compiled in");
+ return NULL;
+}
+
+int vhost_net_start(VirtIODevice *dev,
+ NetClientState *ncs,
+ int total_queues)
+{
+ return -ENOSYS;
+}
+void vhost_net_stop(VirtIODevice *dev,
+ NetClientState *ncs,
+ int total_queues)
+{
+}
+
+void vhost_net_cleanup(struct vhost_net *net)
+{
+}
+
+uint64_t vhost_net_get_features(struct vhost_net *net, uint64_t features)
+{
+ return features;
+}
+
+void vhost_net_ack_features(struct vhost_net *net, uint64_t features)
+{
+}
+
+uint64_t vhost_net_get_acked_features(VHostNetState *net)
+{
+ return 0;
+}
+
+bool vhost_net_virtqueue_pending(VHostNetState *net, int idx)
+{
+ return false;
+}
+
+void vhost_net_virtqueue_mask(VHostNetState *net, VirtIODevice *dev,
+ int idx, bool mask)
+{
+}
+
+int vhost_net_notify_migration_done(struct vhost_net *net, char* mac_addr)
+{
+ return -1;
+}
+
+VHostNetState *get_vhost_net(NetClientState *nc)
+{
+ return 0;
+}
+
+int vhost_set_vring_enable(NetClientState *nc, int enable)
+{
+ return 0;
+}
+
+int vhost_net_set_mtu(struct vhost_net *net, uint16_t mtu)
+{
+ return 0;
+}
diff --git a/hw/net/vhost_net.c b/hw/net/vhost_net.c
index e037db6..be3cc88 100644
--- a/hw/net/vhost_net.c
+++ b/hw/net/vhost_net.c
@@ -18,17 +18,13 @@
#include "net/tap.h"
#include "net/vhost-user.h"
+#include "standard-headers/linux/vhost_types.h"
#include "hw/virtio/virtio-net.h"
#include "net/vhost_net.h"
#include "qemu/error-report.h"
-#ifdef CONFIG_VHOST_NET
-#include <linux/vhost.h>
#include <sys/socket.h>
-#include <linux/kvm.h>
-#include <netpacket/packet.h>
-#include <net/ethernet.h>
#include <net/if.h>
#include <netinet/in.h>
@@ -136,7 +132,7 @@
return tap_get_fd(backend);
default:
fprintf(stderr, "vhost-net requires tap backend\n");
- return -EBADFD;
+ return -ENOSYS;
}
}
@@ -194,6 +190,7 @@
}
/* Set sane init value. Override when guest acks. */
+#ifdef CONFIG_VHOST_NET_USER
if (net->nc->info->type == NET_CLIENT_DRIVER_VHOST_USER) {
features = vhost_user_get_acked_features(net->nc);
if (~net->dev.features & features) {
@@ -203,6 +200,7 @@
goto fail;
}
}
+#endif
vhost_net_ack_features(net, features);
@@ -414,10 +412,12 @@
case NET_CLIENT_DRIVER_TAP:
vhost_net = tap_get_vhost_net(nc);
break;
+#ifdef CONFIG_VHOST_NET_USER
case NET_CLIENT_DRIVER_VHOST_USER:
vhost_net = vhost_user_get_vhost_net(nc);
assert(vhost_net);
break;
+#endif
default:
break;
}
@@ -449,76 +449,3 @@
return vhost_ops->vhost_net_set_mtu(&net->dev, mtu);
}
-
-#else
-uint64_t vhost_net_get_max_queues(VHostNetState *net)
-{
- return 1;
-}
-
-struct vhost_net *vhost_net_init(VhostNetOptions *options)
-{
- error_report("vhost-net support is not compiled in");
- return NULL;
-}
-
-int vhost_net_start(VirtIODevice *dev,
- NetClientState *ncs,
- int total_queues)
-{
- return -ENOSYS;
-}
-void vhost_net_stop(VirtIODevice *dev,
- NetClientState *ncs,
- int total_queues)
-{
-}
-
-void vhost_net_cleanup(struct vhost_net *net)
-{
-}
-
-uint64_t vhost_net_get_features(struct vhost_net *net, uint64_t features)
-{
- return features;
-}
-
-void vhost_net_ack_features(struct vhost_net *net, uint64_t features)
-{
-}
-
-uint64_t vhost_net_get_acked_features(VHostNetState *net)
-{
- return 0;
-}
-
-bool vhost_net_virtqueue_pending(VHostNetState *net, int idx)
-{
- return false;
-}
-
-void vhost_net_virtqueue_mask(VHostNetState *net, VirtIODevice *dev,
- int idx, bool mask)
-{
-}
-
-int vhost_net_notify_migration_done(struct vhost_net *net, char* mac_addr)
-{
- return -1;
-}
-
-VHostNetState *get_vhost_net(NetClientState *nc)
-{
- return 0;
-}
-
-int vhost_set_vring_enable(NetClientState *nc, int enable)
-{
- return 0;
-}
-
-int vhost_net_set_mtu(struct vhost_net *net, uint16_t mtu)
-{
- return 0;
-}
-#endif
diff --git a/hw/net/virtio-net.c b/hw/net/virtio-net.c
index 3f319ef..7e2c2a6 100644
--- a/hw/net/virtio-net.c
+++ b/hw/net/virtio-net.c
@@ -21,12 +21,14 @@
#include "qemu/timer.h"
#include "hw/virtio/virtio-net.h"
#include "net/vhost_net.h"
+#include "net/announce.h"
#include "hw/virtio/virtio-bus.h"
#include "qapi/error.h"
#include "qapi/qapi-events-net.h"
#include "hw/virtio/virtio-access.h"
#include "migration/misc.h"
#include "standard-headers/linux/ethtool.h"
+#include "trace.h"
#define VIRTIO_NET_VM_VERSION 11
@@ -82,29 +84,17 @@
#endif
-/*
- * Calculate the number of bytes up to and including the given 'field' of
- * 'container'.
- */
-#define endof(container, field) \
- (offsetof(container, field) + sizeof_field(container, field))
-
-typedef struct VirtIOFeature {
- uint64_t flags;
- size_t end;
-} VirtIOFeature;
-
static VirtIOFeature feature_sizes[] = {
{.flags = 1ULL << VIRTIO_NET_F_MAC,
- .end = endof(struct virtio_net_config, mac)},
+ .end = virtio_endof(struct virtio_net_config, mac)},
{.flags = 1ULL << VIRTIO_NET_F_STATUS,
- .end = endof(struct virtio_net_config, status)},
+ .end = virtio_endof(struct virtio_net_config, status)},
{.flags = 1ULL << VIRTIO_NET_F_MQ,
- .end = endof(struct virtio_net_config, max_virtqueue_pairs)},
+ .end = virtio_endof(struct virtio_net_config, max_virtqueue_pairs)},
{.flags = 1ULL << VIRTIO_NET_F_MTU,
- .end = endof(struct virtio_net_config, mtu)},
+ .end = virtio_endof(struct virtio_net_config, mtu)},
{.flags = 1ULL << VIRTIO_NET_F_SPEED_DUPLEX,
- .end = endof(struct virtio_net_config, duplex)},
+ .end = virtio_endof(struct virtio_net_config, duplex)},
{}
};
@@ -160,14 +150,42 @@
(n->status & VIRTIO_NET_S_LINK_UP) && vdev->vm_running;
}
+static void virtio_net_announce_notify(VirtIONet *net)
+{
+ VirtIODevice *vdev = VIRTIO_DEVICE(net);
+ trace_virtio_net_announce_notify();
+
+ net->status |= VIRTIO_NET_S_ANNOUNCE;
+ virtio_notify_config(vdev);
+}
+
static void virtio_net_announce_timer(void *opaque)
{
VirtIONet *n = opaque;
+ trace_virtio_net_announce_timer(n->announce_timer.round);
+
+ n->announce_timer.round--;
+ virtio_net_announce_notify(n);
+}
+
+static void virtio_net_announce(NetClientState *nc)
+{
+ VirtIONet *n = qemu_get_nic_opaque(nc);
VirtIODevice *vdev = VIRTIO_DEVICE(n);
- n->announce_counter--;
- n->status |= VIRTIO_NET_S_ANNOUNCE;
- virtio_notify_config(vdev);
+ /*
+ * Make sure the virtio migration announcement timer isn't running
+ * If it is, let it trigger announcement so that we do not cause
+ * confusion.
+ */
+ if (n->announce_timer.round) {
+ return;
+ }
+
+ if (virtio_vdev_has_feature(vdev, VIRTIO_NET_F_GUEST_ANNOUNCE) &&
+ virtio_vdev_has_feature(vdev, VIRTIO_NET_F_CTRL_VQ)) {
+ virtio_net_announce_notify(n);
+ }
}
static void virtio_net_vhost_status(VirtIONet *n, uint8_t status)
@@ -479,8 +497,8 @@
n->nobcast = 0;
/* multiqueue is disabled by default */
n->curr_queues = 1;
- timer_del(n->announce_timer);
- n->announce_counter = 0;
+ timer_del(n->announce_timer.tm);
+ n->announce_timer.round = 0;
n->status &= ~VIRTIO_NET_S_ANNOUNCE;
/* Flush any MAC and VLAN filter table state */
@@ -976,13 +994,12 @@
static int virtio_net_handle_announce(VirtIONet *n, uint8_t cmd,
struct iovec *iov, unsigned int iov_cnt)
{
+ trace_virtio_net_handle_announce(n->announce_timer.round);
if (cmd == VIRTIO_NET_CTRL_ANNOUNCE_ACK &&
n->status & VIRTIO_NET_S_ANNOUNCE) {
n->status &= ~VIRTIO_NET_S_ANNOUNCE;
- if (n->announce_counter) {
- timer_mod(n->announce_timer,
- qemu_clock_get_ms(QEMU_CLOCK_VIRTUAL) +
- self_announce_delay(n->announce_counter));
+ if (n->announce_timer.round) {
+ qemu_announce_timer_step(&n->announce_timer);
}
return VIRTIO_NET_OK;
} else {
@@ -2298,6 +2315,7 @@
VirtIODevice *vdev = VIRTIO_DEVICE(n);
int i, link_down;
+ trace_virtio_net_post_load_device();
virtio_net_set_mrg_rx_bufs(n, n->mergeable_rx_bufs,
virtio_vdev_has_feature(vdev,
VIRTIO_F_VERSION_1));
@@ -2334,8 +2352,15 @@
if (virtio_vdev_has_feature(vdev, VIRTIO_NET_F_GUEST_ANNOUNCE) &&
virtio_vdev_has_feature(vdev, VIRTIO_NET_F_CTRL_VQ)) {
- n->announce_counter = SELF_ANNOUNCE_ROUNDS;
- timer_mod(n->announce_timer, qemu_clock_get_ms(QEMU_CLOCK_VIRTUAL));
+ qemu_announce_timer_reset(&n->announce_timer, migrate_announce_params(),
+ QEMU_CLOCK_VIRTUAL,
+ virtio_net_announce_timer, n);
+ if (n->announce_timer.round) {
+ timer_mod(n->announce_timer.tm,
+ qemu_clock_get_ms(n->announce_timer.type));
+ } else {
+ qemu_announce_timer_del(&n->announce_timer);
+ }
}
return 0;
@@ -2558,6 +2583,7 @@
.receive = virtio_net_receive,
.link_status_changed = virtio_net_set_link_status,
.query_rx_filter = virtio_net_query_rxfilter,
+ .announce = virtio_net_announce,
};
static bool virtio_net_guest_notifier_pending(VirtIODevice *vdev, int idx)
@@ -2580,15 +2606,10 @@
static void virtio_net_set_config_size(VirtIONet *n, uint64_t host_features)
{
- int i, config_size = 0;
virtio_add_feature(&host_features, VIRTIO_NET_F_MAC);
- for (i = 0; feature_sizes[i].flags != 0; i++) {
- if (host_features & feature_sizes[i].flags) {
- config_size = MAX(feature_sizes[i].end, config_size);
- }
- }
- n->config_size = config_size;
+ n->config_size = virtio_feature_get_config_size(feature_sizes,
+ host_features);
}
void virtio_net_set_netclient_name(VirtIONet *n, const char *name,
@@ -2696,8 +2717,10 @@
qemu_macaddr_default_if_unset(&n->nic_conf.macaddr);
memcpy(&n->mac[0], &n->nic_conf.macaddr, sizeof(n->mac));
n->status = VIRTIO_NET_S_LINK_UP;
- n->announce_timer = timer_new_ms(QEMU_CLOCK_VIRTUAL,
- virtio_net_announce_timer, n);
+ qemu_announce_timer_reset(&n->announce_timer, migrate_announce_params(),
+ QEMU_CLOCK_VIRTUAL,
+ virtio_net_announce_timer, n);
+ n->announce_timer.round = 0;
if (n->netclient_type) {
/*
@@ -2760,8 +2783,7 @@
virtio_net_del_queue(n, i);
}
- timer_del(n->announce_timer);
- timer_free(n->announce_timer);
+ qemu_announce_timer_del(&n->announce_timer);
g_free(n->vqs);
qemu_del_nic(n->nic);
virtio_net_rsc_cleanup(n);
diff --git a/hw/nvram/eeprom_at24c.c b/hw/nvram/eeprom_at24c.c
index 27cd01e..d1456da 100644
--- a/hw/nvram/eeprom_at24c.c
+++ b/hw/nvram/eeprom_at24c.c
@@ -74,10 +74,10 @@
}
static
-int at24c_eeprom_recv(I2CSlave *s)
+uint8_t at24c_eeprom_recv(I2CSlave *s)
{
EEPROMState *ee = AT24C_EE(s);
- int ret;
+ uint8_t ret;
ret = ee->mem[ee->cur];
diff --git a/hw/pci/pci.c b/hw/pci/pci.c
index c9fc2fb..35451c1 100644
--- a/hw/pci/pci.c
+++ b/hw/pci/pci.c
@@ -428,7 +428,8 @@
void pci_root_bus_cleanup(PCIBus *bus)
{
pci_bus_uninit(bus);
- object_unparent(OBJECT(bus));
+ /* the caller of the unplug hotplug handler will delete this device */
+ object_property_set_bool(OBJECT(bus), false, "realized", NULL);
}
void pci_bus_irqs(PCIBus *bus, pci_set_irq_fn set_irq, pci_map_irq_fn map_irq,
diff --git a/hw/pci/pcie.c b/hw/pci/pcie.c
index 3f7c366..640f678 100644
--- a/hw/pci/pcie.c
+++ b/hw/pci/pcie.c
@@ -450,7 +450,7 @@
void pcie_cap_slot_unplug_cb(HotplugHandler *hotplug_dev, DeviceState *dev,
Error **errp)
{
- object_unparent(OBJECT(dev));
+ object_property_set_bool(OBJECT(dev), false, "realized", NULL);
}
static void pcie_unplug_device(PCIBus *bus, PCIDevice *dev, void *opaque)
@@ -458,6 +458,7 @@
HotplugHandler *hotplug_ctrl = qdev_get_hotplug_handler(DEVICE(dev));
hotplug_handler_unplug(hotplug_ctrl, DEVICE(dev), &error_abort);
+ object_unparent(OBJECT(dev));
}
void pcie_cap_slot_unplug_request_cb(HotplugHandler *hotplug_dev,
@@ -834,9 +835,12 @@
/*
* Sync the PCIe Link Status negotiated speed and width of a bridge with the
* downstream device. If downstream device is not present, re-write with the
- * Link Capability fields. Limit width and speed to bridge capabilities for
- * compatibility. Use config_read to access the downstream device since it
- * could be an assigned device with volatile link information.
+ * Link Capability fields. If downstream device reports invalid width or
+ * speed, replace with minimum values (LnkSta fields are RsvdZ on VFs but such
+ * values interfere with PCIe native hotplug detecting new devices). Limit
+ * width and speed to bridge capabilities for compatibility. Use config_read
+ * to access the downstream device since it could be an assigned device with
+ * volatile link information.
*/
void pcie_sync_bridge_lnk(PCIDevice *bridge_dev)
{
@@ -856,11 +860,15 @@
if ((lnksta & PCI_EXP_LNKSTA_NLW) > (lnkcap & PCI_EXP_LNKCAP_MLW)) {
lnksta &= ~PCI_EXP_LNKSTA_NLW;
lnksta |= lnkcap & PCI_EXP_LNKCAP_MLW;
+ } else if (!(lnksta & PCI_EXP_LNKSTA_NLW)) {
+ lnksta |= QEMU_PCI_EXP_LNKSTA_NLW(QEMU_PCI_EXP_LNK_X1);
}
if ((lnksta & PCI_EXP_LNKSTA_CLS) > (lnkcap & PCI_EXP_LNKCAP_SLS)) {
lnksta &= ~PCI_EXP_LNKSTA_CLS;
lnksta |= lnkcap & PCI_EXP_LNKCAP_SLS;
+ } else if (!(lnksta & PCI_EXP_LNKSTA_CLS)) {
+ lnksta |= QEMU_PCI_EXP_LNKSTA_CLS(QEMU_PCI_EXP_LNK_2_5GT);
}
}
diff --git a/hw/pci/shpc.c b/hw/pci/shpc.c
index 52ccdc5..49bbb84 100644
--- a/hw/pci/shpc.c
+++ b/hw/pci/shpc.c
@@ -249,6 +249,7 @@
hotplug_ctrl = qdev_get_hotplug_handler(DEVICE(affected_dev));
hotplug_handler_unplug(hotplug_ctrl, DEVICE(affected_dev),
&error_abort);
+ object_unparent(OBJECT(affected_dev));
}
}
}
@@ -546,7 +547,7 @@
void shpc_device_unplug_cb(HotplugHandler *hotplug_dev, DeviceState *dev,
Error **errp)
{
- object_unparent(OBJECT(dev));
+ object_property_set_bool(OBJECT(dev), false, "realized", NULL);
}
void shpc_device_unplug_request_cb(HotplugHandler *hotplug_dev,
diff --git a/hw/ppc/mac_newworld.c b/hw/ppc/mac_newworld.c
index 9846105..97e8817 100644
--- a/hw/ppc/mac_newworld.c
+++ b/hw/ppc/mac_newworld.c
@@ -564,8 +564,7 @@
return NULL;
}
-
-static int core99_kvm_type(const char *arg)
+static int core99_kvm_type(MachineState *machine, const char *arg)
{
/* Always force PR KVM */
return 2;
diff --git a/hw/ppc/mac_oldworld.c b/hw/ppc/mac_oldworld.c
index 284431d..cc1e463 100644
--- a/hw/ppc/mac_oldworld.c
+++ b/hw/ppc/mac_oldworld.c
@@ -420,7 +420,7 @@
return NULL;
}
-static int heathrow_kvm_type(const char *arg)
+static int heathrow_kvm_type(MachineState *machine, const char *arg)
{
/* Always force PR KVM */
return 2;
diff --git a/hw/ppc/pnv.c b/hw/ppc/pnv.c
index da54086..3d5dfef 100644
--- a/hw/ppc/pnv.c
+++ b/hw/ppc/pnv.c
@@ -47,14 +47,16 @@
#include <libfdt.h>
-#define FDT_MAX_SIZE 0x00100000
+#define FDT_MAX_SIZE (1 * MiB)
#define FW_FILE_NAME "skiboot.lid"
#define FW_LOAD_ADDR 0x0
-#define FW_MAX_SIZE 0x00400000
+#define FW_MAX_SIZE (4 * MiB)
#define KERNEL_LOAD_ADDR 0x20000000
+#define KERNEL_MAX_SIZE (256 * MiB)
#define INITRD_LOAD_ADDR 0x60000000
+#define INITRD_MAX_SIZE (256 * MiB)
static const char *pnv_chip_core_typename(const PnvChip *o)
{
@@ -588,7 +590,7 @@
long kernel_size;
kernel_size = load_image_targphys(machine->kernel_filename,
- KERNEL_LOAD_ADDR, 0x2000000);
+ KERNEL_LOAD_ADDR, KERNEL_MAX_SIZE);
if (kernel_size < 0) {
error_report("Could not load kernel '%s'",
machine->kernel_filename);
@@ -600,7 +602,7 @@
if (machine->initrd_filename) {
pnv->initrd_base = INITRD_LOAD_ADDR;
pnv->initrd_size = load_image_targphys(machine->initrd_filename,
- pnv->initrd_base, 0x10000000); /* 128MB max */
+ pnv->initrd_base, INITRD_MAX_SIZE);
if (pnv->initrd_size < 0) {
error_report("Could not load initial ram disk '%s'",
machine->initrd_filename);
@@ -736,18 +738,18 @@
{
Pnv8Chip *chip8 = PNV8_CHIP(obj);
- object_initialize(&chip8->psi, sizeof(chip8->psi), TYPE_PNV_PSI);
- object_property_add_child(obj, "psi", OBJECT(&chip8->psi), NULL);
+ object_initialize_child(obj, "psi", &chip8->psi, sizeof(chip8->psi),
+ TYPE_PNV_PSI, &error_abort, NULL);
object_property_add_const_link(OBJECT(&chip8->psi), "xics",
OBJECT(qdev_get_machine()), &error_abort);
- object_initialize(&chip8->lpc, sizeof(chip8->lpc), TYPE_PNV_LPC);
- object_property_add_child(obj, "lpc", OBJECT(&chip8->lpc), NULL);
+ object_initialize_child(obj, "lpc", &chip8->lpc, sizeof(chip8->lpc),
+ TYPE_PNV_LPC, &error_abort, NULL);
object_property_add_const_link(OBJECT(&chip8->lpc), "psi",
OBJECT(&chip8->psi), &error_abort);
- object_initialize(&chip8->occ, sizeof(chip8->occ), TYPE_PNV_OCC);
- object_property_add_child(obj, "occ", OBJECT(&chip8->occ), NULL);
+ object_initialize_child(obj, "occ", &chip8->occ, sizeof(chip8->occ),
+ TYPE_PNV_OCC, &error_abort, NULL);
object_property_add_const_link(OBJECT(&chip8->occ), "psi",
OBJECT(&chip8->psi), &error_abort);
}
diff --git a/hw/ppc/pnv_psi.c b/hw/ppc/pnv_psi.c
index 8ced095..44bc0cb 100644
--- a/hw/ppc/pnv_psi.c
+++ b/hw/ppc/pnv_psi.c
@@ -444,8 +444,8 @@
{
PnvPsi *psi = PNV_PSI(obj);
- object_initialize(&psi->ics, sizeof(psi->ics), TYPE_ICS_SIMPLE);
- object_property_add_child(obj, "ics-psi", OBJECT(&psi->ics), NULL);
+ object_initialize_child(obj, "ics-psi", &psi->ics, sizeof(psi->ics),
+ TYPE_ICS_SIMPLE, &error_abort, NULL);
}
static const uint8_t irq_to_xivr[] = {
diff --git a/hw/ppc/ppc.c b/hw/ppc/ppc.c
index cffdc39..d1e3d4c 100644
--- a/hw/ppc/ppc.c
+++ b/hw/ppc/ppc.c
@@ -306,6 +306,48 @@
env->irq_inputs = (void **)qemu_allocate_irqs(&power7_set_irq, cpu,
POWER7_INPUT_NB);
}
+
+/* POWER9 internal IRQ controller */
+static void power9_set_irq(void *opaque, int pin, int level)
+{
+ PowerPCCPU *cpu = opaque;
+ CPUPPCState *env = &cpu->env;
+
+ LOG_IRQ("%s: env %p pin %d level %d\n", __func__,
+ env, pin, level);
+
+ switch (pin) {
+ case POWER9_INPUT_INT:
+ /* Level sensitive - active high */
+ LOG_IRQ("%s: set the external IRQ state to %d\n",
+ __func__, level);
+ ppc_set_irq(cpu, PPC_INTERRUPT_EXT, level);
+ break;
+ case POWER9_INPUT_HINT:
+ /* Level sensitive - active high */
+ LOG_IRQ("%s: set the external IRQ state to %d\n",
+ __func__, level);
+ ppc_set_irq(cpu, PPC_INTERRUPT_HVIRT, level);
+ break;
+ default:
+ /* Unknown pin - do nothing */
+ LOG_IRQ("%s: unknown IRQ pin %d\n", __func__, pin);
+ return;
+ }
+ if (level) {
+ env->irq_input_state |= 1 << pin;
+ } else {
+ env->irq_input_state &= ~(1 << pin);
+ }
+}
+
+void ppcPOWER9_irq_init(PowerPCCPU *cpu)
+{
+ CPUPPCState *env = &cpu->env;
+
+ env->irq_inputs = (void **)qemu_allocate_irqs(&power9_set_irq, cpu,
+ POWER9_INPUT_NB);
+}
#endif /* defined(TARGET_PPC64) */
void ppc40x_core_reset(PowerPCCPU *cpu)
@@ -776,7 +818,7 @@
* interrupts in a PM state. Not only they don't cause a
* wakeup but they also get effectively discarded.
*/
- if (!env->in_pm_state) {
+ if (!env->resume_as_sreset) {
ppc_set_irq(cpu, PPC_INTERRUPT_HDECR, 1);
}
}
diff --git a/hw/ppc/sam460ex.c b/hw/ppc/sam460ex.c
index 75250d4..d455c4b 100644
--- a/hw/ppc/sam460ex.c
+++ b/hw/ppc/sam460ex.c
@@ -34,7 +34,7 @@
#include "hw/sysbus.h"
#include "hw/char/serial.h"
#include "hw/i2c/ppc4xx_i2c.h"
-#include "hw/i2c/smbus.h"
+#include "hw/i2c/smbus_eeprom.h"
#include "hw/usb/hcd-ehci.h"
#include "hw/ppc/fdt.h"
diff --git a/hw/ppc/spapr.c b/hw/ppc/spapr.c
index abf9ebc..9e01226 100644
--- a/hw/ppc/spapr.c
+++ b/hw/ppc/spapr.c
@@ -1247,13 +1247,30 @@
* Add info to guest to indentify which host is it being run on
* and what is the uuid of the guest
*/
- if (kvmppc_get_host_model(&buf)) {
- _FDT(fdt_setprop_string(fdt, 0, "host-model", buf));
- g_free(buf);
+ if (spapr->host_model && !g_str_equal(spapr->host_model, "none")) {
+ if (g_str_equal(spapr->host_model, "passthrough")) {
+ /* -M host-model=passthrough */
+ if (kvmppc_get_host_model(&buf)) {
+ _FDT(fdt_setprop_string(fdt, 0, "host-model", buf));
+ g_free(buf);
+ }
+ } else {
+ /* -M host-model=<user-string> */
+ _FDT(fdt_setprop_string(fdt, 0, "host-model", spapr->host_model));
+ }
}
- if (kvmppc_get_host_serial(&buf)) {
- _FDT(fdt_setprop_string(fdt, 0, "host-serial", buf));
- g_free(buf);
+
+ if (spapr->host_serial && !g_str_equal(spapr->host_serial, "none")) {
+ if (g_str_equal(spapr->host_serial, "passthrough")) {
+ /* -M host-serial=passthrough */
+ if (kvmppc_get_host_serial(&buf)) {
+ _FDT(fdt_setprop_string(fdt, 0, "host-serial", buf));
+ g_free(buf);
+ }
+ } else {
+ /* -M host-serial=<user-string> */
+ _FDT(fdt_setprop_string(fdt, 0, "host-serial", spapr->host_serial));
+ }
}
buf = qemu_uuid_unparse_strdup(&qemu_uuid);
@@ -1295,7 +1312,7 @@
QLIST_FOREACH(phb, &spapr->phbs, list) {
ret = spapr_populate_pci_dt(phb, PHANDLE_INTC, fdt,
- spapr->irq->nr_msis);
+ spapr->irq->nr_msis, NULL);
if (ret < 0) {
error_report("couldn't setup PCI devices in fdt");
exit(1);
@@ -1348,6 +1365,14 @@
exit(1);
}
+ if (smc->dr_phb_enabled) {
+ ret = spapr_drc_populate_dt(fdt, 0, NULL, SPAPR_DR_CONNECTOR_TYPE_PHB);
+ if (ret < 0) {
+ error_report("Couldn't set up PHB DR device tree properties");
+ exit(1);
+ }
+ }
+
return fdt;
}
@@ -1372,11 +1397,44 @@
}
}
-static uint64_t spapr_get_patbe(PPCVirtualHypervisor *vhyp)
+struct LPCRSyncState {
+ target_ulong value;
+ target_ulong mask;
+};
+
+static void do_lpcr_sync(CPUState *cs, run_on_cpu_data arg)
+{
+ struct LPCRSyncState *s = arg.host_ptr;
+ PowerPCCPU *cpu = POWERPC_CPU(cs);
+ CPUPPCState *env = &cpu->env;
+ target_ulong lpcr;
+
+ cpu_synchronize_state(cs);
+ lpcr = env->spr[SPR_LPCR];
+ lpcr &= ~s->mask;
+ lpcr |= s->value;
+ ppc_store_lpcr(cpu, lpcr);
+}
+
+void spapr_set_all_lpcrs(target_ulong value, target_ulong mask)
+{
+ CPUState *cs;
+ struct LPCRSyncState s = {
+ .value = value,
+ .mask = mask
+ };
+ CPU_FOREACH(cs) {
+ run_on_cpu(cs, do_lpcr_sync, RUN_ON_CPU_HOST_PTR(&s));
+ }
+}
+
+static void spapr_get_pate(PPCVirtualHypervisor *vhyp, ppc_v3_pate_t *entry)
{
sPAPRMachineState *spapr = SPAPR_MACHINE(vhyp);
- return spapr->patb_entry;
+ /* Copy PATE1:GR into PATE0:HR */
+ entry->dw0 = spapr->patb_entry & PATE0_HR;
+ entry->dw1 = spapr->patb_entry;
}
#define HPTE(_table, _i) (void *)(((uint64_t *)(_table)) + ((_i) * 2))
@@ -1476,8 +1534,25 @@
if (!spapr->htab) {
kvmppc_write_hpte(ptex, pte0, pte1);
} else {
- stq_p(spapr->htab + offset, pte0);
- stq_p(spapr->htab + offset + HASH_PTE_SIZE_64 / 2, pte1);
+ if (pte0 & HPTE64_V_VALID) {
+ stq_p(spapr->htab + offset + HASH_PTE_SIZE_64 / 2, pte1);
+ /*
+ * When setting valid, we write PTE1 first. This ensures
+ * proper synchronization with the reading code in
+ * ppc_hash64_pteg_search()
+ */
+ smp_wmb();
+ stq_p(spapr->htab + offset, pte0);
+ } else {
+ stq_p(spapr->htab + offset, pte0);
+ /*
+ * When clearing it we set PTE0 first. This ensures proper
+ * synchronization with the reading code in
+ * ppc_hash64_pteg_search()
+ */
+ smp_wmb();
+ stq_p(spapr->htab + offset + HASH_PTE_SIZE_64 / 2, pte1);
+ }
}
}
@@ -1548,7 +1623,7 @@
}
}
/* We're setting up a hash table, so that means we're not radix */
- spapr->patb_entry = 0;
+ spapr_set_all_lpcrs(0, LPCR_HR | LPCR_UPRT);
}
void spapr_setup_hpt_and_vrma(sPAPRMachineState *spapr)
@@ -1602,16 +1677,21 @@
if (kvm_enabled() && kvmppc_has_cap_mmu_radix() &&
ppc_type_check_compat(machine->cpu_type, CPU_POWERPC_LOGICAL_3_00, 0,
spapr->max_compat_pvr)) {
- /* If using KVM with radix mode available, VCPUs can be started
+ /*
+ * If using KVM with radix mode available, VCPUs can be started
* without a HPT because KVM will start them in radix mode.
- * Set the GR bit in PATB so that we know there is no HPT. */
- spapr->patb_entry = PATBE1_GR;
+ * Set the GR bit in PATE so that we know there is no HPT.
+ */
+ spapr->patb_entry = PATE1_GR;
+ spapr_set_all_lpcrs(LPCR_HR | LPCR_UPRT, LPCR_HR | LPCR_UPRT);
} else {
spapr_setup_hpt_and_vrma(spapr);
}
- /* if this reset wasn't generated by CAS, we should reset our
- * negotiated options and start from scratch */
+ /*
+ * If this reset wasn't generated by CAS, we should reset our
+ * negotiated options and start from scratch
+ */
if (!spapr->cas_reboot) {
spapr_ovec_cleanup(spapr->ov5_cas);
spapr->ov5_cas = spapr_ovec_new();
@@ -1696,9 +1776,9 @@
static void spapr_rtc_create(sPAPRMachineState *spapr)
{
- object_initialize(&spapr->rtc, sizeof(spapr->rtc), TYPE_SPAPR_RTC);
- object_property_add_child(OBJECT(spapr), "rtc", OBJECT(&spapr->rtc),
- &error_fatal);
+ object_initialize_child(OBJECT(spapr), "rtc",
+ &spapr->rtc, sizeof(spapr->rtc), TYPE_SPAPR_RTC,
+ &error_fatal, NULL);
object_property_set_bool(OBJECT(&spapr->rtc), true, "realized",
&error_fatal);
object_property_add_alias(OBJECT(spapr), "rtc-time", OBJECT(&spapr->rtc),
@@ -1761,9 +1841,16 @@
if (kvm_enabled() && spapr->patb_entry) {
PowerPCCPU *cpu = POWERPC_CPU(first_cpu);
- bool radix = !!(spapr->patb_entry & PATBE1_GR);
+ bool radix = !!(spapr->patb_entry & PATE1_GR);
bool gtse = !!(cpu->env.spr[SPR_LPCR] & LPCR_GTSE);
+ /*
+ * Update LPCR:HR and UPRT as they may not be set properly in
+ * the stream
+ */
+ spapr_set_all_lpcrs(radix ? (LPCR_HR | LPCR_UPRT) : 0,
+ LPCR_HR | LPCR_UPRT);
+
err = kvmppc_configure_v3_mmu(cpu, radix, gtse, spapr->patb_entry);
if (err) {
error_report("Process table config unsupported by the host");
@@ -2796,6 +2883,19 @@
/* We always have at least the nvram device on VIO */
spapr_create_nvram(spapr);
+ /*
+ * Setup hotplug / dynamic-reconfiguration connectors. top-level
+ * connectors (described in root DT node's "ibm,drc-types" property)
+ * are pre-initialized here. additional child connectors (such as
+ * connectors for a PHBs PCI slots) are added as needed during their
+ * parent's realization.
+ */
+ if (smc->dr_phb_enabled) {
+ for (i = 0; i < SPAPR_MAX_PHBS; i++) {
+ spapr_dr_connector_new(OBJECT(machine), TYPE_SPAPR_DRC_PHB, i);
+ }
+ }
+
/* Set up PCI */
spapr_pci_rtas_init();
@@ -2909,6 +3009,9 @@
register_savevm_live(NULL, "spapr/htab", -1, 1,
&savevm_htab_handlers, spapr);
+ qbus_set_hotplug_handler(sysbus_get_default(), OBJECT(machine),
+ &error_fatal);
+
qemu_register_boot_set(spapr_boot_set, spapr);
if (kvm_enabled()) {
@@ -2920,7 +3023,7 @@
}
}
-static int spapr_kvm_type(const char *vm_type)
+static int spapr_kvm_type(MachineState *machine, const char *vm_type)
{
if (!vm_type) {
return 0;
@@ -3144,6 +3247,36 @@
}
}
+static char *spapr_get_host_model(Object *obj, Error **errp)
+{
+ sPAPRMachineState *spapr = SPAPR_MACHINE(obj);
+
+ return g_strdup(spapr->host_model);
+}
+
+static void spapr_set_host_model(Object *obj, const char *value, Error **errp)
+{
+ sPAPRMachineState *spapr = SPAPR_MACHINE(obj);
+
+ g_free(spapr->host_model);
+ spapr->host_model = g_strdup(value);
+}
+
+static char *spapr_get_host_serial(Object *obj, Error **errp)
+{
+ sPAPRMachineState *spapr = SPAPR_MACHINE(obj);
+
+ return g_strdup(spapr->host_serial);
+}
+
+static void spapr_set_host_serial(Object *obj, const char *value, Error **errp)
+{
+ sPAPRMachineState *spapr = SPAPR_MACHINE(obj);
+
+ g_free(spapr->host_serial);
+ spapr->host_serial = g_strdup(value);
+}
+
static void spapr_instance_init(Object *obj)
{
sPAPRMachineState *spapr = SPAPR_MACHINE(obj);
@@ -3189,6 +3322,17 @@
object_property_set_description(obj, "ic-mode",
"Specifies the interrupt controller mode (xics, xive, dual)",
NULL);
+
+ object_property_add_str(obj, "host-model",
+ spapr_get_host_model, spapr_set_host_model,
+ &error_abort);
+ object_property_set_description(obj, "host-model",
+ "Set host's model-id to use - none|passthrough|string", &error_abort);
+ object_property_add_str(obj, "host-serial",
+ spapr_get_host_serial, spapr_set_host_serial,
+ &error_abort);
+ object_property_set_description(obj, "host-serial",
+ "Set host's system-id to use - none|passthrough|string", &error_abort);
}
static void spapr_machine_finalizefn(Object *obj)
@@ -3213,14 +3357,26 @@
}
}
+int spapr_lmb_dt_populate(sPAPRDRConnector *drc, sPAPRMachineState *spapr,
+ void *fdt, int *fdt_start_offset, Error **errp)
+{
+ uint64_t addr;
+ uint32_t node;
+
+ addr = spapr_drc_index(drc) * SPAPR_MEMORY_BLOCK_SIZE;
+ node = object_property_get_uint(OBJECT(drc->dev), PC_DIMM_NODE_PROP,
+ &error_abort);
+ *fdt_start_offset = spapr_populate_memory_node(fdt, node, addr,
+ SPAPR_MEMORY_BLOCK_SIZE);
+ return 0;
+}
+
static void spapr_add_lmbs(DeviceState *dev, uint64_t addr_start, uint64_t size,
- uint32_t node, bool dedicated_hp_event_source,
- Error **errp)
+ bool dedicated_hp_event_source, Error **errp)
{
sPAPRDRConnector *drc;
uint32_t nr_lmbs = size/SPAPR_MEMORY_BLOCK_SIZE;
- int i, fdt_offset, fdt_size;
- void *fdt;
+ int i;
uint64_t addr = addr_start;
bool hotplugged = spapr_drc_hotplugged(dev);
Error *local_err = NULL;
@@ -3230,11 +3386,7 @@
addr / SPAPR_MEMORY_BLOCK_SIZE);
g_assert(drc);
- fdt = create_device_tree(&fdt_size);
- fdt_offset = spapr_populate_memory_node(fdt, node, addr,
- SPAPR_MEMORY_BLOCK_SIZE);
-
- spapr_drc_attach(drc, dev, fdt, fdt_offset, &local_err);
+ spapr_drc_attach(drc, dev, &local_err);
if (local_err) {
while (addr > addr_start) {
addr -= SPAPR_MEMORY_BLOCK_SIZE;
@@ -3242,7 +3394,6 @@
addr / SPAPR_MEMORY_BLOCK_SIZE);
spapr_drc_detach(drc);
}
- g_free(fdt);
error_propagate(errp, local_err);
return;
}
@@ -3275,7 +3426,6 @@
sPAPRMachineState *ms = SPAPR_MACHINE(hotplug_dev);
PCDIMMDevice *dimm = PC_DIMM(dev);
uint64_t size, addr;
- uint32_t node;
size = memory_device_get_region_size(MEMORY_DEVICE(dev), &error_abort);
@@ -3290,10 +3440,7 @@
goto out_unplug;
}
- node = object_property_get_uint(OBJECT(dev), PC_DIMM_NODE_PROP,
- &error_abort);
- spapr_add_lmbs(dev, addr, size, node,
- spapr_ovec_test(ms->ov5_cas, OV5_HP_EVT),
+ spapr_add_lmbs(dev, addr, size, spapr_ovec_test(ms->ov5_cas, OV5_HP_EVT),
&local_err);
if (local_err) {
goto out_unplug;
@@ -3448,6 +3595,7 @@
* unplug handler chain. This can never fail.
*/
hotplug_handler_unplug(hotplug_ctrl, dev, &error_abort);
+ object_unparent(OBJECT(dev));
}
static void spapr_memory_unplug(HotplugHandler *hotplug_dev, DeviceState *dev)
@@ -3456,7 +3604,7 @@
sPAPRDIMMState *ds = spapr_pending_dimm_unplugs_find(spapr, PC_DIMM(dev));
pc_dimm_unplug(PC_DIMM(dev), MACHINE(hotplug_dev));
- object_unparent(OBJECT(dev));
+ object_property_set_bool(OBJECT(dev), false, "realized", NULL);
spapr_pending_dimm_unplugs_remove(spapr, ds);
}
@@ -3513,27 +3661,6 @@
error_propagate(errp, local_err);
}
-static void *spapr_populate_hotplug_cpu_dt(CPUState *cs, int *fdt_offset,
- sPAPRMachineState *spapr)
-{
- PowerPCCPU *cpu = POWERPC_CPU(cs);
- DeviceClass *dc = DEVICE_GET_CLASS(cs);
- int id = spapr_get_vcpu_id(cpu);
- void *fdt;
- int offset, fdt_size;
- char *nodename;
-
- fdt = create_device_tree(&fdt_size);
- nodename = g_strdup_printf("%s@%x", dc->fw_name, id);
- offset = fdt_add_subnode(fdt, 0, nodename);
-
- spapr_populate_cpu_dt(cs, fdt, offset, spapr);
- g_free(nodename);
-
- *fdt_offset = offset;
- return fdt;
-}
-
/* Callback to be called during DRC release. */
void spapr_core_release(DeviceState *dev)
{
@@ -3541,6 +3668,7 @@
/* Call the unplug handler chain. This can never fail. */
hotplug_handler_unplug(hotplug_ctrl, dev, &error_abort);
+ object_unparent(OBJECT(dev));
}
static void spapr_core_unplug(HotplugHandler *hotplug_dev, DeviceState *dev)
@@ -3563,7 +3691,7 @@
assert(core_slot);
core_slot->cpu = NULL;
- object_unparent(OBJECT(dev));
+ object_property_set_bool(OBJECT(dev), false, "realized", NULL);
}
static
@@ -3594,6 +3722,27 @@
spapr_hotplug_req_remove_by_index(drc);
}
+int spapr_core_dt_populate(sPAPRDRConnector *drc, sPAPRMachineState *spapr,
+ void *fdt, int *fdt_start_offset, Error **errp)
+{
+ sPAPRCPUCore *core = SPAPR_CPU_CORE(drc->dev);
+ CPUState *cs = CPU(core->threads[0]);
+ PowerPCCPU *cpu = POWERPC_CPU(cs);
+ DeviceClass *dc = DEVICE_GET_CLASS(cs);
+ int id = spapr_get_vcpu_id(cpu);
+ char *nodename;
+ int offset;
+
+ nodename = g_strdup_printf("%s@%x", dc->fw_name, id);
+ offset = fdt_add_subnode(fdt, 0, nodename);
+ g_free(nodename);
+
+ spapr_populate_cpu_dt(cs, fdt, offset, spapr);
+
+ *fdt_start_offset = offset;
+ return 0;
+}
+
static void spapr_core_plug(HotplugHandler *hotplug_dev, DeviceState *dev,
Error **errp)
{
@@ -3602,7 +3751,7 @@
sPAPRMachineClass *smc = SPAPR_MACHINE_CLASS(mc);
sPAPRCPUCore *core = SPAPR_CPU_CORE(OBJECT(dev));
CPUCore *cc = CPU_CORE(dev);
- CPUState *cs = CPU(core->threads[0]);
+ CPUState *cs;
sPAPRDRConnector *drc;
Error *local_err = NULL;
CPUArchId *core_slot;
@@ -3621,14 +3770,8 @@
g_assert(drc || !mc->has_hotpluggable_cpus);
if (drc) {
- void *fdt;
- int fdt_offset;
-
- fdt = spapr_populate_hotplug_cpu_dt(cs, &fdt_offset, spapr);
-
- spapr_drc_attach(drc, dev, fdt, fdt_offset, &local_err);
+ spapr_drc_attach(drc, dev, &local_err);
if (local_err) {
- g_free(fdt);
error_propagate(errp, local_err);
return;
}
@@ -3712,6 +3855,116 @@
error_propagate(errp, local_err);
}
+int spapr_phb_dt_populate(sPAPRDRConnector *drc, sPAPRMachineState *spapr,
+ void *fdt, int *fdt_start_offset, Error **errp)
+{
+ sPAPRPHBState *sphb = SPAPR_PCI_HOST_BRIDGE(drc->dev);
+ int intc_phandle;
+
+ intc_phandle = spapr_irq_get_phandle(spapr, spapr->fdt_blob, errp);
+ if (intc_phandle <= 0) {
+ return -1;
+ }
+
+ if (spapr_populate_pci_dt(sphb, intc_phandle, fdt, spapr->irq->nr_msis,
+ fdt_start_offset)) {
+ error_setg(errp, "unable to create FDT node for PHB %d", sphb->index);
+ return -1;
+ }
+
+ /* generally SLOF creates these, for hotplug it's up to QEMU */
+ _FDT(fdt_setprop_string(fdt, *fdt_start_offset, "name", "pci"));
+
+ return 0;
+}
+
+static void spapr_phb_pre_plug(HotplugHandler *hotplug_dev, DeviceState *dev,
+ Error **errp)
+{
+ sPAPRMachineState *spapr = SPAPR_MACHINE(OBJECT(hotplug_dev));
+ sPAPRPHBState *sphb = SPAPR_PCI_HOST_BRIDGE(dev);
+ sPAPRMachineClass *smc = SPAPR_MACHINE_GET_CLASS(spapr);
+ const unsigned windows_supported = spapr_phb_windows_supported(sphb);
+
+ if (dev->hotplugged && !smc->dr_phb_enabled) {
+ error_setg(errp, "PHB hotplug not supported for this machine");
+ return;
+ }
+
+ if (sphb->index == (uint32_t)-1) {
+ error_setg(errp, "\"index\" for PAPR PHB is mandatory");
+ return;
+ }
+
+ /*
+ * This will check that sphb->index doesn't exceed the maximum number of
+ * PHBs for the current machine type.
+ */
+ smc->phb_placement(spapr, sphb->index,
+ &sphb->buid, &sphb->io_win_addr,
+ &sphb->mem_win_addr, &sphb->mem64_win_addr,
+ windows_supported, sphb->dma_liobn, errp);
+}
+
+static void spapr_phb_plug(HotplugHandler *hotplug_dev, DeviceState *dev,
+ Error **errp)
+{
+ sPAPRMachineState *spapr = SPAPR_MACHINE(OBJECT(hotplug_dev));
+ sPAPRMachineClass *smc = SPAPR_MACHINE_GET_CLASS(spapr);
+ sPAPRPHBState *sphb = SPAPR_PCI_HOST_BRIDGE(dev);
+ sPAPRDRConnector *drc;
+ bool hotplugged = spapr_drc_hotplugged(dev);
+ Error *local_err = NULL;
+
+ if (!smc->dr_phb_enabled) {
+ return;
+ }
+
+ drc = spapr_drc_by_id(TYPE_SPAPR_DRC_PHB, sphb->index);
+ /* hotplug hooks should check it's enabled before getting this far */
+ assert(drc);
+
+ spapr_drc_attach(drc, DEVICE(dev), &local_err);
+ if (local_err) {
+ error_propagate(errp, local_err);
+ return;
+ }
+
+ if (hotplugged) {
+ spapr_hotplug_req_add_by_index(drc);
+ } else {
+ spapr_drc_reset(drc);
+ }
+}
+
+void spapr_phb_release(DeviceState *dev)
+{
+ HotplugHandler *hotplug_ctrl = qdev_get_hotplug_handler(dev);
+
+ hotplug_handler_unplug(hotplug_ctrl, dev, &error_abort);
+ object_unparent(OBJECT(dev));
+}
+
+static void spapr_phb_unplug(HotplugHandler *hotplug_dev, DeviceState *dev)
+{
+ object_property_set_bool(OBJECT(dev), false, "realized", NULL);
+}
+
+static void spapr_phb_unplug_request(HotplugHandler *hotplug_dev,
+ DeviceState *dev, Error **errp)
+{
+ sPAPRPHBState *sphb = SPAPR_PCI_HOST_BRIDGE(dev);
+ sPAPRDRConnector *drc;
+
+ drc = spapr_drc_by_id(TYPE_SPAPR_DRC_PHB, sphb->index);
+ assert(drc);
+
+ if (!spapr_drc_unplug_requested(drc)) {
+ spapr_drc_detach(drc);
+ spapr_hotplug_req_remove_by_index(drc);
+ }
+}
+
static void spapr_machine_device_plug(HotplugHandler *hotplug_dev,
DeviceState *dev, Error **errp)
{
@@ -3719,6 +3972,8 @@
spapr_memory_plug(hotplug_dev, dev, errp);
} else if (object_dynamic_cast(OBJECT(dev), TYPE_SPAPR_CPU_CORE)) {
spapr_core_plug(hotplug_dev, dev, errp);
+ } else if (object_dynamic_cast(OBJECT(dev), TYPE_SPAPR_PCI_HOST_BRIDGE)) {
+ spapr_phb_plug(hotplug_dev, dev, errp);
}
}
@@ -3729,6 +3984,8 @@
spapr_memory_unplug(hotplug_dev, dev);
} else if (object_dynamic_cast(OBJECT(dev), TYPE_SPAPR_CPU_CORE)) {
spapr_core_unplug(hotplug_dev, dev);
+ } else if (object_dynamic_cast(OBJECT(dev), TYPE_SPAPR_PCI_HOST_BRIDGE)) {
+ spapr_phb_unplug(hotplug_dev, dev);
}
}
@@ -3737,6 +3994,7 @@
{
sPAPRMachineState *sms = SPAPR_MACHINE(OBJECT(hotplug_dev));
MachineClass *mc = MACHINE_GET_CLASS(sms);
+ sPAPRMachineClass *smc = SPAPR_MACHINE_CLASS(mc);
if (object_dynamic_cast(OBJECT(dev), TYPE_PC_DIMM)) {
if (spapr_ovec_test(sms->ov5_cas, OV5_HP_EVT)) {
@@ -3756,6 +4014,12 @@
return;
}
spapr_core_unplug_request(hotplug_dev, dev, errp);
+ } else if (object_dynamic_cast(OBJECT(dev), TYPE_SPAPR_PCI_HOST_BRIDGE)) {
+ if (!smc->dr_phb_enabled) {
+ error_setg(errp, "PHB hot unplug not supported on this machine");
+ return;
+ }
+ spapr_phb_unplug_request(hotplug_dev, dev, errp);
}
}
@@ -3766,6 +4030,8 @@
spapr_memory_pre_plug(hotplug_dev, dev, errp);
} else if (object_dynamic_cast(OBJECT(dev), TYPE_SPAPR_CPU_CORE)) {
spapr_core_pre_plug(hotplug_dev, dev, errp);
+ } else if (object_dynamic_cast(OBJECT(dev), TYPE_SPAPR_PCI_HOST_BRIDGE)) {
+ spapr_phb_pre_plug(hotplug_dev, dev, errp);
}
}
@@ -3773,7 +4039,8 @@
DeviceState *dev)
{
if (object_dynamic_cast(OBJECT(dev), TYPE_PC_DIMM) ||
- object_dynamic_cast(OBJECT(dev), TYPE_SPAPR_CPU_CORE)) {
+ object_dynamic_cast(OBJECT(dev), TYPE_SPAPR_CPU_CORE) ||
+ object_dynamic_cast(OBJECT(dev), TYPE_SPAPR_PCI_HOST_BRIDGE)) {
return HOTPLUG_HANDLER(machine);
}
return NULL;
@@ -4004,7 +4271,7 @@
vhc->map_hptes = spapr_map_hptes;
vhc->unmap_hptes = spapr_unmap_hptes;
vhc->store_hpte = spapr_store_hpte;
- vhc->get_patbe = spapr_get_patbe;
+ vhc->get_pate = spapr_get_pate;
vhc->encode_hpt_for_kvm_pr = spapr_encode_hpt_for_kvm_pr;
xic->ics_get = spapr_ics_get;
xic->ics_resend = spapr_ics_resend;
@@ -4026,6 +4293,7 @@
smc->default_caps.caps[SPAPR_CAP_NESTED_KVM_HV] = SPAPR_CAP_OFF;
spapr_caps_add_properties(smc, &error_abort);
smc->irq = &spapr_irq_xics;
+ smc->dr_phb_enabled = true;
}
static const TypeInfo spapr_machine_info = {
@@ -4086,11 +4354,18 @@
static void spapr_machine_3_1_class_options(MachineClass *mc)
{
sPAPRMachineClass *smc = SPAPR_MACHINE_CLASS(mc);
+ static GlobalProperty compat[] = {
+ { TYPE_SPAPR_MACHINE, "host-model", "passthrough" },
+ { TYPE_SPAPR_MACHINE, "host-serial", "passthrough" },
+ };
spapr_machine_4_0_class_options(mc);
compat_props_add(mc->compat_props, hw_compat_3_1, hw_compat_3_1_len);
+ compat_props_add(mc->compat_props, compat, G_N_ELEMENTS(compat));
+
mc->default_cpu_type = POWERPC_CPU_TYPE_NAME("power8_v2.0");
smc->update_dt_enabled = false;
+ smc->dr_phb_enabled = false;
}
DEFINE_SPAPR_MACHINE(3_1, "3.1", false);
diff --git a/hw/ppc/spapr_drc.c b/hw/ppc/spapr_drc.c
index 2edb7d1..2943cf4 100644
--- a/hw/ppc/spapr_drc.c
+++ b/hw/ppc/spapr_drc.c
@@ -22,6 +22,7 @@
#include "qemu/error-report.h"
#include "hw/ppc/spapr.h" /* for RTAS return codes */
#include "hw/pci-host/spapr.h" /* spapr_phb_remove_pci_device_cb callback */
+#include "sysemu/device_tree.h"
#include "trace.h"
#define DRC_CONTAINER_PATH "/dr-connector"
@@ -373,8 +374,7 @@
} while (fdt_depth != 0);
}
-void spapr_drc_attach(sPAPRDRConnector *drc, DeviceState *d, void *fdt,
- int fdt_start_offset, Error **errp)
+void spapr_drc_attach(sPAPRDRConnector *drc, DeviceState *d, Error **errp)
{
trace_spapr_drc_attach(spapr_drc_index(drc));
@@ -384,11 +384,8 @@
}
g_assert((drc->state == SPAPR_DRC_STATE_LOGICAL_UNUSABLE)
|| (drc->state == SPAPR_DRC_STATE_PHYSICAL_POWERON));
- g_assert(fdt);
drc->dev = d;
- drc->fdt = fdt;
- drc->fdt_start_offset = fdt_start_offset;
object_property_add_link(OBJECT(drc), "device",
object_get_typename(OBJECT(drc->dev)),
@@ -674,6 +671,7 @@
drck->typename = "CPU";
drck->drc_name_prefix = "CPU ";
drck->release = spapr_core_release;
+ drck->dt_populate = spapr_core_dt_populate;
}
static void spapr_drc_pci_class_init(ObjectClass *k, void *data)
@@ -684,6 +682,7 @@
drck->typename = "28";
drck->drc_name_prefix = "C";
drck->release = spapr_phb_remove_pci_device_cb;
+ drck->dt_populate = spapr_pci_dt_populate;
}
static void spapr_drc_lmb_class_init(ObjectClass *k, void *data)
@@ -694,6 +693,18 @@
drck->typename = "MEM";
drck->drc_name_prefix = "LMB ";
drck->release = spapr_lmb_release;
+ drck->dt_populate = spapr_lmb_dt_populate;
+}
+
+static void spapr_drc_phb_class_init(ObjectClass *k, void *data)
+{
+ sPAPRDRConnectorClass *drck = SPAPR_DR_CONNECTOR_CLASS(k);
+
+ drck->typeshift = SPAPR_DR_CONNECTOR_TYPE_SHIFT_PHB;
+ drck->typename = "PHB";
+ drck->drc_name_prefix = "PHB ";
+ drck->release = spapr_phb_release;
+ drck->dt_populate = spapr_phb_dt_populate;
}
static const TypeInfo spapr_dr_connector_info = {
@@ -739,6 +750,13 @@
.class_init = spapr_drc_lmb_class_init,
};
+static const TypeInfo spapr_drc_phb_info = {
+ .name = TYPE_SPAPR_DRC_PHB,
+ .parent = TYPE_SPAPR_DRC_LOGICAL,
+ .instance_size = sizeof(sPAPRDRConnector),
+ .class_init = spapr_drc_phb_class_init,
+};
+
/* helper functions for external users */
sPAPRDRConnector *spapr_drc_by_index(uint32_t index)
@@ -1102,10 +1120,28 @@
goto out;
}
- g_assert(drc->fdt);
-
drck = SPAPR_DR_CONNECTOR_GET_CLASS(drc);
+ if (!drc->fdt) {
+ Error *local_err = NULL;
+ void *fdt;
+ int fdt_size;
+
+ fdt = create_device_tree(&fdt_size);
+
+ if (drck->dt_populate(drc, spapr, fdt, &drc->fdt_start_offset,
+ &local_err)) {
+ g_free(fdt);
+ error_free(local_err);
+ rc = SPAPR_DR_CC_RESPONSE_ERROR;
+ goto out;
+ }
+
+ drc->fdt = fdt;
+ drc->ccs_offset = drc->fdt_start_offset;
+ drc->ccs_depth = 0;
+ }
+
do {
uint32_t tag;
const char *name;
@@ -1189,6 +1225,7 @@
type_register_static(&spapr_drc_cpu_info);
type_register_static(&spapr_drc_pci_info);
type_register_static(&spapr_drc_lmb_info);
+ type_register_static(&spapr_drc_phb_info);
spapr_rtas_register(RTAS_SET_INDICATOR, "set-indicator",
rtas_set_indicator);
diff --git a/hw/ppc/spapr_events.c b/hw/ppc/spapr_events.c
index b9c7ecb..ab9a1f0 100644
--- a/hw/ppc/spapr_events.c
+++ b/hw/ppc/spapr_events.c
@@ -526,6 +526,9 @@
case SPAPR_DR_CONNECTOR_TYPE_CPU:
hp->hotplug_type = RTAS_LOG_V6_HP_TYPE_CPU;
break;
+ case SPAPR_DR_CONNECTOR_TYPE_PHB:
+ hp->hotplug_type = RTAS_LOG_V6_HP_TYPE_PHB;
+ break;
default:
/* we shouldn't be signaling hotplug events for resources
* that don't support them
diff --git a/hw/ppc/spapr_hcall.c b/hw/ppc/spapr_hcall.c
index 17bcaa3..476bad6 100644
--- a/hw/ppc/spapr_hcall.c
+++ b/hw/ppc/spapr_hcall.c
@@ -17,37 +17,6 @@
#include "mmu-book3s-v3.h"
#include "hw/mem/memory-device.h"
-struct LPCRSyncState {
- target_ulong value;
- target_ulong mask;
-};
-
-static void do_lpcr_sync(CPUState *cs, run_on_cpu_data arg)
-{
- struct LPCRSyncState *s = arg.host_ptr;
- PowerPCCPU *cpu = POWERPC_CPU(cs);
- CPUPPCState *env = &cpu->env;
- target_ulong lpcr;
-
- cpu_synchronize_state(cs);
- lpcr = env->spr[SPR_LPCR];
- lpcr &= ~s->mask;
- lpcr |= s->value;
- ppc_store_lpcr(cpu, lpcr);
-}
-
-static void set_all_lpcrs(target_ulong value, target_ulong mask)
-{
- CPUState *cs;
- struct LPCRSyncState s = {
- .value = value,
- .mask = mask
- };
- CPU_FOREACH(cs) {
- run_on_cpu(cs, do_lpcr_sync, RUN_ON_CPU_HOST_PTR(&s));
- }
-}
-
static bool has_spr(PowerPCCPU *cpu, int spr)
{
/* We can test whether the SPR is defined by checking for a valid name */
@@ -1255,12 +1224,12 @@
switch (mflags) {
case H_SET_MODE_ENDIAN_BIG:
- set_all_lpcrs(0, LPCR_ILE);
+ spapr_set_all_lpcrs(0, LPCR_ILE);
spapr_pci_switch_vga(true);
return H_SUCCESS;
case H_SET_MODE_ENDIAN_LITTLE:
- set_all_lpcrs(LPCR_ILE, LPCR_ILE);
+ spapr_set_all_lpcrs(LPCR_ILE, LPCR_ILE);
spapr_pci_switch_vga(false);
return H_SUCCESS;
}
@@ -1289,7 +1258,7 @@
return H_UNSUPPORTED_FLAG;
}
- set_all_lpcrs(mflags << LPCR_AIL_SHIFT, LPCR_AIL);
+ spapr_set_all_lpcrs(mflags << LPCR_AIL_SHIFT, LPCR_AIL);
return H_SUCCESS;
}
@@ -1342,12 +1311,12 @@
* later and so assumed radix and now it's called H_REG_PROC_TBL
*/
- if ((patbe_old & PATBE1_GR) == (patbe_new & PATBE1_GR)) {
+ if ((patbe_old & PATE1_GR) == (patbe_new & PATE1_GR)) {
/* We assume RADIX, so this catches all the "Do Nothing" cases */
- } else if (!(patbe_old & PATBE1_GR)) {
+ } else if (!(patbe_old & PATE1_GR)) {
/* HASH->RADIX : Free HPT */
spapr_free_hpt(spapr);
- } else if (!(patbe_new & PATBE1_GR)) {
+ } else if (!(patbe_new & PATE1_GR)) {
/* RADIX->HASH || NOTHING->HASH : Allocate HPT */
spapr_setup_hpt_and_vrma(spapr);
}
@@ -1385,7 +1354,7 @@
} else if (table_size > 24) {
return H_P4;
}
- cproc = PATBE1_GR | proc_tbl | table_size;
+ cproc = PATE1_GR | proc_tbl | table_size;
} else { /* Register new HPT process table */
if (flags & FLAG_HASH_PROC_TBL) { /* Hash with Segment Tables */
/* TODO - Not Supported */
@@ -1404,13 +1373,15 @@
}
} else { /* Deregister current process table */
- /* Set to benign value: (current GR) | 0. This allows
- * deregistration in KVM to succeed even if the radix bit in flags
- * doesn't match the radix bit in the old PATB. */
- cproc = spapr->patb_entry & PATBE1_GR;
+ /*
+ * Set to benign value: (current GR) | 0. This allows
+ * deregistration in KVM to succeed even if the radix bit
+ * in flags doesn't match the radix bit in the old PATE.
+ */
+ cproc = spapr->patb_entry & PATE1_GR;
}
} else { /* Maintain current registration */
- if (!(flags & FLAG_RADIX) != !(spapr->patb_entry & PATBE1_GR)) {
+ if (!(flags & FLAG_RADIX) != !(spapr->patb_entry & PATE1_GR)) {
/* Technically caused by flag bits => H_PARAMETER */
return H_PARAMETER; /* Existing Process Table Mismatch */
}
@@ -1422,10 +1393,11 @@
spapr->patb_entry = cproc; /* Save new process table */
- /* Update the UPRT and GTSE bits in the LPCR for all cpus */
- set_all_lpcrs(((flags & (FLAG_RADIX | FLAG_HASH_PROC_TBL)) ? LPCR_UPRT : 0) |
- ((flags & FLAG_GTSE) ? LPCR_GTSE : 0),
- LPCR_UPRT | LPCR_GTSE);
+ /* Update the UPRT, HR and GTSE bits in the LPCR for all cpus */
+ spapr_set_all_lpcrs(((flags & (FLAG_RADIX | FLAG_HASH_PROC_TBL)) ?
+ (LPCR_UPRT | LPCR_HR) : 0) |
+ ((flags & FLAG_GTSE) ? LPCR_GTSE : 0),
+ LPCR_UPRT | LPCR_HR | LPCR_GTSE);
if (kvm_enabled()) {
return kvmppc_configure_v3_mmu(cpu, flags & FLAG_RADIX,
@@ -1646,7 +1618,7 @@
if (!spapr->cas_reboot) {
/* If spapr_machine_reset() did not set up a HPT but one is necessary
* (because the guest isn't going to use radix) then set it up here. */
- if ((spapr->patb_entry & PATBE1_GR) && !guest_radix) {
+ if ((spapr->patb_entry & PATE1_GR) && !guest_radix) {
/* legacy hash or new hash: */
spapr_setup_hpt_and_vrma(spapr);
}
diff --git a/hw/ppc/spapr_irq.c b/hw/ppc/spapr_irq.c
index 4297eed..4145079 100644
--- a/hw/ppc/spapr_irq.c
+++ b/hw/ppc/spapr_irq.c
@@ -230,6 +230,11 @@
/* TODO: create the KVM XICS device */
}
+static const char *spapr_irq_get_nodename_xics(sPAPRMachineState *spapr)
+{
+ return XICS_NODENAME;
+}
+
#define SPAPR_IRQ_XICS_NR_IRQS 0x1000
#define SPAPR_IRQ_XICS_NR_MSIS \
(XICS_IRQ_BASE + SPAPR_IRQ_XICS_NR_IRQS - SPAPR_IRQ_MSI)
@@ -249,6 +254,7 @@
.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,
};
/*
@@ -384,6 +390,11 @@
xive_source_set_irq(&spapr->xive->source, srcno, val);
}
+static const char *spapr_irq_get_nodename_xive(sPAPRMachineState *spapr)
+{
+ return spapr->xive->nodename;
+}
+
/*
* XIVE uses the full IRQ number space. Set it to 8K to be compatible
* with XICS.
@@ -407,6 +418,7 @@
.post_load = spapr_irq_post_load_xive,
.reset = spapr_irq_reset_xive,
.set_irq = spapr_irq_set_irq_xive,
+ .get_nodename = spapr_irq_get_nodename_xive,
};
/*
@@ -541,6 +553,11 @@
spapr_irq_current(spapr)->set_irq(spapr, srcno, val);
}
+static const char *spapr_irq_get_nodename_dual(sPAPRMachineState *spapr)
+{
+ return spapr_irq_current(spapr)->get_nodename(spapr);
+}
+
/*
* Define values in sync with the XIVE and XICS backend
*/
@@ -561,7 +578,8 @@
.cpu_intc_create = spapr_irq_cpu_intc_create_dual,
.post_load = spapr_irq_post_load_dual,
.reset = spapr_irq_reset_dual,
- .set_irq = spapr_irq_set_irq_dual
+ .set_irq = spapr_irq_set_irq_dual,
+ .get_nodename = spapr_irq_get_nodename_dual,
};
/*
@@ -620,6 +638,27 @@
}
}
+int spapr_irq_get_phandle(sPAPRMachineState *spapr, void *fdt, Error **errp)
+{
+ const char *nodename = spapr->irq->get_nodename(spapr);
+ int offset, phandle;
+
+ offset = fdt_subnode_offset(fdt, 0, nodename);
+ if (offset < 0) {
+ error_setg(errp, "Can't find node \"%s\": %s", nodename,
+ fdt_strerror(offset));
+ return -1;
+ }
+
+ phandle = fdt_get_phandle(fdt, offset);
+ if (!phandle) {
+ error_setg(errp, "Can't get phandle of node \"%s\"", nodename);
+ return -1;
+ }
+
+ return phandle;
+}
+
/*
* XICS legacy routines - to deprecate one day
*/
@@ -691,4 +730,5 @@
.cpu_intc_create = spapr_irq_cpu_intc_create_xics,
.post_load = spapr_irq_post_load_xics,
.set_irq = spapr_irq_set_irq_xics,
+ .get_nodename = spapr_irq_get_nodename_xics,
};
diff --git a/hw/ppc/spapr_ovec.c b/hw/ppc/spapr_ovec.c
index 318bf33..12510b2 100644
--- a/hw/ppc/spapr_ovec.c
+++ b/hw/ppc/spapr_ovec.c
@@ -16,6 +16,7 @@
#include "qemu/bitmap.h"
#include "exec/address-spaces.h"
#include "qemu/error-report.h"
+#include "sysemu/qtest.h"
#include "trace.h"
#include <libfdt.h>
@@ -131,6 +132,11 @@
g_assert(ov);
g_assert(bitnr < OV_MAXBITS);
+ /* support memory unplug for qtest */
+ if (qtest_enabled() && bitnr == OV5_HP_EVT) {
+ return true;
+ }
+
return test_bit(bitnr, ov->bitmap) ? true : false;
}
diff --git a/hw/ppc/spapr_pci.c b/hw/ppc/spapr_pci.c
index 60777b2..69059c3 100644
--- a/hw/ppc/spapr_pci.c
+++ b/hw/ppc/spapr_pci.c
@@ -1379,6 +1379,7 @@
HotplugHandler *hotplug_ctrl = qdev_get_hotplug_handler(dev);
hotplug_handler_unplug(hotplug_ctrl, dev, &error_abort);
+ object_unparent(OBJECT(dev));
}
static sPAPRDRConnector *spapr_phb_get_pci_func_drc(sPAPRPHBState *phb,
@@ -1408,6 +1409,17 @@
return spapr_drc_index(drc);
}
+int spapr_pci_dt_populate(sPAPRDRConnector *drc, sPAPRMachineState *spapr,
+ void *fdt, int *fdt_start_offset, Error **errp)
+{
+ HotplugHandler *plug_handler = qdev_get_hotplug_handler(drc->dev);
+ sPAPRPHBState *sphb = SPAPR_PCI_HOST_BRIDGE(plug_handler);
+ PCIDevice *pdev = PCI_DEVICE(drc->dev);
+
+ *fdt_start_offset = spapr_create_pci_child_dt(sphb, pdev, fdt, 0);
+ return 0;
+}
+
static void spapr_pci_plug(HotplugHandler *plug_handler,
DeviceState *plugged_dev, Error **errp)
{
@@ -1417,8 +1429,6 @@
Error *local_err = NULL;
PCIBus *bus = PCI_BUS(qdev_get_parent_bus(DEVICE(pdev)));
uint32_t slotnr = PCI_SLOT(pdev->devfn);
- void *fdt = NULL;
- int fdt_start_offset, fdt_size;
/* if DR is disabled we don't need to do anything in the case of
* hotplug or coldplug callbacks
@@ -1448,10 +1458,7 @@
goto out;
}
- fdt = create_device_tree(&fdt_size);
- fdt_start_offset = spapr_create_pci_child_dt(phb, pdev, fdt, 0);
-
- spapr_drc_attach(drc, DEVICE(pdev), fdt, fdt_start_offset, &local_err);
+ spapr_drc_attach(drc, DEVICE(pdev), &local_err);
if (local_err) {
goto out;
}
@@ -1483,7 +1490,6 @@
out:
if (local_err) {
error_propagate(errp, local_err);
- g_free(fdt);
}
}
@@ -1501,7 +1507,7 @@
* an 'idle' state, as the device cleanup code expects.
*/
pci_device_reset(PCI_DEVICE(plugged_dev));
- object_unparent(OBJECT(plugged_dev));
+ object_property_set_bool(OBJECT(plugged_dev), false, "realized", NULL);
}
static void spapr_pci_unplug_request(HotplugHandler *plug_handler,
@@ -1565,6 +1571,75 @@
}
}
+static void spapr_phb_finalizefn(Object *obj)
+{
+ sPAPRPHBState *sphb = SPAPR_PCI_HOST_BRIDGE(obj);
+
+ g_free(sphb->dtbusname);
+ sphb->dtbusname = NULL;
+}
+
+static void spapr_phb_unrealize(DeviceState *dev, Error **errp)
+{
+ sPAPRMachineState *spapr = SPAPR_MACHINE(qdev_get_machine());
+ SysBusDevice *s = SYS_BUS_DEVICE(dev);
+ PCIHostState *phb = PCI_HOST_BRIDGE(s);
+ sPAPRPHBState *sphb = SPAPR_PCI_HOST_BRIDGE(phb);
+ sPAPRTCETable *tcet;
+ int i;
+ const unsigned windows_supported = spapr_phb_windows_supported(sphb);
+
+ if (sphb->msi) {
+ g_hash_table_unref(sphb->msi);
+ sphb->msi = NULL;
+ }
+
+ /*
+ * Remove IO/MMIO subregions and aliases, rest should get cleaned
+ * via PHB's unrealize->object_finalize
+ */
+ for (i = windows_supported - 1; i >= 0; i--) {
+ tcet = spapr_tce_find_by_liobn(sphb->dma_liobn[i]);
+ if (tcet) {
+ memory_region_del_subregion(&sphb->iommu_root,
+ spapr_tce_get_iommu(tcet));
+ }
+ }
+
+ if (sphb->dr_enabled) {
+ for (i = PCI_SLOT_MAX * 8 - 1; i >= 0; i--) {
+ sPAPRDRConnector *drc = spapr_drc_by_id(TYPE_SPAPR_DRC_PCI,
+ (sphb->index << 16) | i);
+
+ if (drc) {
+ object_unparent(OBJECT(drc));
+ }
+ }
+ }
+
+ for (i = PCI_NUM_PINS - 1; i >= 0; i--) {
+ if (sphb->lsi_table[i].irq) {
+ spapr_irq_free(spapr, sphb->lsi_table[i].irq, 1);
+ sphb->lsi_table[i].irq = 0;
+ }
+ }
+
+ QLIST_REMOVE(sphb, list);
+
+ memory_region_del_subregion(&sphb->iommu_root, &sphb->msiwindow);
+
+ address_space_destroy(&sphb->iommu_as);
+
+ qbus_set_hotplug_handler(BUS(phb->bus), NULL, &error_abort);
+ pci_unregister_root_bus(phb->bus);
+
+ memory_region_del_subregion(get_system_memory(), &sphb->iowindow);
+ if (sphb->mem64_win_pciaddr != (hwaddr)-1) {
+ memory_region_del_subregion(get_system_memory(), &sphb->mem64window);
+ }
+ memory_region_del_subregion(get_system_memory(), &sphb->mem32window);
+}
+
static void spapr_phb_realize(DeviceState *dev, Error **errp)
{
/* We don't use SPAPR_MACHINE() in order to exit gracefully if the user
@@ -1582,29 +1657,14 @@
PCIBus *bus;
uint64_t msi_window_size = 4096;
sPAPRTCETable *tcet;
- const unsigned windows_supported =
- sphb->ddw_enabled ? SPAPR_PCI_DMA_MAX_WINDOWS : 1;
+ const unsigned windows_supported = spapr_phb_windows_supported(sphb);
if (!spapr) {
error_setg(errp, TYPE_SPAPR_PCI_HOST_BRIDGE " needs a pseries machine");
return;
}
- if (sphb->index != (uint32_t)-1) {
- Error *local_err = NULL;
-
- smc->phb_placement(spapr, sphb->index,
- &sphb->buid, &sphb->io_win_addr,
- &sphb->mem_win_addr, &sphb->mem64_win_addr,
- windows_supported, sphb->dma_liobn, &local_err);
- if (local_err) {
- error_propagate(errp, local_err);
- return;
- }
- } else {
- error_setg(errp, "\"index\" for PAPR PHB is mandatory");
- return;
- }
+ assert(sphb->index != (uint32_t)-1); /* checked in spapr_phb_pre_plug() */
if (sphb->mem64_win_size != 0) {
if (sphb->mem_win_size > SPAPR_PCI_MEM32_WIN_SIZE) {
@@ -1740,6 +1800,10 @@
if (local_err) {
error_propagate_prepend(errp, local_err,
"can't allocate LSIs: ");
+ /*
+ * Older machines will never support PHB hotplug, ie, this is an
+ * init only path and QEMU will terminate. No need to rollback.
+ */
return;
}
}
@@ -1747,7 +1811,7 @@
spapr_irq_claim(spapr, irq, true, &local_err);
if (local_err) {
error_propagate_prepend(errp, local_err, "can't allocate LSIs: ");
- return;
+ goto unrealize;
}
sphb->lsi_table[i].irq = irq;
@@ -1767,13 +1831,17 @@
if (!tcet) {
error_setg(errp, "Creating window#%d failed for %s",
i, sphb->dtbusname);
- return;
+ goto unrealize;
}
memory_region_add_subregion(&sphb->iommu_root, 0,
spapr_tce_get_iommu(tcet));
}
sphb->msi = g_hash_table_new_full(g_int_hash, g_int_equal, g_free, g_free);
+ return;
+
+unrealize:
+ spapr_phb_unrealize(dev, NULL);
}
static int spapr_phb_children_reset(Object *child, void *opaque)
@@ -1972,6 +2040,7 @@
hc->root_bus_path = spapr_phb_root_bus_path;
dc->realize = spapr_phb_realize;
+ dc->unrealize = spapr_phb_unrealize;
dc->props = spapr_phb_properties;
dc->reset = spapr_phb_reset;
dc->vmsd = &vmstate_spapr_pci;
@@ -1987,6 +2056,7 @@
.name = TYPE_SPAPR_PCI_HOST_BRIDGE,
.parent = TYPE_PCI_HOST_BRIDGE,
.instance_size = sizeof(sPAPRPHBState),
+ .instance_finalize = spapr_phb_finalizefn,
.class_init = spapr_phb_class_init,
.interfaces = (InterfaceInfo[]) {
{ TYPE_HOTPLUG_HANDLER },
@@ -2070,7 +2140,7 @@
}
int spapr_populate_pci_dt(sPAPRPHBState *phb, uint32_t intc_phandle, void *fdt,
- uint32_t nr_msis)
+ uint32_t nr_msis, int *node_offset)
{
int bus_off, i, j, ret;
gchar *nodename;
@@ -2120,11 +2190,15 @@
sPAPRTCETable *tcet;
PCIBus *bus = PCI_HOST_BRIDGE(phb)->bus;
sPAPRFDT s_fdt;
+ sPAPRDRConnector *drc;
/* Start populating the FDT */
nodename = g_strdup_printf("pci@%" PRIx64, phb->buid);
_FDT(bus_off = fdt_add_subnode(fdt, 0, nodename));
g_free(nodename);
+ if (node_offset) {
+ *node_offset = bus_off;
+ }
/* Write PHB properties */
_FDT(fdt_setprop_string(fdt, bus_off, "device_type", "pci"));
@@ -2183,6 +2257,14 @@
tcet->liobn, tcet->bus_offset,
tcet->nb_table << tcet->page_shift);
+ drc = spapr_drc_by_id(TYPE_SPAPR_DRC_PHB, phb->index);
+ if (drc) {
+ uint32_t drc_index = cpu_to_be32(spapr_drc_index(drc));
+
+ _FDT(fdt_setprop(fdt, bus_off, "ibm,my-drc-index", &drc_index,
+ sizeof(drc_index)));
+ }
+
/* Walk the bridges and program the bus numbers*/
spapr_phb_pci_enumerate(phb);
_FDT(fdt_setprop_cell(fdt, bus_off, "qemu,phb-enumerated", 0x1));
diff --git a/hw/ppc/spapr_rtas.c b/hw/ppc/spapr_rtas.c
index d6a0952..7a2cb78 100644
--- a/hw/ppc/spapr_rtas.c
+++ b/hw/ppc/spapr_rtas.c
@@ -172,10 +172,10 @@
* New cpus are expected to start in the same radix/hash mode
* as the existing CPUs
*/
- if (ppc64_radix_guest(callcpu)) {
- lpcr |= LPCR_UPRT | LPCR_GTSE;
+ if (ppc64_v3_radix(callcpu)) {
+ lpcr |= LPCR_UPRT | LPCR_GTSE | LPCR_HR;
} else {
- lpcr &= ~(LPCR_UPRT | LPCR_GTSE);
+ lpcr &= ~(LPCR_UPRT | LPCR_GTSE | LPCR_HR);
}
}
ppc_store_lpcr(newcpu, lpcr);
diff --git a/hw/s390x/ap-bridge.c b/hw/s390x/ap-bridge.c
index 3795d30..75ad0a6 100644
--- a/hw/s390x/ap-bridge.c
+++ b/hw/s390x/ap-bridge.c
@@ -39,6 +39,7 @@
void s390_init_ap(void)
{
DeviceState *dev;
+ BusState *bus;
/* If no AP instructions then no need for AP bridge */
if (!s390_has_feat(S390_FEAT_AP)) {
@@ -52,13 +53,18 @@
qdev_init_nofail(dev);
/* Create bus on bridge device */
- qbus_create(TYPE_AP_BUS, dev, TYPE_AP_BUS);
+ bus = qbus_create(TYPE_AP_BUS, dev, TYPE_AP_BUS);
+
+ /* Enable hotplugging */
+ qbus_set_hotplug_handler(bus, OBJECT(dev), &error_abort);
}
static void ap_bridge_class_init(ObjectClass *oc, void *data)
{
DeviceClass *dc = DEVICE_CLASS(oc);
+ HotplugHandlerClass *hc = HOTPLUG_HANDLER_CLASS(oc);
+ hc->unplug = qdev_simple_device_unplug_cb;
set_bit(DEVICE_CATEGORY_BRIDGE, dc->categories);
}
@@ -67,6 +73,10 @@
.parent = TYPE_SYS_BUS_DEVICE,
.instance_size = 0,
.class_init = ap_bridge_class_init,
+ .interfaces = (InterfaceInfo[]) {
+ { TYPE_HOTPLUG_HANDLER },
+ { }
+ }
};
static void ap_register(void)
diff --git a/hw/s390x/css-bridge.c b/hw/s390x/css-bridge.c
index 7573c40..e04d51b 100644
--- a/hw/s390x/css-bridge.c
+++ b/hw/s390x/css-bridge.c
@@ -51,7 +51,7 @@
css_generate_sch_crws(sch->cssid, sch->ssid, sch->schid, 1, 0);
- object_unparent(OBJECT(dev));
+ object_property_set_bool(OBJECT(dev), false, "realized", NULL);
}
static void virtual_css_bus_reset(BusState *qbus)
diff --git a/hw/s390x/s390-pci-bus.c b/hw/s390x/s390-pci-bus.c
index 5998942..2d0a28d 100644
--- a/hw/s390x/s390-pci-bus.c
+++ b/hw/s390x/s390-pci-bus.c
@@ -154,14 +154,17 @@
/* Unplug the PCI device */
if (pbdev->pdev) {
- hotplug_ctrl = qdev_get_hotplug_handler(DEVICE(pbdev->pdev));
- hotplug_handler_unplug(hotplug_ctrl, DEVICE(pbdev->pdev),
- &error_abort);
+ DeviceState *pdev = DEVICE(pbdev->pdev);
+
+ hotplug_ctrl = qdev_get_hotplug_handler(pdev);
+ hotplug_handler_unplug(hotplug_ctrl, pdev, &error_abort);
+ object_unparent(OBJECT(pdev));
}
/* Unplug the zPCI device */
hotplug_ctrl = qdev_get_hotplug_handler(DEVICE(pbdev));
hotplug_handler_unplug(hotplug_ctrl, DEVICE(pbdev), &error_abort);
+ object_unparent(OBJECT(pbdev));
}
void s390_pci_sclp_deconfigure(SCCB *sccb)
@@ -994,7 +997,7 @@
pbdev->fh, pbdev->fid);
bus = pci_get_bus(pci_dev);
devfn = pci_dev->devfn;
- object_unparent(OBJECT(pci_dev));
+ object_property_set_bool(OBJECT(dev), false, "realized", NULL);
s390_pci_msix_free(pbdev);
s390_pci_iommu_free(s, bus, devfn);
@@ -1005,7 +1008,7 @@
pbdev->fid = 0;
QTAILQ_REMOVE(&s->zpci_devs, pbdev, link);
g_hash_table_remove(s->zpci_table, &pbdev->idx);
- object_unparent(OBJECT(pbdev));
+ object_property_set_bool(OBJECT(dev), false, "realized", NULL);
}
}
diff --git a/hw/smbios/smbios.c b/hw/smbios/smbios.c
index 818be8a..47be907 100644
--- a/hw/smbios/smbios.c
+++ b/hw/smbios/smbios.c
@@ -563,6 +563,7 @@
t->height = 0;
t->number_of_power_cords = 0;
t->contained_element_count = 0;
+ t->contained_element_record_length = 0;
SMBIOS_TABLE_SET_STR(3, sku_number_str, type3.sku);
SMBIOS_BUILD_TABLE_POST;
diff --git a/hw/timer/ds1338.c b/hw/timer/ds1338.c
index 3849b74..03da754 100644
--- a/hw/timer/ds1338.c
+++ b/hw/timer/ds1338.c
@@ -117,7 +117,7 @@
return 0;
}
-static int ds1338_recv(I2CSlave *i2c)
+static uint8_t ds1338_recv(I2CSlave *i2c)
{
DS1338State *s = DS1338(i2c);
uint8_t res;
diff --git a/hw/timer/m41t80.c b/hw/timer/m41t80.c
index 734d7d9..c45b929 100644
--- a/hw/timer/m41t80.c
+++ b/hw/timer/m41t80.c
@@ -40,7 +40,7 @@
return 0;
}
-static int m41t80_recv(I2CSlave *i2c)
+static uint8_t m41t80_recv(I2CSlave *i2c)
{
M41t80State *s = M41T80(i2c);
struct tm now;
diff --git a/hw/timer/twl92230.c b/hw/timer/twl92230.c
index 51ec355..c83d803 100644
--- a/hw/timer/twl92230.c
+++ b/hw/timer/twl92230.c
@@ -737,7 +737,7 @@
return 0;
}
-static int menelaus_rx(I2CSlave *i2c)
+static uint8_t menelaus_rx(I2CSlave *i2c)
{
MenelausState *s = TWL92230(i2c);
diff --git a/hw/tpm/tpm_tis.c b/hw/tpm/tpm_tis.c
index fd6bb9b..fd183e8 100644
--- a/hw/tpm/tpm_tis.c
+++ b/hw/tpm/tpm_tis.c
@@ -106,17 +106,26 @@
static void tpm_tis_show_buffer(const unsigned char *buffer,
size_t buffer_size, const char *string)
{
- uint32_t len, i;
+ size_t len, i;
+ char *line_buffer, *p;
len = MIN(tpm_cmd_get_size(buffer), buffer_size);
- printf("tpm_tis: %s length = %d\n", string, len);
- for (i = 0; i < len; i++) {
+
+ /*
+ * allocate enough room for 3 chars per buffer entry plus a
+ * newline after every 16 chars and a final null terminator.
+ */
+ line_buffer = g_malloc(len * 3 + (len / 16) + 1);
+
+ for (i = 0, p = line_buffer; i < len; i++) {
if (i && !(i % 16)) {
- printf("\n");
+ p += sprintf(p, "\n");
}
- printf("%.2X ", buffer[i]);
+ p += sprintf(p, "%.2X ", buffer[i]);
}
- printf("\n");
+ trace_tpm_tis_show_buffer(string, len, line_buffer);
+
+ g_free(line_buffer);
}
/*
@@ -143,9 +152,8 @@
*/
static void tpm_tis_tpm_send(TPMState *s, uint8_t locty)
{
- if (DEBUG_TIS) {
- tpm_tis_show_buffer(s->buffer, s->be_buffer_size,
- "tpm_tis: To TPM");
+ if (trace_event_get_state_backends(TRACE_TPM_TIS_SHOW_BUFFER)) {
+ tpm_tis_show_buffer(s->buffer, s->be_buffer_size, "To TPM");
}
/*
@@ -313,9 +321,8 @@
s->loc[locty].state = TPM_TIS_STATE_COMPLETION;
s->rw_offset = 0;
- if (DEBUG_TIS) {
- tpm_tis_show_buffer(s->buffer, s->be_buffer_size,
- "tpm_tis: From TPM");
+ if (trace_event_get_state_backends(TRACE_TPM_TIS_SHOW_BUFFER)) {
+ tpm_tis_show_buffer(s->buffer, s->be_buffer_size, "From TPM");
}
if (TPM_TIS_IS_VALID_LOCTY(s->next_locty)) {
@@ -624,7 +631,7 @@
}
/* cancel any seize by a lower locality */
- for (l = 0; l < locty - 1; l++) {
+ for (l = 0; l < locty; l++) {
s->loc[l].access &= ~TPM_TIS_ACCESS_SEIZE;
}
diff --git a/hw/tpm/trace-events b/hw/tpm/trace-events
index 920d32a..f45dcd2 100644
--- a/hw/tpm/trace-events
+++ b/hw/tpm/trace-events
@@ -36,6 +36,7 @@
tpm_emulator_inst_init(void) ""
# hw/tpm/tpm_tis.c
+tpm_tis_show_buffer(const char *direction, size_t len, const char *buf) "direction: %s len: %zu\nbuf: %s"
tpm_tis_raise_irq(uint32_t irqmask) "Raising IRQ for flag 0x%08x"
tpm_tis_new_active_locality(uint8_t locty) "Active locality is now %d"
tpm_tis_abort(uint8_t locty) "New active locality is %d"
diff --git a/hw/usb/dev-mtp.c b/hw/usb/dev-mtp.c
index f1d20fa..06e376b 100644
--- a/hw/usb/dev-mtp.c
+++ b/hw/usb/dev-mtp.c
@@ -11,17 +11,16 @@
#include "qemu/osdep.h"
#include "qapi/error.h"
+#include "qemu/error-report.h"
#include <wchar.h>
#include <dirent.h>
#include <sys/statvfs.h>
-#ifdef CONFIG_INOTIFY1
-#include <sys/inotify.h>
-#include "qemu/main-loop.h"
-#endif
+
#include "qemu-common.h"
#include "qemu/iov.h"
+#include "qemu/filemonitor.h"
#include "trace.h"
#include "hw/usb.h"
#include "desc.h"
@@ -132,7 +131,6 @@
EP_EVENT,
};
-#ifdef CONFIG_INOTIFY1
typedef struct MTPMonEntry MTPMonEntry;
struct MTPMonEntry {
@@ -141,7 +139,6 @@
QTAILQ_ENTRY(MTPMonEntry) next;
};
-#endif
struct MTPControl {
uint16_t code;
@@ -172,10 +169,8 @@
char *name;
char *path;
struct stat stat;
-#ifdef CONFIG_INOTIFY1
- /* inotify watch cookie */
- int watchfd;
-#endif
+ /* file monitor watch id */
+ int watchid;
MTPObject *parent;
uint32_t nchildren;
QLIST_HEAD(, MTPObject) children;
@@ -198,11 +193,8 @@
bool readonly;
QTAILQ_HEAD(, MTPObject) objects;
-#ifdef CONFIG_INOTIFY1
- /* inotify descriptor */
- int inotifyfd;
+ QFileMonitor *file_monitor;
QTAILQ_HEAD(, MTPMonEntry) events;
-#endif
/* Responder is expecting a write operation */
bool write_pending;
struct {
@@ -383,7 +375,7 @@
/* ----------------------------------------------------------------------- */
static MTPObject *usb_mtp_object_alloc(MTPState *s, uint32_t handle,
- MTPObject *parent, char *name)
+ MTPObject *parent, const char *name)
{
MTPObject *o = g_new0(MTPObject, 1);
@@ -391,6 +383,7 @@
goto ignore;
}
+ o->watchid = -1;
o->handle = handle;
o->parent = parent;
o->name = g_strdup(name);
@@ -437,6 +430,10 @@
trace_usb_mtp_object_free(s->dev.addr, o->handle, o->path);
+ if (o->watchid != -1 && s->file_monitor) {
+ qemu_file_monitor_remove_watch(s->file_monitor, o->path, o->watchid);
+ }
+
QTAILQ_REMOVE(&s->objects, o, next);
if (o->parent) {
QLIST_REMOVE(o, list);
@@ -465,7 +462,7 @@
}
static MTPObject *usb_mtp_add_child(MTPState *s, MTPObject *o,
- char *name)
+ const char *name)
{
MTPObject *child =
usb_mtp_object_alloc(s, s->next_handle++, o, name);
@@ -484,10 +481,14 @@
}
static MTPObject *usb_mtp_object_lookup_name(MTPObject *parent,
- char *name, int len)
+ const char *name, int len)
{
MTPObject *iter;
+ if (len == -1) {
+ len = strlen(name);
+ }
+
QLIST_FOREACH(iter, &parent->children, list) {
if (strncmp(iter->name, name, len) == 0) {
return iter;
@@ -497,13 +498,12 @@
return NULL;
}
-#ifdef CONFIG_INOTIFY1
-static MTPObject *usb_mtp_object_lookup_wd(MTPState *s, int wd)
+static MTPObject *usb_mtp_object_lookup_id(MTPState *s, int id)
{
MTPObject *iter;
QTAILQ_FOREACH(iter, &s->objects, next) {
- if (iter->watchfd == wd) {
+ if (iter->watchid == id) {
return iter;
}
}
@@ -511,160 +511,103 @@
return NULL;
}
-static void inotify_watchfn(void *arg)
+static void file_monitor_event(int id,
+ QFileMonitorEvent ev,
+ const char *name,
+ void *opaque)
{
- MTPState *s = arg;
- ssize_t bytes;
- /* From the man page: atleast one event can be read */
- int pos;
- char buf[sizeof(struct inotify_event) + NAME_MAX + 1];
+ MTPState *s = opaque;
+ MTPObject *parent = usb_mtp_object_lookup_id(s, id);
+ MTPMonEntry *entry = NULL;
+ MTPObject *o;
- for (;;) {
- bytes = read(s->inotifyfd, buf, sizeof(buf));
- pos = 0;
-
- if (bytes <= 0) {
- /* Better luck next time */
- return;
- }
-
- /*
- * TODO: Ignore initiator initiated events.
- * For now we are good because the store is RO
- */
- while (bytes > 0) {
- char *p = buf + pos;
- struct inotify_event *event = (struct inotify_event *)p;
- int watchfd = 0;
- uint32_t mask = event->mask & (IN_CREATE | IN_DELETE |
- IN_MODIFY | IN_IGNORED);
- MTPObject *parent = usb_mtp_object_lookup_wd(s, event->wd);
- MTPMonEntry *entry = NULL;
- MTPObject *o;
-
- pos = pos + sizeof(struct inotify_event) + event->len;
- bytes = bytes - pos;
-
- if (!parent) {
- continue;
- }
-
- switch (mask) {
- case IN_CREATE:
- if (usb_mtp_object_lookup_name
- (parent, event->name, event->len)) {
- /* Duplicate create event */
- continue;
- }
- entry = g_new0(MTPMonEntry, 1);
- entry->handle = s->next_handle;
- entry->event = EVT_OBJ_ADDED;
- o = usb_mtp_add_child(s, parent, event->name);
- if (!o) {
- g_free(entry);
- continue;
- }
- o->watchfd = watchfd;
- trace_usb_mtp_inotify_event(s->dev.addr, event->name,
- event->mask, "Obj Added");
- break;
-
- case IN_DELETE:
- /*
- * The kernel issues a IN_IGNORED event
- * when a dir containing a watchpoint is
- * deleted, so we don't have to delete the
- * watchpoint
- */
- o = usb_mtp_object_lookup_name(parent, event->name, event->len);
- if (!o) {
- continue;
- }
- entry = g_new0(MTPMonEntry, 1);
- entry->handle = o->handle;
- entry->event = EVT_OBJ_REMOVED;
- trace_usb_mtp_inotify_event(s->dev.addr, o->path,
- event->mask, "Obj Deleted");
- usb_mtp_object_free(s, o);
- break;
-
- case IN_MODIFY:
- o = usb_mtp_object_lookup_name(parent, event->name, event->len);
- if (!o) {
- continue;
- }
- entry = g_new0(MTPMonEntry, 1);
- entry->handle = o->handle;
- entry->event = EVT_OBJ_INFO_CHANGED;
- trace_usb_mtp_inotify_event(s->dev.addr, o->path,
- event->mask, "Obj Modified");
- break;
-
- case IN_IGNORED:
- trace_usb_mtp_inotify_event(s->dev.addr, parent->path,
- event->mask, "Obj parent dir ignored");
- break;
-
- default:
- fprintf(stderr, "usb-mtp: failed to parse inotify event\n");
- continue;
- }
-
- if (entry) {
- QTAILQ_INSERT_HEAD(&s->events, entry, next);
- }
- }
- }
-}
-
-static int usb_mtp_inotify_init(MTPState *s)
-{
- int fd;
-
- fd = inotify_init1(IN_NONBLOCK);
- if (fd == -1) {
- return 1;
- }
-
- QTAILQ_INIT(&s->events);
- s->inotifyfd = fd;
-
- qemu_set_fd_handler(fd, inotify_watchfn, NULL, s);
-
- return 0;
-}
-
-static void usb_mtp_inotify_cleanup(MTPState *s)
-{
- MTPMonEntry *e, *p;
-
- if (!s->inotifyfd) {
+ if (!parent) {
return;
}
- qemu_set_fd_handler(s->inotifyfd, NULL, NULL, s);
- close(s->inotifyfd);
+ switch (ev) {
+ case QFILE_MONITOR_EVENT_CREATED:
+ if (usb_mtp_object_lookup_name(parent, name, -1)) {
+ /* Duplicate create event */
+ return;
+ }
+ entry = g_new0(MTPMonEntry, 1);
+ entry->handle = s->next_handle;
+ entry->event = EVT_OBJ_ADDED;
+ o = usb_mtp_add_child(s, parent, name);
+ if (!o) {
+ g_free(entry);
+ return;
+ }
+ trace_usb_mtp_file_monitor_event(s->dev.addr, name, "Obj Added");
+ break;
+
+ case QFILE_MONITOR_EVENT_DELETED:
+ /*
+ * The kernel issues a IN_IGNORED event
+ * when a dir containing a watchpoint is
+ * deleted, so we don't have to delete the
+ * watchpoint
+ */
+ o = usb_mtp_object_lookup_name(parent, name, -1);
+ if (!o) {
+ return;
+ }
+ entry = g_new0(MTPMonEntry, 1);
+ entry->handle = o->handle;
+ entry->event = EVT_OBJ_REMOVED;
+ trace_usb_mtp_file_monitor_event(s->dev.addr, o->path, "Obj Deleted");
+ usb_mtp_object_free(s, o);
+ break;
+
+ case QFILE_MONITOR_EVENT_MODIFIED:
+ o = usb_mtp_object_lookup_name(parent, name, -1);
+ if (!o) {
+ return;
+ }
+ entry = g_new0(MTPMonEntry, 1);
+ entry->handle = o->handle;
+ entry->event = EVT_OBJ_INFO_CHANGED;
+ trace_usb_mtp_file_monitor_event(s->dev.addr, o->path, "Obj Modified");
+ break;
+
+ case QFILE_MONITOR_EVENT_IGNORED:
+ trace_usb_mtp_file_monitor_event(s->dev.addr, parent->path,
+ "Obj parent dir ignored");
+ break;
+
+ case QFILE_MONITOR_EVENT_ATTRIBUTES:
+ break;
+
+ default:
+ g_assert_not_reached();
+ }
+
+ if (entry) {
+ QTAILQ_INSERT_HEAD(&s->events, entry, next);
+ }
+}
+
+static void usb_mtp_file_monitor_cleanup(MTPState *s)
+{
+ MTPMonEntry *e, *p;
QTAILQ_FOREACH_SAFE(e, &s->events, next, p) {
QTAILQ_REMOVE(&s->events, e, next);
g_free(e);
}
+
+ qemu_file_monitor_free(s->file_monitor);
+ s->file_monitor = NULL;
}
-static int usb_mtp_add_watch(int inotifyfd, char *path)
-{
- uint32_t mask = IN_CREATE | IN_DELETE | IN_MODIFY |
- IN_ISDIR;
-
- return inotify_add_watch(inotifyfd, path, mask);
-}
-#endif
static void usb_mtp_object_readdir(MTPState *s, MTPObject *o)
{
struct dirent *entry;
DIR *dir;
int fd;
+ Error *err = NULL;
if (o->have_children) {
return;
@@ -680,16 +623,21 @@
close(fd);
return;
}
-#ifdef CONFIG_INOTIFY1
- int watchfd = usb_mtp_add_watch(s->inotifyfd, o->path);
- if (watchfd == -1) {
- fprintf(stderr, "usb-mtp: failed to add watch for %s\n", o->path);
- } else {
- trace_usb_mtp_inotify_event(s->dev.addr, o->path,
- 0, "Watch Added");
- o->watchfd = watchfd;
+
+ if (s->file_monitor) {
+ int id = qemu_file_monitor_add_watch(s->file_monitor, o->path, NULL,
+ file_monitor_event, s, &err);
+ if (id == -1) {
+ error_report("usb-mtp: failed to add watch for %s: %s", o->path,
+ error_get_pretty(err));
+ error_free(err);
+ } else {
+ trace_usb_mtp_file_monitor_event(s->dev.addr, o->path,
+ "Watch Added");
+ o->watchid = id;
+ }
}
-#endif
+
while ((entry = readdir(dir)) != NULL) {
usb_mtp_add_child(s, o, entry->d_name);
}
@@ -1197,13 +1145,11 @@
/* Assumes that children, if any, have been already freed */
static void usb_mtp_object_free_one(MTPState *s, MTPObject *o)
{
-#ifndef CONFIG_INOTIFY1
assert(o->nchildren == 0);
QTAILQ_REMOVE(&s->objects, o, next);
g_free(o->name);
g_free(o->path);
g_free(o);
-#endif
}
static int usb_mtp_deletefn(MTPState *s, MTPObject *o, uint32_t trans)
@@ -1231,9 +1177,7 @@
usb_mtp_object_free_one(s, o);
success = true;
}
- }
-
- if (o->format == FMT_ASSOCIATION) {
+ } else if (o->format == FMT_ASSOCIATION) {
if (rmdir(o->path)) {
partial_delete = true;
} else {
@@ -1302,6 +1246,7 @@
MTPData *data_in = NULL;
MTPObject *o = NULL;
uint32_t nres = 0, res0 = 0;
+ Error *err = NULL;
/* sanity checks */
if (c->code >= CMD_CLOSE_SESSION && s->session == 0) {
@@ -1329,19 +1274,21 @@
trace_usb_mtp_op_open_session(s->dev.addr);
s->session = c->argv[0];
usb_mtp_object_alloc(s, s->next_handle++, NULL, s->root);
-#ifdef CONFIG_INOTIFY1
- if (usb_mtp_inotify_init(s)) {
- fprintf(stderr, "usb-mtp: file monitoring init failed\n");
+
+ s->file_monitor = qemu_file_monitor_new(&err);
+ if (err) {
+ error_report("usb-mtp: file monitoring init failed: %s",
+ error_get_pretty(err));
+ error_free(err);
+ } else {
+ QTAILQ_INIT(&s->events);
}
-#endif
break;
case CMD_CLOSE_SESSION:
trace_usb_mtp_op_close_session(s->dev.addr);
s->session = 0;
s->next_handle = 0;
-#ifdef CONFIG_INOTIFY1
- usb_mtp_inotify_cleanup(s);
-#endif
+ usb_mtp_file_monitor_cleanup(s);
usb_mtp_object_free(s, QTAILQ_FIRST(&s->objects));
assert(QTAILQ_EMPTY(&s->objects));
break;
@@ -1554,9 +1501,7 @@
trace_usb_mtp_reset(s->dev.addr);
-#ifdef CONFIG_INOTIFY1
- usb_mtp_inotify_cleanup(s);
-#endif
+ usb_mtp_file_monitor_cleanup(s);
usb_mtp_object_free(s, QTAILQ_FIRST(&s->objects));
s->session = 0;
usb_mtp_data_free(s->data_in);
@@ -1644,17 +1589,21 @@
return ret;
}
-static void usb_mtp_update_object(MTPObject *parent, char *name)
+static int usb_mtp_update_object(MTPObject *parent, char *name)
{
+ int ret = -1;
+
MTPObject *o =
usb_mtp_object_lookup_name(parent, name, strlen(name));
if (o) {
- lstat(o->path, &o->stat);
+ ret = lstat(o->path, &o->stat);
}
+
+ return ret;
}
-static void usb_mtp_write_data(MTPState *s)
+static int usb_mtp_write_data(MTPState *s)
{
MTPData *d = s->data_out;
MTPObject *parent =
@@ -1662,6 +1611,7 @@
char *path = NULL;
uint64_t rc;
mode_t mask = 0644;
+ int ret = 0;
assert(d != NULL);
@@ -1670,13 +1620,13 @@
if (!parent || !s->write_pending) {
usb_mtp_queue_result(s, RES_INVALID_OBJECTINFO, d->trans,
0, 0, 0, 0);
- return;
+ return 1;
}
if (s->dataset.filename) {
path = g_strdup_printf("%s/%s", parent->path, s->dataset.filename);
if (s->dataset.format == FMT_ASSOCIATION) {
- d->fd = mkdir(path, mask);
+ ret = mkdir(path, mask);
goto free;
}
d->fd = open(path, O_CREAT | O_WRONLY |
@@ -1706,15 +1656,21 @@
goto done;
}
if (d->write_status != WRITE_END) {
- return;
+ g_free(path);
+ return ret;
} else {
- /* Only for < 4G file sizes */
- if (s->dataset.size != 0xFFFFFFFF && d->offset != s->dataset.size) {
+ /*
+ * Return an incomplete transfer if file size doesn't match
+ * for < 4G file or if lstat fails which will result in an incorrect
+ * file size
+ */
+ if ((s->dataset.size != 0xFFFFFFFF &&
+ d->offset != s->dataset.size) ||
+ usb_mtp_update_object(parent, s->dataset.filename)) {
usb_mtp_queue_result(s, RES_INCOMPLETE_TRANSFER, d->trans,
0, 0, 0, 0);
goto done;
}
- usb_mtp_update_object(parent, s->dataset.filename);
}
}
@@ -1729,12 +1685,14 @@
*/
if (d->fd != -1) {
close(d->fd);
+ d->fd = -1;
}
free:
g_free(s->dataset.filename);
s->dataset.size = 0;
g_free(path);
s->write_pending = false;
+ return ret;
}
static void usb_mtp_write_metadata(MTPState *s, uint64_t dlen)
@@ -1771,14 +1729,12 @@
s->write_pending = true;
if (s->dataset.format == FMT_ASSOCIATION) {
- usb_mtp_write_data(s);
- /* next_handle will be allocated to the newly created dir */
- if (d->fd == -1) {
+ if (usb_mtp_write_data(s)) {
+ /* next_handle will be allocated to the newly created dir */
usb_mtp_queue_result(s, RES_STORE_FULL, d->trans,
0, 0, 0, 0);
return;
}
- d->fd = -1;
}
usb_mtp_queue_result(s, RES_OK, d->trans, 3, QEMU_STORAGE_ID,
@@ -2027,7 +1983,6 @@
}
break;
case EP_EVENT:
-#ifdef CONFIG_INOTIFY1
if (!QTAILQ_EMPTY(&s->events)) {
struct MTPMonEntry *e = QTAILQ_LAST(&s->events);
uint32_t handle;
@@ -2051,7 +2006,6 @@
g_free(e);
return;
}
-#endif
p->status = USB_RET_NAK;
return;
default:
diff --git a/hw/usb/host-libusb.c b/hw/usb/host-libusb.c
index 833250a..67b7465 100644
--- a/hw/usb/host-libusb.c
+++ b/hw/usb/host-libusb.c
@@ -82,7 +82,7 @@
uint32_t options;
uint32_t loglevel;
bool needs_autoscan;
-
+ bool allow_guest_reset;
/* state */
QTAILQ_ENTRY(USBHostDevice) next;
int seen, errcount;
@@ -1456,6 +1456,10 @@
USBHostDevice *s = USB_HOST_DEVICE(udev);
int rc;
+ if (!s->allow_guest_reset) {
+ return;
+ }
+
trace_usb_host_reset(s->bus_num, s->addr);
rc = libusb_reset_device(s->dh);
@@ -1573,6 +1577,7 @@
DEFINE_PROP_UINT32("productid", USBHostDevice, match.product_id, 0),
DEFINE_PROP_UINT32("isobufs", USBHostDevice, iso_urb_count, 4),
DEFINE_PROP_UINT32("isobsize", USBHostDevice, iso_urb_frames, 32),
+ DEFINE_PROP_BOOL("guest-reset", USBHostDevice, allow_guest_reset, true),
DEFINE_PROP_UINT32("loglevel", USBHostDevice, loglevel,
LIBUSB_LOG_LEVEL_WARNING),
DEFINE_PROP_BIT("pipeline", USBHostDevice, options,
diff --git a/hw/usb/trace-events b/hw/usb/trace-events
index 2c18770..99b1e8b 100644
--- a/hw/usb/trace-events
+++ b/hw/usb/trace-events
@@ -237,7 +237,7 @@
usb_mtp_object_alloc(int dev, uint32_t handle, const char *path) "dev %d, handle 0x%x, path %s"
usb_mtp_object_free(int dev, uint32_t handle, const char *path) "dev %d, handle 0x%x, path %s"
usb_mtp_add_child(int dev, uint32_t handle, const char *path) "dev %d, handle 0x%x, path %s"
-usb_mtp_inotify_event(int dev, const char *path, uint32_t mask, const char *s) "dev %d, path %s mask 0x%x event %s"
+usb_mtp_file_monitor_event(int dev, const char *path, const char *s) "dev %d, path %s event %s"
# hw/usb/host-libusb.c
usb_host_open_started(int bus, int addr) "dev %d:%d"
diff --git a/hw/vfio/ap.c b/hw/vfio/ap.c
index 6166ccd..d8b79eb 100644
--- a/hw/vfio/ap.c
+++ b/hw/vfio/ap.c
@@ -169,7 +169,7 @@
set_bit(DEVICE_CATEGORY_MISC, dc->categories);
dc->realize = vfio_ap_realize;
dc->unrealize = vfio_ap_unrealize;
- dc->hotpluggable = false;
+ dc->hotpluggable = true;
dc->reset = vfio_ap_reset;
dc->bus_type = TYPE_AP_BUS;
}
diff --git a/hw/vfio/pci-quirks.c b/hw/vfio/pci-quirks.c
index eae31c7..40a1200 100644
--- a/hw/vfio/pci-quirks.c
+++ b/hw/vfio/pci-quirks.c
@@ -526,8 +526,6 @@
* note it for future reference.
*/
-#define PCI_VENDOR_ID_NVIDIA 0x10de
-
/*
* Nvidia has several different methods to get to config space, the
* nouveu project has several of these documented here:
diff --git a/hw/virtio/Makefile.objs b/hw/virtio/Makefile.objs
index d335dd0..a3eb8ed 100644
--- a/hw/virtio/Makefile.objs
+++ b/hw/virtio/Makefile.objs
@@ -2,15 +2,18 @@
common-obj-y += virtio-bus.o
obj-y += virtio.o
+obj-$(call lor,$(CONFIG_VHOST_USER),$(CONFIG_VHOST_KERNEL)) += vhost.o vhost-backend.o
+common-obj-$(call lnot,$(call lor,$(CONFIG_VHOST_USER),$(CONFIG_VHOST_KERNEL))) += vhost-stub.o
+obj-$(CONFIG_VHOST_USER) += vhost-user.o
+
common-obj-$(CONFIG_VIRTIO_RNG) += virtio-rng.o
common-obj-$(CONFIG_VIRTIO_PCI) += virtio-pci.o
common-obj-$(CONFIG_VIRTIO_MMIO) += virtio-mmio.o
obj-$(CONFIG_VIRTIO_BALLOON) += virtio-balloon.o
obj-$(CONFIG_VIRTIO_CRYPTO) += virtio-crypto.o
obj-$(call land,$(CONFIG_VIRTIO_CRYPTO),$(CONFIG_VIRTIO_PCI)) += virtio-crypto-pci.o
-
-obj-$(CONFIG_LINUX) += vhost.o vhost-backend.o vhost-user.o
obj-$(CONFIG_VHOST_VSOCK) += vhost-vsock.o
+
ifeq ($(CONFIG_VIRTIO_PCI),y)
obj-$(CONFIG_VHOST_VSOCK) += vhost-vsock-pci.o
obj-$(CONFIG_VHOST_USER_BLK) += vhost-user-blk-pci.o
@@ -28,5 +31,4 @@
endif
endif
-common-obj-$(call lnot,$(call land,$(CONFIG_VIRTIO),$(CONFIG_LINUX))) += vhost-stub.o
common-obj-$(CONFIG_ALL) += vhost-stub.o
diff --git a/hw/virtio/vhost-backend.c b/hw/virtio/vhost-backend.c
index 7f09efa..96b8d3c 100644
--- a/hw/virtio/vhost-backend.c
+++ b/hw/virtio/vhost-backend.c
@@ -9,11 +9,14 @@
*/
#include "qemu/osdep.h"
-#include <linux/vhost.h>
-#include <sys/ioctl.h>
#include "hw/virtio/vhost.h"
#include "hw/virtio/vhost-backend.h"
#include "qemu/error-report.h"
+#include "standard-headers/linux/vhost_types.h"
+
+#ifdef CONFIG_VHOST_KERNEL
+#include <linux/vhost.h>
+#include <sys/ioctl.h>
static int vhost_kernel_call(struct vhost_dev *dev, unsigned long int request,
void *arg)
@@ -265,18 +268,23 @@
.vhost_set_iotlb_callback = vhost_kernel_set_iotlb_callback,
.vhost_send_device_iotlb_msg = vhost_kernel_send_device_iotlb_msg,
};
+#endif
int vhost_set_backend_type(struct vhost_dev *dev, VhostBackendType backend_type)
{
int r = 0;
switch (backend_type) {
+#ifdef CONFIG_VHOST_KERNEL
case VHOST_BACKEND_TYPE_KERNEL:
dev->vhost_ops = &kernel_ops;
break;
+#endif
+#ifdef CONFIG_VHOST_USER
case VHOST_BACKEND_TYPE_USER:
dev->vhost_ops = &user_ops;
break;
+#endif
default:
error_report("Unknown vhost backend type");
r = -1;
diff --git a/hw/virtio/vhost-user.c b/hw/virtio/vhost-user.c
index 564a31d..0d6c64e 100644
--- a/hw/virtio/vhost-user.c
+++ b/hw/virtio/vhost-user.c
@@ -27,8 +27,12 @@
#include <sys/ioctl.h>
#include <sys/socket.h>
#include <sys/un.h>
-#include <linux/vhost.h>
+
+#include "standard-headers/linux/vhost_types.h"
+
+#ifdef CONFIG_LINUX
#include <linux/userfaultfd.h>
+#endif
#define VHOST_MEMORY_MAX_NREGIONS 8
#define VHOST_USER_F_PROTOCOL_FEATURES 30
@@ -1110,6 +1114,7 @@
return ret;
}
+#ifdef CONFIG_LINUX
/*
* Called back from the postcopy fault thread when a fault is received on our
* ufd.
@@ -1177,6 +1182,7 @@
trace_vhost_user_postcopy_waker_nomatch(qemu_ram_get_idstr(rb), offset);
return 0;
}
+#endif
/*
* Called at the start of an inbound postcopy on reception of the
@@ -1184,6 +1190,7 @@
*/
static int vhost_user_postcopy_advise(struct vhost_dev *dev, Error **errp)
{
+#ifdef CONFIG_LINUX
struct vhost_user *u = dev->opaque;
CharBackend *chr = u->user->chr;
int ufd;
@@ -1227,6 +1234,10 @@
u->postcopy_fd.idstr = "vhost-user"; /* Need to find unique name */
postcopy_register_shared_ufd(&u->postcopy_fd);
return 0;
+#else
+ error_setg(errp, "Postcopy not supported on non-Linux systems");
+ return -1;
+#endif
}
/*
diff --git a/hw/virtio/vhost.c b/hw/virtio/vhost.c
index 569c405..311432f 100644
--- a/hw/virtio/vhost.c
+++ b/hw/virtio/vhost.c
@@ -21,7 +21,7 @@
#include "qemu/range.h"
#include "qemu/error-report.h"
#include "qemu/memfd.h"
-#include <linux/vhost.h>
+#include "standard-headers/linux/vhost_types.h"
#include "exec/address-spaces.h"
#include "hw/virtio/virtio-bus.h"
#include "hw/virtio/virtio-access.h"
diff --git a/hw/virtio/virtio-balloon.c b/hw/virtio/virtio-balloon.c
index a12677d..e3a6594 100644
--- a/hw/virtio/virtio-balloon.c
+++ b/hw/virtio/virtio-balloon.c
@@ -27,17 +27,88 @@
#include "qapi/visitor.h"
#include "trace.h"
#include "qemu/error-report.h"
+#include "migration/misc.h"
#include "hw/virtio/virtio-bus.h"
#include "hw/virtio/virtio-access.h"
#define BALLOON_PAGE_SIZE (1 << VIRTIO_BALLOON_PFN_SHIFT)
-static void balloon_page(void *addr, int deflate)
+struct PartiallyBalloonedPage {
+ RAMBlock *rb;
+ ram_addr_t base;
+ unsigned long bitmap[];
+};
+
+static void balloon_inflate_page(VirtIOBalloon *balloon,
+ MemoryRegion *mr, hwaddr offset)
{
- if (!qemu_balloon_is_inhibited()) {
- qemu_madvise(addr, BALLOON_PAGE_SIZE,
- deflate ? QEMU_MADV_WILLNEED : QEMU_MADV_DONTNEED);
+ void *addr = memory_region_get_ram_ptr(mr) + offset;
+ RAMBlock *rb;
+ size_t rb_page_size;
+ int subpages;
+ ram_addr_t ram_offset, host_page_base;
+
+ /* XXX is there a better way to get to the RAMBlock than via a
+ * host address? */
+ rb = qemu_ram_block_from_host(addr, false, &ram_offset);
+ rb_page_size = qemu_ram_pagesize(rb);
+ host_page_base = ram_offset & ~(rb_page_size - 1);
+
+ if (rb_page_size == BALLOON_PAGE_SIZE) {
+ /* Easy case */
+
+ ram_block_discard_range(rb, ram_offset, rb_page_size);
+ /* We ignore errors from ram_block_discard_range(), because it
+ * has already reported them, and failing to discard a balloon
+ * page is not fatal */
+ return;
+ }
+
+ /* Hard case
+ *
+ * We've put a piece of a larger host page into the balloon - we
+ * need to keep track until we have a whole host page to
+ * discard
+ */
+ warn_report_once(
+"Balloon used with backing page size > 4kiB, this may not be reliable");
+
+ subpages = rb_page_size / BALLOON_PAGE_SIZE;
+
+ if (balloon->pbp
+ && (rb != balloon->pbp->rb
+ || host_page_base != balloon->pbp->base)) {
+ /* We've partially ballooned part of a host page, but now
+ * we're trying to balloon part of a different one. Too hard,
+ * give up on the old partial page */
+ free(balloon->pbp);
+ balloon->pbp = NULL;
+ }
+
+ if (!balloon->pbp) {
+ /* Starting on a new host page */
+ size_t bitlen = BITS_TO_LONGS(subpages) * sizeof(unsigned long);
+ balloon->pbp = g_malloc0(sizeof(PartiallyBalloonedPage) + bitlen);
+ balloon->pbp->rb = rb;
+ balloon->pbp->base = host_page_base;
+ }
+
+ bitmap_set(balloon->pbp->bitmap,
+ (ram_offset - balloon->pbp->base) / BALLOON_PAGE_SIZE,
+ subpages);
+
+ if (bitmap_full(balloon->pbp->bitmap, subpages)) {
+ /* We've accumulated a full host page, we can actually discard
+ * it now */
+
+ ram_block_discard_range(rb, balloon->pbp->base, rb_page_size);
+ /* We ignore errors from ram_block_discard_range(), because it
+ * has already reported them, and failing to discard a balloon
+ * page is not fatal */
+
+ free(balloon->pbp);
+ balloon->pbp = NULL;
}
}
@@ -222,17 +293,19 @@
}
while (iov_to_buf(elem->out_sg, elem->out_num, offset, &pfn, 4) == 4) {
- ram_addr_t pa;
- ram_addr_t addr;
+ hwaddr pa;
int p = virtio_ldl_p(vdev, &pfn);
- pa = (ram_addr_t) p << VIRTIO_BALLOON_PFN_SHIFT;
+ pa = (hwaddr) p << VIRTIO_BALLOON_PFN_SHIFT;
offset += 4;
- /* FIXME: remove get_system_memory(), but how? */
- section = memory_region_find(get_system_memory(), pa, 1);
- if (!int128_nz(section.size) ||
- !memory_region_is_ram(section.mr) ||
+ section = memory_region_find(get_system_memory(), pa,
+ BALLOON_PAGE_SIZE);
+ if (!section.mr) {
+ trace_virtio_balloon_bad_addr(pa);
+ continue;
+ }
+ if (!memory_region_is_ram(section.mr) ||
memory_region_is_rom(section.mr) ||
memory_region_is_romd(section.mr)) {
trace_virtio_balloon_bad_addr(pa);
@@ -242,11 +315,9 @@
trace_virtio_balloon_handle_output(memory_region_name(section.mr),
pa);
- /* Using memory_region_get_ram_ptr is bending the rules a bit, but
- should be OK because we only want a single page. */
- addr = section.offset_within_region;
- balloon_page(memory_region_get_ram_ptr(section.mr) + addr,
- !!(vq == s->dvq));
+ if (!qemu_balloon_is_inhibited() && vq != s->dvq) {
+ balloon_inflate_page(s, section.mr, section.offset_within_region);
+ }
memory_region_unref(section.mr);
}
@@ -308,6 +379,184 @@
}
}
+static void virtio_balloon_handle_free_page_vq(VirtIODevice *vdev,
+ VirtQueue *vq)
+{
+ VirtIOBalloon *s = VIRTIO_BALLOON(vdev);
+ qemu_bh_schedule(s->free_page_bh);
+}
+
+static bool get_free_page_hints(VirtIOBalloon *dev)
+{
+ VirtQueueElement *elem;
+ VirtIODevice *vdev = VIRTIO_DEVICE(dev);
+ VirtQueue *vq = dev->free_page_vq;
+
+ while (dev->block_iothread) {
+ qemu_cond_wait(&dev->free_page_cond, &dev->free_page_lock);
+ }
+
+ elem = virtqueue_pop(vq, sizeof(VirtQueueElement));
+ if (!elem) {
+ return false;
+ }
+
+ if (elem->out_num) {
+ uint32_t id;
+ size_t size = iov_to_buf(elem->out_sg, elem->out_num, 0,
+ &id, sizeof(id));
+ virtqueue_push(vq, elem, size);
+ g_free(elem);
+
+ virtio_tswap32s(vdev, &id);
+ if (unlikely(size != sizeof(id))) {
+ virtio_error(vdev, "received an incorrect cmd id");
+ return false;
+ }
+ if (id == dev->free_page_report_cmd_id) {
+ dev->free_page_report_status = FREE_PAGE_REPORT_S_START;
+ } else {
+ /*
+ * Stop the optimization only when it has started. This
+ * avoids a stale stop sign for the previous command.
+ */
+ if (dev->free_page_report_status == FREE_PAGE_REPORT_S_START) {
+ dev->free_page_report_status = FREE_PAGE_REPORT_S_STOP;
+ }
+ }
+ }
+
+ if (elem->in_num) {
+ if (dev->free_page_report_status == FREE_PAGE_REPORT_S_START) {
+ qemu_guest_free_page_hint(elem->in_sg[0].iov_base,
+ elem->in_sg[0].iov_len);
+ }
+ virtqueue_push(vq, elem, 1);
+ g_free(elem);
+ }
+
+ return true;
+}
+
+static void virtio_ballloon_get_free_page_hints(void *opaque)
+{
+ VirtIOBalloon *dev = opaque;
+ VirtIODevice *vdev = VIRTIO_DEVICE(dev);
+ VirtQueue *vq = dev->free_page_vq;
+ bool continue_to_get_hints;
+
+ do {
+ qemu_mutex_lock(&dev->free_page_lock);
+ virtio_queue_set_notification(vq, 0);
+ continue_to_get_hints = get_free_page_hints(dev);
+ qemu_mutex_unlock(&dev->free_page_lock);
+ virtio_notify(vdev, vq);
+ /*
+ * Start to poll the vq once the reporting started. Otherwise, continue
+ * only when there are entries on the vq, which need to be given back.
+ */
+ } while (continue_to_get_hints ||
+ dev->free_page_report_status == FREE_PAGE_REPORT_S_START);
+ virtio_queue_set_notification(vq, 1);
+}
+
+static bool virtio_balloon_free_page_support(void *opaque)
+{
+ VirtIOBalloon *s = opaque;
+ VirtIODevice *vdev = VIRTIO_DEVICE(s);
+
+ return virtio_vdev_has_feature(vdev, VIRTIO_BALLOON_F_FREE_PAGE_HINT);
+}
+
+static void virtio_balloon_free_page_start(VirtIOBalloon *s)
+{
+ VirtIODevice *vdev = VIRTIO_DEVICE(s);
+
+ /* For the stop and copy phase, we don't need to start the optimization */
+ if (!vdev->vm_running) {
+ return;
+ }
+
+ if (s->free_page_report_cmd_id == UINT_MAX) {
+ s->free_page_report_cmd_id =
+ VIRTIO_BALLOON_FREE_PAGE_REPORT_CMD_ID_MIN;
+ } else {
+ s->free_page_report_cmd_id++;
+ }
+
+ s->free_page_report_status = FREE_PAGE_REPORT_S_REQUESTED;
+ virtio_notify_config(vdev);
+}
+
+static void virtio_balloon_free_page_stop(VirtIOBalloon *s)
+{
+ VirtIODevice *vdev = VIRTIO_DEVICE(s);
+
+ if (s->free_page_report_status != FREE_PAGE_REPORT_S_STOP) {
+ /*
+ * The lock also guarantees us that the
+ * virtio_ballloon_get_free_page_hints exits after the
+ * free_page_report_status is set to S_STOP.
+ */
+ qemu_mutex_lock(&s->free_page_lock);
+ /*
+ * The guest hasn't done the reporting, so host sends a notification
+ * to the guest to actively stop the reporting.
+ */
+ s->free_page_report_status = FREE_PAGE_REPORT_S_STOP;
+ qemu_mutex_unlock(&s->free_page_lock);
+ virtio_notify_config(vdev);
+ }
+}
+
+static void virtio_balloon_free_page_done(VirtIOBalloon *s)
+{
+ VirtIODevice *vdev = VIRTIO_DEVICE(s);
+
+ s->free_page_report_status = FREE_PAGE_REPORT_S_DONE;
+ virtio_notify_config(vdev);
+}
+
+static int
+virtio_balloon_free_page_report_notify(NotifierWithReturn *n, void *data)
+{
+ VirtIOBalloon *dev = container_of(n, VirtIOBalloon,
+ free_page_report_notify);
+ VirtIODevice *vdev = VIRTIO_DEVICE(dev);
+ PrecopyNotifyData *pnd = data;
+
+ if (!virtio_balloon_free_page_support(dev)) {
+ /*
+ * This is an optimization provided to migration, so just return 0 to
+ * have the normal migration process not affected when this feature is
+ * not supported.
+ */
+ return 0;
+ }
+
+ switch (pnd->reason) {
+ case PRECOPY_NOTIFY_SETUP:
+ precopy_enable_free_page_optimization();
+ break;
+ case PRECOPY_NOTIFY_COMPLETE:
+ case PRECOPY_NOTIFY_CLEANUP:
+ case PRECOPY_NOTIFY_BEFORE_BITMAP_SYNC:
+ virtio_balloon_free_page_stop(dev);
+ break;
+ case PRECOPY_NOTIFY_AFTER_BITMAP_SYNC:
+ if (vdev->vm_running) {
+ virtio_balloon_free_page_start(dev);
+ } else {
+ virtio_balloon_free_page_done(dev);
+ }
+ break;
+ default:
+ virtio_error(vdev, "%s: %d reason unknown", __func__, pnd->reason);
+ }
+
+ return 0;
+}
+
static void virtio_balloon_get_config(VirtIODevice *vdev, uint8_t *config_data)
{
VirtIOBalloon *dev = VIRTIO_BALLOON(vdev);
@@ -316,6 +565,17 @@
config.num_pages = cpu_to_le32(dev->num_pages);
config.actual = cpu_to_le32(dev->actual);
+ if (dev->free_page_report_status == FREE_PAGE_REPORT_S_REQUESTED) {
+ config.free_page_report_cmd_id =
+ cpu_to_le32(dev->free_page_report_cmd_id);
+ } else if (dev->free_page_report_status == FREE_PAGE_REPORT_S_STOP) {
+ config.free_page_report_cmd_id =
+ cpu_to_le32(VIRTIO_BALLOON_CMD_ID_STOP);
+ } else if (dev->free_page_report_status == FREE_PAGE_REPORT_S_DONE) {
+ config.free_page_report_cmd_id =
+ cpu_to_le32(VIRTIO_BALLOON_CMD_ID_DONE);
+ }
+
trace_virtio_balloon_get_config(config.num_pages, config.actual);
memcpy(config_data, &config, sizeof(struct virtio_balloon_config));
}
@@ -376,6 +636,7 @@
VirtIOBalloon *dev = VIRTIO_BALLOON(vdev);
f |= dev->host_features;
virtio_add_feature(&f, VIRTIO_BALLOON_F_STATS_VQ);
+
return f;
}
@@ -412,6 +673,18 @@
return 0;
}
+static const VMStateDescription vmstate_virtio_balloon_free_page_report = {
+ .name = "virtio-balloon-device/free-page-report",
+ .version_id = 1,
+ .minimum_version_id = 1,
+ .needed = virtio_balloon_free_page_support,
+ .fields = (VMStateField[]) {
+ VMSTATE_UINT32(free_page_report_cmd_id, VirtIOBalloon),
+ VMSTATE_UINT32(free_page_report_status, VirtIOBalloon),
+ VMSTATE_END_OF_LIST()
+ }
+};
+
static const VMStateDescription vmstate_virtio_balloon_device = {
.name = "virtio-balloon-device",
.version_id = 1,
@@ -422,6 +695,10 @@
VMSTATE_UINT32(actual, VirtIOBalloon),
VMSTATE_END_OF_LIST()
},
+ .subsections = (const VMStateDescription * []) {
+ &vmstate_virtio_balloon_free_page_report,
+ NULL
+ }
};
static void virtio_balloon_device_realize(DeviceState *dev, Error **errp)
@@ -446,6 +723,29 @@
s->dvq = virtio_add_queue(vdev, 128, virtio_balloon_handle_output);
s->svq = virtio_add_queue(vdev, 128, virtio_balloon_receive_stats);
+ if (virtio_has_feature(s->host_features,
+ VIRTIO_BALLOON_F_FREE_PAGE_HINT)) {
+ s->free_page_vq = virtio_add_queue(vdev, VIRTQUEUE_MAX_SIZE,
+ virtio_balloon_handle_free_page_vq);
+ s->free_page_report_status = FREE_PAGE_REPORT_S_STOP;
+ s->free_page_report_cmd_id =
+ VIRTIO_BALLOON_FREE_PAGE_REPORT_CMD_ID_MIN;
+ s->free_page_report_notify.notify =
+ virtio_balloon_free_page_report_notify;
+ precopy_add_notifier(&s->free_page_report_notify);
+ if (s->iothread) {
+ object_ref(OBJECT(s->iothread));
+ s->free_page_bh = aio_bh_new(iothread_get_aio_context(s->iothread),
+ virtio_ballloon_get_free_page_hints, s);
+ qemu_mutex_init(&s->free_page_lock);
+ qemu_cond_init(&s->free_page_cond);
+ s->block_iothread = false;
+ } else {
+ /* Simply disable this feature if the iothread wasn't created. */
+ s->host_features &= ~(1 << VIRTIO_BALLOON_F_FREE_PAGE_HINT);
+ virtio_error(vdev, "iothread is missing");
+ }
+ }
reset_stats(s);
}
@@ -454,6 +754,11 @@
VirtIODevice *vdev = VIRTIO_DEVICE(dev);
VirtIOBalloon *s = VIRTIO_BALLOON(dev);
+ if (virtio_balloon_free_page_support(s)) {
+ qemu_bh_delete(s->free_page_bh);
+ virtio_balloon_free_page_stop(s);
+ precopy_remove_notifier(&s->free_page_report_notify);
+ }
balloon_stats_destroy_timer(s);
qemu_remove_balloon_handler(s);
virtio_cleanup(vdev);
@@ -463,6 +768,10 @@
{
VirtIOBalloon *s = VIRTIO_BALLOON(vdev);
+ if (virtio_balloon_free_page_support(s)) {
+ virtio_balloon_free_page_stop(s);
+ }
+
if (s->stats_vq_elem != NULL) {
virtqueue_unpop(s->svq, s->stats_vq_elem, 0);
g_free(s->stats_vq_elem);
@@ -480,6 +789,26 @@
* was stopped */
virtio_balloon_receive_stats(vdev, s->svq);
}
+
+ if (virtio_balloon_free_page_support(s)) {
+ /*
+ * The VM is woken up and the iothread was blocked, so signal it to
+ * continue.
+ */
+ if (vdev->vm_running && s->block_iothread) {
+ qemu_mutex_lock(&s->free_page_lock);
+ s->block_iothread = false;
+ qemu_cond_signal(&s->free_page_cond);
+ qemu_mutex_unlock(&s->free_page_lock);
+ }
+
+ /* The VM is stopped, block the iothread. */
+ if (!vdev->vm_running) {
+ qemu_mutex_lock(&s->free_page_lock);
+ s->block_iothread = true;
+ qemu_mutex_unlock(&s->free_page_lock);
+ }
+ }
}
static void virtio_balloon_instance_init(Object *obj)
@@ -508,6 +837,10 @@
static Property virtio_balloon_properties[] = {
DEFINE_PROP_BIT("deflate-on-oom", VirtIOBalloon, host_features,
VIRTIO_BALLOON_F_DEFLATE_ON_OOM, false),
+ DEFINE_PROP_BIT("free-page-hint", VirtIOBalloon, host_features,
+ VIRTIO_BALLOON_F_FREE_PAGE_HINT, false),
+ DEFINE_PROP_LINK("iothread", VirtIOBalloon, iothread, TYPE_IOTHREAD,
+ IOThread *),
DEFINE_PROP_END_OF_LIST(),
};
diff --git a/hw/virtio/virtio.c b/hw/virtio/virtio.c
index a1ff647..2626a89 100644
--- a/hw/virtio/virtio.c
+++ b/hw/virtio/virtio.c
@@ -2036,6 +2036,21 @@
return ret;
}
+size_t virtio_feature_get_config_size(VirtIOFeature *feature_sizes,
+ uint64_t host_features)
+{
+ size_t config_size = 0;
+ int i;
+
+ for (i = 0; feature_sizes[i].flags != 0; i++) {
+ if (host_features & feature_sizes[i].flags) {
+ config_size = MAX(feature_sizes[i].end, config_size);
+ }
+ }
+
+ return config_size;
+}
+
int virtio_load(VirtIODevice *vdev, QEMUFile *f, int version_id)
{
int i, ret;
diff --git a/hw/watchdog/cmsdk-apb-watchdog.c b/hw/watchdog/cmsdk-apb-watchdog.c
index eb79a73..9c865bc 100644
--- a/hw/watchdog/cmsdk-apb-watchdog.c
+++ b/hw/watchdog/cmsdk-apb-watchdog.c
@@ -14,6 +14,10 @@
* System Design Kit (CMSDK) and documented in the Cortex-M System
* Design Kit Technical Reference Manual (ARM DDI0479C):
* https://developer.arm.com/products/system-design/system-design-kits/cortex-m-system-design-kit
+ *
+ * We also support the variant of this device found in the TI
+ * Stellaris/Luminary boards and documented in:
+ * http://www.ti.com/lit/ds/symlink/lm3s6965.pdf
*/
#include "qemu/osdep.h"
@@ -37,6 +41,7 @@
REG32(WDOGRIS, 0x10)
FIELD(WDOGRIS, INT, 0, 1)
REG32(WDOGMIS, 0x14)
+REG32(WDOGTEST, 0x418) /* only in Stellaris/Luminary version of the device */
REG32(WDOGLOCK, 0xc00)
#define WDOG_UNLOCK_VALUE 0x1ACCE551
REG32(WDOGITCR, 0xf00)
@@ -61,12 +66,18 @@
REG32(CID3, 0xffc)
/* PID/CID values */
-static const int watchdog_id[] = {
+static const uint32_t cmsdk_apb_watchdog_id[] = {
0x04, 0x00, 0x00, 0x00, /* PID4..PID7 */
0x24, 0xb8, 0x1b, 0x00, /* PID0..PID3 */
0x0d, 0xf0, 0x05, 0xb1, /* CID0..CID3 */
};
+static const uint32_t luminary_watchdog_id[] = {
+ 0x00, 0x00, 0x00, 0x00, /* PID4..PID7 */
+ 0x05, 0x18, 0x18, 0x01, /* PID0..PID3 */
+ 0x0d, 0xf0, 0x05, 0xb1, /* CID0..CID3 */
+};
+
static bool cmsdk_apb_watchdog_intstatus(CMSDKAPBWatchdog *s)
{
/* Return masked interrupt status */
@@ -85,6 +96,10 @@
bool wdogres;
if (s->itcr) {
+ /*
+ * Not checking that !s->is_luminary since s->itcr can't be written
+ * when s->is_luminary in the first place.
+ */
wdogint = s->itop & R_WDOGITOP_WDOGINT_MASK;
wdogres = s->itop & R_WDOGITOP_WDOGRES_MASK;
} else {
@@ -124,19 +139,34 @@
r = s->lock;
break;
case A_WDOGITCR:
+ if (s->is_luminary) {
+ goto bad_offset;
+ }
r = s->itcr;
break;
case A_PID4 ... A_CID3:
- r = watchdog_id[(offset - A_PID4) / 4];
+ r = s->id[(offset - A_PID4) / 4];
break;
case A_WDOGINTCLR:
case A_WDOGITOP:
+ if (s->is_luminary) {
+ goto bad_offset;
+ }
qemu_log_mask(LOG_GUEST_ERROR,
"CMSDK APB watchdog read: read of WO offset %x\n",
(int)offset);
r = 0;
break;
+ case A_WDOGTEST:
+ if (!s->is_luminary) {
+ goto bad_offset;
+ }
+ qemu_log_mask(LOG_UNIMP,
+ "Luminary watchdog read: stall not implemented\n");
+ r = 0;
+ break;
default:
+bad_offset:
qemu_log_mask(LOG_GUEST_ERROR,
"CMSDK APB watchdog read: bad offset %x\n", (int)offset);
r = 0;
@@ -170,6 +200,14 @@
ptimer_run(s->timer, 0);
break;
case A_WDOGCONTROL:
+ if (s->is_luminary && 0 != (R_WDOGCONTROL_INTEN_MASK & s->control)) {
+ /*
+ * The Luminary version of this device ignores writes to
+ * this register after the guest has enabled interrupts
+ * (so they can only be disabled again via reset).
+ */
+ break;
+ }
s->control = value & R_WDOGCONTROL_VALID_MASK;
cmsdk_apb_watchdog_update(s);
break;
@@ -182,10 +220,16 @@
s->lock = (value != WDOG_UNLOCK_VALUE);
break;
case A_WDOGITCR:
+ if (s->is_luminary) {
+ goto bad_offset;
+ }
s->itcr = value & R_WDOGITCR_VALID_MASK;
cmsdk_apb_watchdog_update(s);
break;
case A_WDOGITOP:
+ if (s->is_luminary) {
+ goto bad_offset;
+ }
s->itop = value & R_WDOGITOP_VALID_MASK;
cmsdk_apb_watchdog_update(s);
break;
@@ -197,7 +241,15 @@
"CMSDK APB watchdog write: write to RO offset 0x%x\n",
(int)offset);
break;
+ case A_WDOGTEST:
+ if (!s->is_luminary) {
+ goto bad_offset;
+ }
+ qemu_log_mask(LOG_UNIMP,
+ "Luminary watchdog write: stall not implemented\n");
+ break;
default:
+bad_offset:
qemu_log_mask(LOG_GUEST_ERROR,
"CMSDK APB watchdog write: bad offset 0x%x\n",
(int)offset);
@@ -256,6 +308,9 @@
s, "cmsdk-apb-watchdog", 0x1000);
sysbus_init_mmio(sbd, &s->iomem);
sysbus_init_irq(sbd, &s->wdogint);
+
+ s->is_luminary = false;
+ s->id = cmsdk_apb_watchdog_id;
}
static void cmsdk_apb_watchdog_realize(DeviceState *dev, Error **errp)
@@ -318,9 +373,24 @@
.class_init = cmsdk_apb_watchdog_class_init,
};
+static void luminary_watchdog_init(Object *obj)
+{
+ CMSDKAPBWatchdog *s = CMSDK_APB_WATCHDOG(obj);
+
+ s->is_luminary = true;
+ s->id = luminary_watchdog_id;
+}
+
+static const TypeInfo luminary_watchdog_info = {
+ .name = TYPE_LUMINARY_WATCHDOG,
+ .parent = TYPE_CMSDK_APB_WATCHDOG,
+ .instance_init = luminary_watchdog_init
+};
+
static void cmsdk_apb_watchdog_register_types(void)
{
type_register_static(&cmsdk_apb_watchdog_info);
+ type_register_static(&luminary_watchdog_info);
}
type_init(cmsdk_apb_watchdog_register_types);
diff --git a/include/authz/base.h b/include/authz/base.h
new file mode 100644
index 0000000..77dcd54
--- /dev/null
+++ b/include/authz/base.h
@@ -0,0 +1,112 @@
+/*
+ * QEMU authorization framework base class
+ *
+ * Copyright (c) 2018 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * 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/>.
+ *
+ */
+
+#ifndef QAUTHZ_BASE_H__
+#define QAUTHZ_BASE_H__
+
+#include "qemu-common.h"
+#include "qapi/error.h"
+#include "qom/object.h"
+
+
+#define TYPE_QAUTHZ "authz"
+
+#define QAUTHZ_CLASS(klass) \
+ OBJECT_CLASS_CHECK(QAuthZClass, (klass), \
+ TYPE_QAUTHZ)
+#define QAUTHZ_GET_CLASS(obj) \
+ OBJECT_GET_CLASS(QAuthZClass, (obj), \
+ TYPE_QAUTHZ)
+#define QAUTHZ(obj) \
+ INTERFACE_CHECK(QAuthZ, (obj), \
+ TYPE_QAUTHZ)
+
+typedef struct QAuthZ QAuthZ;
+typedef struct QAuthZClass QAuthZClass;
+
+/**
+ * QAuthZ:
+ *
+ * The QAuthZ class defines an API contract to be used
+ * for providing an authorization driver for services
+ * with user identities.
+ */
+
+struct QAuthZ {
+ Object parent_obj;
+};
+
+
+struct QAuthZClass {
+ ObjectClass parent_class;
+
+ bool (*is_allowed)(QAuthZ *authz,
+ const char *identity,
+ Error **errp);
+};
+
+
+/**
+ * qauthz_is_allowed:
+ * @authz: the authorization object
+ * @identity: the user identity to authorize
+ * @errp: pointer to a NULL initialized error object
+ *
+ * Check if a user @identity is authorized. If an error
+ * occurs this method will return false to indicate
+ * denial, as well as setting @errp to contain the details.
+ * Callers are recommended to treat the denial and error
+ * scenarios identically. Specifically the error info in
+ * @errp should never be fed back to the user being
+ * authorized, it is merely for benefit of administrator
+ * debugging.
+ *
+ * Returns: true if @identity is authorized, false if denied or if
+ * an error occurred.
+ */
+bool qauthz_is_allowed(QAuthZ *authz,
+ const char *identity,
+ Error **errp);
+
+
+/**
+ * qauthz_is_allowed_by_id:
+ * @authzid: ID of the authorization object
+ * @identity: the user identity to authorize
+ * @errp: pointer to a NULL initialized error object
+ *
+ * Check if a user @identity is authorized. If an error
+ * occurs this method will return false to indicate
+ * denial, as well as setting @errp to contain the details.
+ * Callers are recommended to treat the denial and error
+ * scenarios identically. Specifically the error info in
+ * @errp should never be fed back to the user being
+ * authorized, it is merely for benefit of administrator
+ * debugging.
+ *
+ * Returns: true if @identity is authorized, false if denied or if
+ * an error occurred.
+ */
+bool qauthz_is_allowed_by_id(const char *authzid,
+ const char *identity,
+ Error **errp);
+
+#endif /* QAUTHZ_BASE_H__ */
+
diff --git a/include/authz/list.h b/include/authz/list.h
new file mode 100644
index 0000000..a7225a7
--- /dev/null
+++ b/include/authz/list.h
@@ -0,0 +1,106 @@
+/*
+ * QEMU list authorization driver
+ *
+ * Copyright (c) 2018 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * 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/>.
+ *
+ */
+
+#ifndef QAUTHZ_LIST_H__
+#define QAUTHZ_LIST_H__
+
+#include "authz/base.h"
+#include "qapi/qapi-types-authz.h"
+
+#define TYPE_QAUTHZ_LIST "authz-list"
+
+#define QAUTHZ_LIST_CLASS(klass) \
+ OBJECT_CLASS_CHECK(QAuthZListClass, (klass), \
+ TYPE_QAUTHZ_LIST)
+#define QAUTHZ_LIST_GET_CLASS(obj) \
+ OBJECT_GET_CLASS(QAuthZListClass, (obj), \
+ TYPE_QAUTHZ_LIST)
+#define QAUTHZ_LIST(obj) \
+ INTERFACE_CHECK(QAuthZList, (obj), \
+ TYPE_QAUTHZ_LIST)
+
+typedef struct QAuthZList QAuthZList;
+typedef struct QAuthZListClass QAuthZListClass;
+
+
+/**
+ * QAuthZList:
+ *
+ * This authorization driver provides a list mechanism
+ * for granting access by matching user names against a
+ * list of globs. Each match rule has an associated policy
+ * and a catch all policy applies if no rule matches
+ *
+ * To create an instance of this class via QMP:
+ *
+ * {
+ * "execute": "object-add",
+ * "arguments": {
+ * "qom-type": "authz-list",
+ * "id": "authz0",
+ * "props": {
+ * "rules": [
+ * { "match": "fred", "policy": "allow", "format": "exact" },
+ * { "match": "bob", "policy": "allow", "format": "exact" },
+ * { "match": "danb", "policy": "deny", "format": "exact" },
+ * { "match": "dan*", "policy": "allow", "format": "glob" }
+ * ],
+ * "policy": "deny"
+ * }
+ * }
+ * }
+ *
+ */
+struct QAuthZList {
+ QAuthZ parent_obj;
+
+ QAuthZListPolicy policy;
+ QAuthZListRuleList *rules;
+};
+
+
+struct QAuthZListClass {
+ QAuthZClass parent_class;
+};
+
+
+QAuthZList *qauthz_list_new(const char *id,
+ QAuthZListPolicy policy,
+ Error **errp);
+
+ssize_t qauthz_list_append_rule(QAuthZList *auth,
+ const char *match,
+ QAuthZListPolicy policy,
+ QAuthZListFormat format,
+ Error **errp);
+
+ssize_t qauthz_list_insert_rule(QAuthZList *auth,
+ const char *match,
+ QAuthZListPolicy policy,
+ QAuthZListFormat format,
+ size_t index,
+ Error **errp);
+
+ssize_t qauthz_list_delete_rule(QAuthZList *auth,
+ const char *match);
+
+
+#endif /* QAUTHZ_LIST_H__ */
+
diff --git a/include/authz/listfile.h b/include/authz/listfile.h
new file mode 100644
index 0000000..bcc8d80
--- /dev/null
+++ b/include/authz/listfile.h
@@ -0,0 +1,111 @@
+/*
+ * QEMU list file authorization driver
+ *
+ * Copyright (c) 2018 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * 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/>.
+ *
+ */
+
+#ifndef QAUTHZ_LIST_FILE_H__
+#define QAUTHZ_LIST_FILE_H__
+
+#include "authz/list.h"
+#include "qapi/qapi-types-authz.h"
+#include "qemu/filemonitor.h"
+
+#define TYPE_QAUTHZ_LIST_FILE "authz-list-file"
+
+#define QAUTHZ_LIST_FILE_CLASS(klass) \
+ OBJECT_CLASS_CHECK(QAuthZListFileClass, (klass), \
+ TYPE_QAUTHZ_LIST_FILE)
+#define QAUTHZ_LIST_FILE_GET_CLASS(obj) \
+ OBJECT_GET_CLASS(QAuthZListFileClass, (obj), \
+ TYPE_QAUTHZ_LIST_FILE)
+#define QAUTHZ_LIST_FILE(obj) \
+ INTERFACE_CHECK(QAuthZListFile, (obj), \
+ TYPE_QAUTHZ_LIST_FILE)
+
+typedef struct QAuthZListFile QAuthZListFile;
+typedef struct QAuthZListFileClass QAuthZListFileClass;
+
+
+/**
+ * QAuthZListFile:
+ *
+ * This authorization driver provides a file mechanism
+ * for granting access by matching user names against a
+ * file of globs. Each match rule has an associated policy
+ * and a catch all policy applies if no rule matches
+ *
+ * To create an instance of this class via QMP:
+ *
+ * {
+ * "execute": "object-add",
+ * "arguments": {
+ * "qom-type": "authz-list-file",
+ * "id": "authz0",
+ * "props": {
+ * "filename": "/etc/qemu/myvm-vnc.acl",
+ * "refresh": true
+ * }
+ * }
+ * }
+ *
+ * If 'refresh' is 'yes', inotify is used to monitor for changes
+ * to the file and auto-reload the rules.
+ *
+ * The myvm-vnc.acl file should contain the parameters for
+ * the QAuthZList object in JSON format:
+ *
+ * {
+ * "rules": [
+ * { "match": "fred", "policy": "allow", "format": "exact" },
+ * { "match": "bob", "policy": "allow", "format": "exact" },
+ * { "match": "danb", "policy": "deny", "format": "exact" },
+ * { "match": "dan*", "policy": "allow", "format": "glob" }
+ * ],
+ * "policy": "deny"
+ * }
+ *
+ * The object can be created on the command line using
+ *
+ * -object authz-list-file,id=authz0,\
+ * filename=/etc/qemu/myvm-vnc.acl,refresh=yes
+ *
+ */
+struct QAuthZListFile {
+ QAuthZ parent_obj;
+
+ QAuthZ *list;
+ char *filename;
+ bool refresh;
+ QFileMonitor *file_monitor;
+ int file_watch;
+};
+
+
+struct QAuthZListFileClass {
+ QAuthZClass parent_class;
+};
+
+
+QAuthZListFile *qauthz_list_file_new(const char *id,
+ const char *filename,
+ bool refresh,
+ Error **errp);
+
+
+#endif /* QAUTHZ_LIST_FILE_H__ */
+
diff --git a/include/authz/pamacct.h b/include/authz/pamacct.h
new file mode 100644
index 0000000..6e3046e
--- /dev/null
+++ b/include/authz/pamacct.h
@@ -0,0 +1,100 @@
+/*
+ * QEMU PAM authorization driver
+ *
+ * Copyright (c) 2018 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * 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/>.
+ *
+ */
+
+#ifndef QAUTHZ_PAM_H__
+#define QAUTHZ_PAM_H__
+
+#include "authz/base.h"
+
+
+#define TYPE_QAUTHZ_PAM "authz-pam"
+
+#define QAUTHZ_PAM_CLASS(klass) \
+ OBJECT_CLASS_CHECK(QAuthZPAMClass, (klass), \
+ TYPE_QAUTHZ_PAM)
+#define QAUTHZ_PAM_GET_CLASS(obj) \
+ OBJECT_GET_CLASS(QAuthZPAMClass, (obj), \
+ TYPE_QAUTHZ_PAM)
+#define QAUTHZ_PAM(obj) \
+ INTERFACE_CHECK(QAuthZPAM, (obj), \
+ TYPE_QAUTHZ_PAM)
+
+typedef struct QAuthZPAM QAuthZPAM;
+typedef struct QAuthZPAMClass QAuthZPAMClass;
+
+
+/**
+ * QAuthZPAM:
+ *
+ * This authorization driver provides a PAM mechanism
+ * for granting access by matching user names against a
+ * list of globs. Each match rule has an associated policy
+ * and a catch all policy applies if no rule matches
+ *
+ * To create an instance of this class via QMP:
+ *
+ * {
+ * "execute": "object-add",
+ * "arguments": {
+ * "qom-type": "authz-pam",
+ * "id": "authz0",
+ * "parameters": {
+ * "service": "qemu-vnc-tls"
+ * }
+ * }
+ * }
+ *
+ * The driver only uses the PAM "account" verification
+ * subsystem. The above config would require a config
+ * file /etc/pam.d/qemu-vnc-tls. For a simple file
+ * lookup it would contain
+ *
+ * account requisite pam_listfile.so item=user sense=allow \
+ * file=/etc/qemu/vnc.allow
+ *
+ * The external file would then contain a list of usernames.
+ * If x509 cert was being used as the username, a suitable
+ * entry would match the distinguish name:
+ *
+ * CN=laptop.berrange.com,O=Berrange Home,L=London,ST=London,C=GB
+ *
+ * On the command line it can be created using
+ *
+ * -object authz-pam,id=authz0,service=qemu-vnc-tls
+ *
+ */
+struct QAuthZPAM {
+ QAuthZ parent_obj;
+
+ char *service;
+};
+
+
+struct QAuthZPAMClass {
+ QAuthZClass parent_class;
+};
+
+
+QAuthZPAM *qauthz_pam_new(const char *id,
+ const char *service,
+ Error **errp);
+
+
+#endif /* QAUTHZ_PAM_H__ */
diff --git a/include/authz/simple.h b/include/authz/simple.h
new file mode 100644
index 0000000..ef13958
--- /dev/null
+++ b/include/authz/simple.h
@@ -0,0 +1,84 @@
+/*
+ * QEMU simple authorization driver
+ *
+ * Copyright (c) 2018 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * 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/>.
+ *
+ */
+
+#ifndef QAUTHZ_SIMPLE_H__
+#define QAUTHZ_SIMPLE_H__
+
+#include "authz/base.h"
+
+#define TYPE_QAUTHZ_SIMPLE "authz-simple"
+
+#define QAUTHZ_SIMPLE_CLASS(klass) \
+ OBJECT_CLASS_CHECK(QAuthZSimpleClass, (klass), \
+ TYPE_QAUTHZ_SIMPLE)
+#define QAUTHZ_SIMPLE_GET_CLASS(obj) \
+ OBJECT_GET_CLASS(QAuthZSimpleClass, (obj), \
+ TYPE_QAUTHZ_SIMPLE)
+#define QAUTHZ_SIMPLE(obj) \
+ INTERFACE_CHECK(QAuthZSimple, (obj), \
+ TYPE_QAUTHZ_SIMPLE)
+
+typedef struct QAuthZSimple QAuthZSimple;
+typedef struct QAuthZSimpleClass QAuthZSimpleClass;
+
+
+/**
+ * QAuthZSimple:
+ *
+ * This authorization driver provides a simple mechanism
+ * for granting access based on an exact matched username.
+ *
+ * To create an instance of this class via QMP:
+ *
+ * {
+ * "execute": "object-add",
+ * "arguments": {
+ * "qom-type": "authz-simple",
+ * "id": "authz0",
+ * "props": {
+ * "identity": "fred"
+ * }
+ * }
+ * }
+ *
+ * Or via the command line
+ *
+ * -object authz-simple,id=authz0,identity=fred
+ *
+ */
+struct QAuthZSimple {
+ QAuthZ parent_obj;
+
+ char *identity;
+};
+
+
+struct QAuthZSimpleClass {
+ QAuthZClass parent_class;
+};
+
+
+QAuthZSimple *qauthz_simple_new(const char *id,
+ const char *identity,
+ Error **errp);
+
+
+#endif /* QAUTHZ_SIMPLE_H__ */
+
diff --git a/include/block/block.h b/include/block/block.h
index 73357c6..5b5cf86 100644
--- a/include/block/block.h
+++ b/include/block/block.h
@@ -485,21 +485,17 @@
int64_t *cluster_offset,
int64_t *cluster_bytes);
-const char *bdrv_get_encrypted_filename(BlockDriverState *bs);
void bdrv_get_backing_filename(BlockDriverState *bs,
char *filename, int filename_size);
-void bdrv_get_full_backing_filename(BlockDriverState *bs,
- char *dest, size_t sz, Error **errp);
-void bdrv_get_full_backing_filename_from_filename(const char *backed,
- const char *backing,
- char *dest, size_t sz,
- Error **errp);
+char *bdrv_get_full_backing_filename(BlockDriverState *bs, Error **errp);
+char *bdrv_get_full_backing_filename_from_filename(const char *backed,
+ const char *backing,
+ Error **errp);
+char *bdrv_dirname(BlockDriverState *bs, Error **errp);
int path_has_protocol(const char *path);
int path_is_absolute(const char *path);
-void path_combine(char *dest, int dest_size,
- const char *base_path,
- const char *filename);
+char *path_combine(const char *base_path, const char *filename);
int bdrv_readv_vmstate(BlockDriverState *bs, QEMUIOVector *qiov, int64_t pos);
int bdrv_writev_vmstate(BlockDriverState *bs, QEMUIOVector *qiov, int64_t pos);
diff --git a/include/block/block_int.h b/include/block/block_int.h
index 0075baf..836d67c 100644
--- a/include/block/block_int.h
+++ b/include/block/block_int.h
@@ -139,7 +139,42 @@
Error **errp);
int (*bdrv_make_empty)(BlockDriverState *bs);
- void (*bdrv_refresh_filename)(BlockDriverState *bs, QDict *options);
+ /*
+ * Refreshes the bs->exact_filename field. If that is impossible,
+ * bs->exact_filename has to be left empty.
+ */
+ void (*bdrv_refresh_filename)(BlockDriverState *bs);
+
+ /*
+ * Gathers the open options for all children into @target.
+ * A simple format driver (without backing file support) might
+ * implement this function like this:
+ *
+ * QINCREF(bs->file->bs->full_open_options);
+ * qdict_put(target, "file", bs->file->bs->full_open_options);
+ *
+ * If not specified, the generic implementation will simply put
+ * all children's options under their respective name.
+ *
+ * @backing_overridden is true when bs->backing seems not to be
+ * the child that would result from opening bs->backing_file.
+ * Therefore, if it is true, the backing child's options should be
+ * gathered; otherwise, there is no need since the backing child
+ * is the one implied by the image header.
+ *
+ * Note that ideally this function would not be needed. Every
+ * block driver which implements it is probably doing something
+ * shady regarding its runtime option structure.
+ */
+ void (*bdrv_gather_child_options)(BlockDriverState *bs, QDict *target,
+ bool backing_overridden);
+
+ /*
+ * Returns an allocated string which is the directory name of this BDS: It
+ * will be used to make relative filenames absolute by prepending this
+ * function's return value to them.
+ */
+ char *(*bdrv_dirname)(BlockDriverState *bs, Error **errp);
/* aio */
BlockAIOCB *(*bdrv_aio_preadv)(BlockDriverState *bs,
@@ -510,6 +545,13 @@
void (*bdrv_register_buf)(BlockDriverState *bs, void *host, size_t size);
void (*bdrv_unregister_buf)(BlockDriverState *bs, void *host);
QLIST_ENTRY(BlockDriver) list;
+
+ /* Pointer to a NULL-terminated array of names of strong options
+ * that can be specified for bdrv_open(). A strong option is one
+ * that changes the data of a BDS.
+ * If this pointer is NULL, the array is considered empty.
+ * "filename" and "driver" are always considered strong. */
+ const char *const *strong_runtime_opts;
};
typedef struct BlockLimits {
@@ -662,6 +704,11 @@
*/
uint64_t shared_perm;
+ /* backup of permissions during permission update procedure */
+ bool has_backup_perm;
+ uint64_t backup_perm;
+ uint64_t backup_shared_perm;
+
QLIST_ENTRY(BdrvChild) next;
QLIST_ENTRY(BdrvChild) next_parent;
};
@@ -697,6 +744,10 @@
char filename[PATH_MAX];
char backing_file[PATH_MAX]; /* if non zero, the image is a diff of
this file image */
+ /* The backing filename indicated by the image header; if we ever
+ * open this file, then this is replaced by the resulting BDS's
+ * filename (i.e. after a bdrv_refresh_filename() run). */
+ char auto_backing_file[PATH_MAX];
char backing_format[16]; /* if non-zero and backing_file exists */
QDict *full_open_options;
diff --git a/include/block/nbd.h b/include/block/nbd.h
index 96cfb1d..c6ef1ef 100644
--- a/include/block/nbd.h
+++ b/include/block/nbd.h
@@ -300,7 +300,8 @@
int nbd_init(int fd, QIOChannelSocket *sioc, NBDExportInfo *info,
Error **errp);
int nbd_send_request(QIOChannel *ioc, NBDRequest *request);
-int nbd_receive_reply(QIOChannel *ioc, NBDReply *reply, Error **errp);
+int coroutine_fn nbd_receive_reply(BlockDriverState *bs, QIOChannel *ioc,
+ NBDReply *reply, Error **errp);
int nbd_client(int fd);
int nbd_disconnect(int fd);
int nbd_errno_to_system_errno(int err);
diff --git a/include/block/snapshot.h b/include/block/snapshot.h
index f73d109..b5d5084 100644
--- a/include/block/snapshot.h
+++ b/include/block/snapshot.h
@@ -61,9 +61,6 @@
const char *snapshot_id,
const char *name,
Error **errp);
-int bdrv_snapshot_delete_by_id_or_name(BlockDriverState *bs,
- const char *id_or_name,
- Error **errp);
int bdrv_snapshot_list(BlockDriverState *bs,
QEMUSnapshotInfo **psn_info);
int bdrv_snapshot_load_tmp(BlockDriverState *bs,
diff --git a/include/chardev/spice.h b/include/chardev/spice.h
new file mode 100644
index 0000000..6431da3
--- /dev/null
+++ b/include/chardev/spice.h
@@ -0,0 +1,27 @@
+#ifndef CHARDEV_SPICE_H_
+#define CHARDEV_SPICE_H_
+
+#include <spice.h>
+#include "chardev/char-fe.h"
+
+typedef struct SpiceChardev {
+ Chardev parent;
+
+ SpiceCharDeviceInstance sin;
+ bool active;
+ bool blocked;
+ const uint8_t *datapos;
+ int datalen;
+ QLIST_ENTRY(SpiceChardev) next;
+} SpiceChardev;
+
+#define TYPE_CHARDEV_SPICE "chardev-spice"
+#define TYPE_CHARDEV_SPICEVMC "chardev-spicevmc"
+#define TYPE_CHARDEV_SPICEPORT "chardev-spiceport"
+
+#define SPICE_CHARDEV(obj) OBJECT_CHECK(SpiceChardev, (obj), TYPE_CHARDEV_SPICE)
+
+void qemu_chr_open_spice_port(Chardev *chr, ChardevBackend *backend,
+ bool *be_opened, Error **errp);
+
+#endif
diff --git a/include/exec/cpu-common.h b/include/exec/cpu-common.h
index 63ec1f9..cef8b88 100644
--- a/include/exec/cpu-common.h
+++ b/include/exec/cpu-common.h
@@ -72,6 +72,9 @@
void qemu_ram_set_idstr(RAMBlock *block, const char *name, DeviceState *dev);
void qemu_ram_unset_idstr(RAMBlock *block);
const char *qemu_ram_get_idstr(RAMBlock *rb);
+void *qemu_ram_get_host_addr(RAMBlock *rb);
+ram_addr_t qemu_ram_get_offset(RAMBlock *rb);
+ram_addr_t qemu_ram_get_used_length(RAMBlock *rb);
bool qemu_ram_is_shared(RAMBlock *rb);
bool qemu_ram_is_uf_zeroable(RAMBlock *rb);
void qemu_ram_set_uf_zeroable(RAMBlock *rb);
@@ -116,11 +119,9 @@
extern struct MemoryRegion io_mem_rom;
extern struct MemoryRegion io_mem_notdirty;
-typedef int (RAMBlockIterFunc)(const char *block_name, void *host_addr,
- ram_addr_t offset, ram_addr_t length, void *opaque);
+typedef int (RAMBlockIterFunc)(RAMBlock *rb, void *opaque);
int qemu_ram_foreach_block(RAMBlockIterFunc func, void *opaque);
-int qemu_ram_foreach_migratable_block(RAMBlockIterFunc func, void *opaque);
int ram_block_discard_range(RAMBlock *rb, uint64_t start, size_t length);
#endif
diff --git a/include/exec/poison.h b/include/exec/poison.h
index ecdc83c..1a7a57b 100644
--- a/include/exec/poison.h
+++ b/include/exec/poison.h
@@ -86,7 +86,6 @@
#pragma GCC poison CONFIG_XTENSA_DIS
#pragma GCC poison CONFIG_LINUX_USER
-#pragma GCC poison CONFIG_VHOST_NET
#pragma GCC poison CONFIG_KVM
#pragma GCC poison CONFIG_SOFTMMU
diff --git a/include/fpu/softfloat.h b/include/fpu/softfloat.h
index 38a5e99..3ff3fa5 100644
--- a/include/fpu/softfloat.h
+++ b/include/fpu/softfloat.h
@@ -466,7 +466,7 @@
static inline bool float32_is_normal(float32 a)
{
- return ((float32_val(a) + 0x00800000) & 0x7fffffff) >= 0x01000000;
+ return (((float32_val(a) >> 23) + 1) & 0xff) >= 2;
}
static inline bool float32_is_denormal(float32 a)
@@ -622,7 +622,7 @@
static inline bool float64_is_normal(float64 a)
{
- return ((float64_val(a) + (1ULL << 52)) & -1ULL >> 1) >= 1ULL << 53;
+ return (((float64_val(a) >> 52) + 1) & 0x7ff) >= 2;
}
static inline bool float64_is_denormal(float64 a)
@@ -878,6 +878,7 @@
int64_t float128_to_int64_round_to_zero(float128, float_status *status);
uint64_t float128_to_uint64(float128, float_status *status);
uint64_t float128_to_uint64_round_to_zero(float128, float_status *status);
+uint32_t float128_to_uint32(float128, float_status *status);
uint32_t float128_to_uint32_round_to_zero(float128, float_status *status);
float32 float128_to_float32(float128, float_status *status);
float64 float128_to_float64(float128, float_status *status);
@@ -940,6 +941,16 @@
return (a.high & 0x7fff000000000000LL) == 0;
}
+static inline bool float128_is_normal(float128 a)
+{
+ return (((a.high >> 48) + 1) & 0x7fff) >= 2;
+}
+
+static inline bool float128_is_denormal(float128 a)
+{
+ return float128_is_zero_or_denormal(a) && !float128_is_zero(a);
+}
+
static inline int float128_is_any_nan(float128 a)
{
return ((a.high >> 48) & 0x7fff) == 0x7fff &&
diff --git a/include/hw/acpi/acpi.h b/include/hw/acpi/acpi.h
index bbf5412..c91e2b9 100644
--- a/include/hw/acpi/acpi.h
+++ b/include/hw/acpi/acpi.h
@@ -190,7 +190,6 @@
uint8_t *acpi_table_next(uint8_t *current);
unsigned acpi_table_len(void *current);
void acpi_table_add(const QemuOpts *opts, Error **errp);
-void acpi_table_add_builtin(const QemuOpts *opts, Error **errp);
typedef struct AcpiSlicOem AcpiSlicOem;
struct AcpiSlicOem {
diff --git a/include/hw/arm/armsse.h b/include/hw/arm/armsse.h
index 7ef871c..81e082c 100644
--- a/include/hw/arm/armsse.h
+++ b/include/hw/arm/armsse.h
@@ -95,6 +95,7 @@
#include "hw/misc/iotkit-sysctl.h"
#include "hw/misc/iotkit-sysinfo.h"
#include "hw/misc/armsse-cpuid.h"
+#include "hw/misc/armsse-mhu.h"
#include "hw/misc/unimp.h"
#include "hw/or-irq.h"
#include "hw/core/split-irq.h"
@@ -166,7 +167,7 @@
IoTKitSysCtl sysctl;
IoTKitSysCtl sysinfo;
- UnimplementedDeviceState mhu[2];
+ ARMSSEMHU mhu[2];
UnimplementedDeviceState ppu[NUM_PPUS];
UnimplementedDeviceState cachectrl[SSE_MAX_CPUS];
UnimplementedDeviceState cpusecctrl[SSE_MAX_CPUS];
diff --git a/include/hw/arm/virt.h b/include/hw/arm/virt.h
index 4cc57a7..507517c 100644
--- a/include/hw/arm/virt.h
+++ b/include/hw/arm/virt.h
@@ -64,7 +64,6 @@
VIRT_GIC_VCPU,
VIRT_GIC_ITS,
VIRT_GIC_REDIST,
- VIRT_GIC_REDIST2,
VIRT_SMMU,
VIRT_UART,
VIRT_MMIO,
@@ -74,12 +73,18 @@
VIRT_PCIE_MMIO,
VIRT_PCIE_PIO,
VIRT_PCIE_ECAM,
- VIRT_PCIE_ECAM_HIGH,
VIRT_PLATFORM_BUS,
- VIRT_PCIE_MMIO_HIGH,
VIRT_GPIO,
VIRT_SECURE_UART,
VIRT_SECURE_MEM,
+ VIRT_LOWMEMMAP_LAST,
+};
+
+/* indices of IO regions located after the RAM */
+enum {
+ VIRT_HIGH_GIC_REDIST2 = VIRT_LOWMEMMAP_LAST,
+ VIRT_HIGH_PCIE_ECAM,
+ VIRT_HIGH_PCIE_MMIO,
};
typedef enum VirtIOMMUType {
@@ -116,7 +121,7 @@
int32_t gic_version;
VirtIOMMUType iommu;
struct arm_boot_info bootinfo;
- const MemMapEntry *memmap;
+ MemMapEntry *memmap;
const int *irqmap;
int smp_cpus;
void *fdt;
@@ -126,9 +131,10 @@
uint32_t msi_phandle;
uint32_t iommu_phandle;
int psci_conduit;
+ hwaddr highest_gpa;
} VirtMachineState;
-#define VIRT_ECAM_ID(high) (high ? VIRT_PCIE_ECAM_HIGH : VIRT_PCIE_ECAM)
+#define VIRT_ECAM_ID(high) (high ? VIRT_HIGH_PCIE_ECAM : VIRT_PCIE_ECAM)
#define TYPE_VIRT_MACHINE MACHINE_TYPE_NAME("virt")
#define VIRT_MACHINE(obj) \
diff --git a/include/hw/boards.h b/include/hw/boards.h
index 05f9f45..9690c71 100644
--- a/include/hw/boards.h
+++ b/include/hw/boards.h
@@ -156,6 +156,9 @@
* should instead use "unimplemented-device" for all memory ranges where
* the guest will attempt to probe for a device that QEMU doesn't
* implement and a stub device is required.
+ * @kvm_type:
+ * Return the type of KVM corresponding to the kvm-type string option or
+ * computed based on other criteria such as the host kernel capabilities.
*/
struct MachineClass {
/*< private >*/
@@ -171,7 +174,7 @@
void (*init)(MachineState *state);
void (*reset)(void);
void (*hot_add_cpu)(const int64_t id, Error **errp);
- int (*kvm_type)(const char *arg);
+ int (*kvm_type)(MachineState *machine, const char *arg);
BlockInterfaceType block_default_type;
int units_per_default_bus;
@@ -206,6 +209,7 @@
void (*numa_auto_assign_ram)(MachineClass *mc, NodeInfo *nodes,
int nb_nodes, ram_addr_t size);
bool ignore_boot_device_suffixes;
+ bool smbus_no_migration_support;
HotplugHandler *(*get_hotplug_handler)(MachineState *machine,
DeviceState *dev);
diff --git a/include/hw/firmware/smbios.h b/include/hw/firmware/smbios.h
index eeb5a4d..6fef32a 100644
--- a/include/hw/firmware/smbios.h
+++ b/include/hw/firmware/smbios.h
@@ -162,6 +162,7 @@
uint8_t height;
uint8_t number_of_power_cords;
uint8_t contained_element_count;
+ uint8_t contained_element_record_length;
uint8_t sku_number_str;
/* contained elements follow */
} QEMU_PACKED;
diff --git a/include/hw/i2c/i2c.h b/include/hw/i2c/i2c.h
index cf4c45a..8e236f7 100644
--- a/include/hw/i2c/i2c.h
+++ b/include/hw/i2c/i2c.h
@@ -33,10 +33,9 @@
/*
* Slave to master. This cannot fail, the device should always
- * return something here. Negative values probably result in 0xff
- * and a possible log from the driver, and shouldn't be used.
+ * return something here.
*/
- int (*recv)(I2CSlave *s);
+ uint8_t (*recv)(I2CSlave *s);
/*
* Notify the slave of a bus state change. For start event,
@@ -78,7 +77,7 @@
void i2c_nack(I2CBus *bus);
int i2c_send_recv(I2CBus *bus, uint8_t *data, bool send);
int i2c_send(I2CBus *bus, uint8_t data);
-int i2c_recv(I2CBus *bus);
+uint8_t i2c_recv(I2CBus *bus);
DeviceState *i2c_create_slave(I2CBus *bus, const char *name, uint8_t addr);
diff --git a/include/hw/i2c/pm_smbus.h b/include/hw/i2c/pm_smbus.h
index 060d3c6..fb55c44 100644
--- a/include/hw/i2c/pm_smbus.h
+++ b/include/hw/i2c/pm_smbus.h
@@ -1,6 +1,8 @@
#ifndef PM_SMBUS_H
#define PM_SMBUS_H
+#include "hw/i2c/smbus_master.h"
+
#define PM_SMBUS_MAX_MSG_SIZE 32
typedef struct PMSMBus {
@@ -31,8 +33,23 @@
/* Set on block transfers after the last byte has been read, so the
INTR bit can be set at the right time. */
bool op_done;
+
+ /* Set during an I2C block read, so we know how to handle data. */
+ bool in_i2c_block_read;
+
+ /* Used to work around a bug in AMIBIOS, see smb_transaction_start() */
+ bool start_transaction_on_status_read;
} PMSMBus;
void pm_smbus_init(DeviceState *parent, PMSMBus *smb, bool force_aux_blk);
+/*
+ * For backwards compatibility on migration, older versions don't have
+ * working migration for pm_smbus, this lets us ignore the migrations
+ * for older machine versions.
+ */
+bool pm_smbus_vmstate_needed(void);
+
+extern const VMStateDescription pmsmb_vmstate;
+
#endif /* PM_SMBUS_H */
diff --git a/include/hw/i2c/smbus.h b/include/hw/i2c/smbus.h
deleted file mode 100644
index 89dfea1..0000000
--- a/include/hw/i2c/smbus.h
+++ /dev/null
@@ -1,101 +0,0 @@
-#ifndef QEMU_SMBUS_H
-#define QEMU_SMBUS_H
-
-/*
- * QEMU SMBus API
- *
- * Copyright (c) 2007 Arastra, Inc.
- *
- * 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 "hw/i2c/i2c.h"
-
-#define TYPE_SMBUS_DEVICE "smbus-device"
-#define SMBUS_DEVICE(obj) \
- OBJECT_CHECK(SMBusDevice, (obj), TYPE_SMBUS_DEVICE)
-#define SMBUS_DEVICE_CLASS(klass) \
- OBJECT_CLASS_CHECK(SMBusDeviceClass, (klass), TYPE_SMBUS_DEVICE)
-#define SMBUS_DEVICE_GET_CLASS(obj) \
- OBJECT_GET_CLASS(SMBusDeviceClass, (obj), TYPE_SMBUS_DEVICE)
-
-typedef struct SMBusDevice SMBusDevice;
-
-typedef struct SMBusDeviceClass
-{
- I2CSlaveClass parent_class;
- void (*quick_cmd)(SMBusDevice *dev, uint8_t read);
- void (*send_byte)(SMBusDevice *dev, uint8_t val);
- uint8_t (*receive_byte)(SMBusDevice *dev);
- /* We can't distinguish between a word write and a block write with
- length 1, so pass the whole data block including the length byte
- (if present). The device is responsible figuring out what type of
- command this is. */
- void (*write_data)(SMBusDevice *dev, uint8_t cmd, uint8_t *buf, int len);
- /* Likewise we can't distinguish between different reads, or even know
- the length of the read until the read is complete, so read data a
- byte at a time. The device is responsible for adding the length
- byte on block reads. */
- uint8_t (*read_data)(SMBusDevice *dev, uint8_t cmd, int n);
-} SMBusDeviceClass;
-
-struct SMBusDevice {
- /* The SMBus protocol is implemented on top of I2C. */
- I2CSlave i2c;
-
- /* Remaining fields for internal use only. */
- int mode;
- int data_len;
- uint8_t data_buf[34]; /* command + len + 32 bytes of data. */
- uint8_t command;
-};
-
-/* Master device commands. */
-int smbus_quick_command(I2CBus *bus, uint8_t addr, int read);
-int smbus_receive_byte(I2CBus *bus, uint8_t addr);
-int smbus_send_byte(I2CBus *bus, uint8_t addr, uint8_t data);
-int smbus_read_byte(I2CBus *bus, uint8_t addr, uint8_t command);
-int smbus_write_byte(I2CBus *bus, uint8_t addr, uint8_t command, uint8_t data);
-int smbus_read_word(I2CBus *bus, uint8_t addr, uint8_t command);
-int smbus_write_word(I2CBus *bus, uint8_t addr, uint8_t command, uint16_t data);
-
-/*
- * Do a block transfer from an I2C device. If recv_len is set, then the
- * first received byte is a length field and is used to know how much data
- * to receive. Otherwise receive "len" bytes. If send_cmd is set, send
- * the command byte first before receiving the data.
- */
-int smbus_read_block(I2CBus *bus, uint8_t addr, uint8_t command, uint8_t *data,
- int len, bool recv_len, bool send_cmd);
-
-/*
- * Do a block transfer to an I2C device. If send_len is set, send the
- * "len" value before the data.
- */
-int smbus_write_block(I2CBus *bus, uint8_t addr, uint8_t command, uint8_t *data,
- int len, bool send_len);
-
-void smbus_eeprom_init_one(I2CBus *smbus, uint8_t address, uint8_t *eeprom_buf);
-void smbus_eeprom_init(I2CBus *smbus, int nb_eeprom,
- const uint8_t *eeprom_spd, int size);
-
-enum sdram_type { SDR = 0x4, DDR = 0x7, DDR2 = 0x8 };
-uint8_t *spd_data_generate(enum sdram_type type, ram_addr_t size, Error **errp);
-
-#endif
diff --git a/include/hw/i2c/smbus_eeprom.h b/include/hw/i2c/smbus_eeprom.h
new file mode 100644
index 0000000..0f96836
--- /dev/null
+++ b/include/hw/i2c/smbus_eeprom.h
@@ -0,0 +1,35 @@
+/*
+ * QEMU SMBus EEPROM API
+ *
+ * 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.
+ */
+
+#ifndef HW_SMBUS_EEPROM_H
+#define HW_SMBUS_EEPROM_H
+
+#include "hw/i2c/i2c.h"
+
+void smbus_eeprom_init_one(I2CBus *bus, uint8_t address, uint8_t *eeprom_buf);
+void smbus_eeprom_init(I2CBus *bus, int nb_eeprom,
+ const uint8_t *eeprom_spd, int size);
+
+enum sdram_type { SDR = 0x4, DDR = 0x7, DDR2 = 0x8 };
+uint8_t *spd_data_generate(enum sdram_type type, ram_addr_t size, Error **errp);
+
+#endif
diff --git a/include/hw/i2c/smbus_master.h b/include/hw/i2c/smbus_master.h
new file mode 100644
index 0000000..bb13bc4
--- /dev/null
+++ b/include/hw/i2c/smbus_master.h
@@ -0,0 +1,55 @@
+/*
+ * QEMU SMBus host (master) API
+ *
+ * Copyright (c) 2007 Arastra, Inc.
+ *
+ * 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.
+ */
+
+#ifndef HW_SMBUS_MASTER_H
+#define HW_SMBUS_MASTER_H
+
+#include "hw/i2c/i2c.h"
+
+/* Master device commands. */
+int smbus_quick_command(I2CBus *bus, uint8_t addr, int read);
+int smbus_receive_byte(I2CBus *bus, uint8_t addr);
+int smbus_send_byte(I2CBus *bus, uint8_t addr, uint8_t data);
+int smbus_read_byte(I2CBus *bus, uint8_t addr, uint8_t command);
+int smbus_write_byte(I2CBus *bus, uint8_t addr, uint8_t command, uint8_t data);
+int smbus_read_word(I2CBus *bus, uint8_t addr, uint8_t command);
+int smbus_write_word(I2CBus *bus, uint8_t addr, uint8_t command, uint16_t data);
+
+/*
+ * Do a block transfer from an I2C device. If recv_len is set, then the
+ * first received byte is a length field and is used to know how much data
+ * to receive. Otherwise receive "len" bytes. If send_cmd is set, send
+ * the command byte first before receiving the data.
+ */
+int smbus_read_block(I2CBus *bus, uint8_t addr, uint8_t command, uint8_t *data,
+ int len, bool recv_len, bool send_cmd);
+
+/*
+ * Do a block transfer to an I2C device. If send_len is set, send the
+ * "len" value before the data.
+ */
+int smbus_write_block(I2CBus *bus, uint8_t addr, uint8_t command, uint8_t *data,
+ int len, bool send_len);
+
+#endif
diff --git a/include/hw/i2c/smbus_slave.h b/include/hw/i2c/smbus_slave.h
new file mode 100644
index 0000000..ebe0683
--- /dev/null
+++ b/include/hw/i2c/smbus_slave.h
@@ -0,0 +1,100 @@
+/*
+ * QEMU SMBus device (slave) API
+ *
+ * Copyright (c) 2007 Arastra, Inc.
+ *
+ * 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.
+ */
+
+#ifndef HW_SMBUS_SLAVE_H
+#define HW_SMBUS_SLAVE_H
+
+#include "hw/i2c/i2c.h"
+
+#define TYPE_SMBUS_DEVICE "smbus-device"
+#define SMBUS_DEVICE(obj) \
+ OBJECT_CHECK(SMBusDevice, (obj), TYPE_SMBUS_DEVICE)
+#define SMBUS_DEVICE_CLASS(klass) \
+ OBJECT_CLASS_CHECK(SMBusDeviceClass, (klass), TYPE_SMBUS_DEVICE)
+#define SMBUS_DEVICE_GET_CLASS(obj) \
+ OBJECT_GET_CLASS(SMBusDeviceClass, (obj), TYPE_SMBUS_DEVICE)
+
+typedef struct SMBusDevice SMBusDevice;
+
+typedef struct SMBusDeviceClass
+{
+ I2CSlaveClass parent_class;
+
+ /*
+ * An operation with no data, special in SMBus.
+ * This may be NULL, quick commands are ignore in that case.
+ */
+ void (*quick_cmd)(SMBusDevice *dev, uint8_t read);
+
+ /*
+ * We can't distinguish between a word write and a block write with
+ * length 1, so pass the whole data block including the length byte
+ * (if present). The device is responsible figuring out what type of
+ * command this is.
+ * This may be NULL if no data is written to the device. Writes
+ * will be ignore in that case.
+ */
+ int (*write_data)(SMBusDevice *dev, uint8_t *buf, uint8_t len);
+
+ /*
+ * Likewise we can't distinguish between different reads, or even know
+ * the length of the read until the read is complete, so read data a
+ * byte at a time. The device is responsible for adding the length
+ * byte on block reads. This call cannot fail, it should return
+ * something, preferably 0xff if nothing is available.
+ * This may be NULL if no data is read from the device. Reads will
+ * return 0xff in that case.
+ */
+ uint8_t (*receive_byte)(SMBusDevice *dev);
+} SMBusDeviceClass;
+
+#define SMBUS_DATA_MAX_LEN 34 /* command + len + 32 bytes of data. */
+
+struct SMBusDevice {
+ /* The SMBus protocol is implemented on top of I2C. */
+ I2CSlave i2c;
+
+ /* Remaining fields for internal use only. */
+ int32_t mode;
+ int32_t data_len;
+ uint8_t data_buf[SMBUS_DATA_MAX_LEN];
+};
+
+extern const VMStateDescription vmstate_smbus_device;
+
+#define VMSTATE_SMBUS_DEVICE(_field, _state) { \
+ .name = (stringify(_field)), \
+ .size = sizeof(SMBusDevice), \
+ .vmsd = &vmstate_smbus_device, \
+ .flags = VMS_STRUCT, \
+ .offset = vmstate_offset_value(_state, _field, SMBusDevice), \
+}
+
+/*
+ * Users should call this in their .needed functions to know if the
+ * SMBus slave data needs to be transferred.
+ */
+bool smbus_vmstate_needed(SMBusDevice *dev);
+
+#endif
diff --git a/include/hw/i386/pc.h b/include/hw/i386/pc.h
index 3ff127e..54222a2 100644
--- a/include/hw/i386/pc.h
+++ b/include/hw/i386/pc.h
@@ -189,7 +189,6 @@
void pc_cpus_init(PCMachineState *pcms);
void pc_hot_add_cpu(const int64_t id, Error **errp);
-void pc_acpi_init(const char *default_dsdt);
void pc_guest_info_init(PCMachineState *pcms);
diff --git a/include/hw/ide/internal.h b/include/hw/ide/internal.h
index 880413d..8efd031 100644
--- a/include/hw/ide/internal.h
+++ b/include/hw/ide/internal.h
@@ -346,7 +346,6 @@
typedef struct IDEBufferedRequest {
QLIST_ENTRY(IDEBufferedRequest) list;
- struct iovec iov;
QEMUIOVector qiov;
QEMUIOVector *original_qiov;
BlockCompletionFunc *original_cb;
@@ -405,7 +404,6 @@
int atapi_dma; /* true if dma is requested for the packet cmd */
BlockAcctCookie acct;
BlockAIOCB *pio_aiocb;
- struct iovec iov;
QEMUIOVector qiov;
QLIST_HEAD(, IDEBufferedRequest) buffered_requests;
/* ATA DMA state */
@@ -457,7 +455,6 @@
struct IDEDMA {
const struct IDEDMAOps *ops;
- struct iovec iov;
QEMUIOVector qiov;
BlockAIOCB *aiocb;
};
diff --git a/include/hw/misc/armsse-mhu.h b/include/hw/misc/armsse-mhu.h
new file mode 100644
index 0000000..e57eafc
--- /dev/null
+++ b/include/hw/misc/armsse-mhu.h
@@ -0,0 +1,44 @@
+/*
+ * ARM SSE-200 Message Handling Unit (MHU)
+ *
+ * Copyright (c) 2019 Linaro Limited
+ * Written by Peter Maydell
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 or
+ * (at your option) any later version.
+ */
+
+/*
+ * This is a model of the Message Handling Unit (MHU) which is part of the
+ * Arm SSE-200 and documented in
+ * http://infocenter.arm.com/help/topic/com.arm.doc.101104_0100_00_en/corelink_sse200_subsystem_for_embedded_technical_reference_manual_101104_0100_00_en.pdf
+ *
+ * QEMU interface:
+ * + sysbus MMIO region 0: the system information register bank
+ * + sysbus IRQ 0: interrupt for CPU 0
+ * + sysbus IRQ 1: interrupt for CPU 1
+ */
+
+#ifndef HW_MISC_SSE_MHU_H
+#define HW_MISC_SSE_MHU_H
+
+#include "hw/sysbus.h"
+
+#define TYPE_ARMSSE_MHU "armsse-mhu"
+#define ARMSSE_MHU(obj) OBJECT_CHECK(ARMSSEMHU, (obj), TYPE_ARMSSE_MHU)
+
+typedef struct ARMSSEMHU {
+ /*< private >*/
+ SysBusDevice parent_obj;
+
+ /*< public >*/
+ MemoryRegion iomem;
+ qemu_irq cpu0irq;
+ qemu_irq cpu1irq;
+
+ uint32_t cpu0intr;
+ uint32_t cpu1intr;
+} ARMSSEMHU;
+
+#endif
diff --git a/include/hw/misc/iotkit-sysctl.h b/include/hw/misc/iotkit-sysctl.h
index e36613c..601c8ec 100644
--- a/include/hw/misc/iotkit-sysctl.h
+++ b/include/hw/misc/iotkit-sysctl.h
@@ -17,6 +17,9 @@
* "system control register" blocks.
*
* QEMU interface:
+ * + QOM property "SYS_VERSION": value of the SYS_VERSION register of the
+ * system information block of the SSE
+ * (used to identify whether to provide SSE-200-only registers)
* + sysbus MMIO region 0: the system information register bank
* + sysbus MMIO region 1: the system control register bank
*/
@@ -41,9 +44,29 @@
uint32_t reset_syndrome;
uint32_t reset_mask;
uint32_t gretreg;
- uint32_t initsvrtor0;
+ uint32_t initsvtor0;
uint32_t cpuwait;
uint32_t wicctrl;
+ uint32_t scsecctrl;
+ uint32_t fclk_div;
+ uint32_t sysclk_div;
+ uint32_t clock_force;
+ uint32_t initsvtor1;
+ uint32_t nmi_enable;
+ uint32_t ewctrl;
+ uint32_t pdcm_pd_sys_sense;
+ uint32_t pdcm_pd_sram0_sense;
+ uint32_t pdcm_pd_sram1_sense;
+ uint32_t pdcm_pd_sram2_sense;
+ uint32_t pdcm_pd_sram3_sense;
+
+ /* Properties */
+ uint32_t sys_version;
+ uint32_t cpuwait_rst;
+ uint32_t initsvtor0_rst;
+ uint32_t initsvtor1_rst;
+
+ bool is_sse200;
} IoTKitSysCtl;
#endif
diff --git a/include/hw/pci-host/spapr.h b/include/hw/pci-host/spapr.h
index 51d81c4..ab0e3a0 100644
--- a/include/hw/pci-host/spapr.h
+++ b/include/hw/pci-host/spapr.h
@@ -113,7 +113,7 @@
}
int spapr_populate_pci_dt(sPAPRPHBState *phb, uint32_t intc_phandle, void *fdt,
- uint32_t nr_msis);
+ uint32_t nr_msis, int *node_offset);
void spapr_pci_rtas_init(void);
@@ -121,8 +121,10 @@
PCIDevice *spapr_pci_find_dev(sPAPRMachineState *spapr, uint64_t buid,
uint32_t config_addr);
-/* PCI release callback. */
+/* DRC callbacks */
void spapr_phb_remove_pci_device_cb(DeviceState *dev);
+int spapr_pci_dt_populate(sPAPRDRConnector *drc, sPAPRMachineState *spapr,
+ void *fdt, int *fdt_start_offset, Error **errp);
/* VFIO EEH hooks */
#ifdef CONFIG_LINUX
@@ -163,4 +165,9 @@
void spapr_phb_dma_reset(sPAPRPHBState *sphb);
+static inline unsigned spapr_phb_windows_supported(sPAPRPHBState *sphb)
+{
+ return sphb->ddw_enabled ? SPAPR_PCI_DMA_MAX_WINDOWS : 1;
+}
+
#endif /* PCI_HOST_SPAPR_H */
diff --git a/include/hw/pci/pci_ids.h b/include/hw/pci/pci_ids.h
index eeb3301..0abe27a 100644
--- a/include/hw/pci/pci_ids.h
+++ b/include/hw/pci/pci_ids.h
@@ -271,4 +271,6 @@
#define PCI_VENDOR_ID_SYNOPSYS 0x16C3
+#define PCI_VENDOR_ID_NVIDIA 0x10de
+
#endif
diff --git a/include/hw/ppc/ppc.h b/include/hw/ppc/ppc.h
index 298ec35..746170f 100644
--- a/include/hw/ppc/ppc.h
+++ b/include/hw/ppc/ppc.h
@@ -73,6 +73,7 @@
static inline void ppc6xx_irq_init(PowerPCCPU *cpu) {}
static inline void ppc970_irq_init(PowerPCCPU *cpu) {}
static inline void ppcPOWER7_irq_init(PowerPCCPU *cpu) {}
+static inline void ppcPOWER9_irq_init(PowerPCCPU *cpu) {}
static inline void ppce500_irq_init(PowerPCCPU *cpu) {}
#else
void ppc40x_irq_init(PowerPCCPU *cpu);
@@ -80,6 +81,7 @@
void ppc6xx_irq_init(PowerPCCPU *cpu);
void ppc970_irq_init(PowerPCCPU *cpu);
void ppcPOWER7_irq_init(PowerPCCPU *cpu);
+void ppcPOWER9_irq_init(PowerPCCPU *cpu);
#endif
/* PPC machines for OpenBIOS */
diff --git a/include/hw/ppc/spapr.h b/include/hw/ppc/spapr.h
index 631fc51..59073a7 100644
--- a/include/hw/ppc/spapr.h
+++ b/include/hw/ppc/spapr.h
@@ -104,6 +104,7 @@
/*< public >*/
bool dr_lmb_enabled; /* enable dynamic-reconfig/hotplug of LMBs */
+ bool dr_phb_enabled; /* enable dynamic-reconfig/hotplug of PHBs */
bool update_dt_enabled; /* enable KVMPPC_H_UPDATE_DT */
bool use_ohci_by_default; /* use USB-OHCI instead of XHCI */
bool pre_2_10_has_unused_icps;
@@ -177,6 +178,8 @@
/*< public >*/
char *kvm_type;
+ char *host_model;
+ char *host_serial;
int32_t irq_map_nr;
unsigned long *irq_map;
@@ -762,9 +765,16 @@
void spapr_clear_pending_events(sPAPRMachineState *spapr);
int spapr_max_server_number(sPAPRMachineState *spapr);
-/* CPU and LMB DRC release callbacks. */
+/* DRC callbacks. */
void spapr_core_release(DeviceState *dev);
+int spapr_core_dt_populate(sPAPRDRConnector *drc, sPAPRMachineState *spapr,
+ void *fdt, int *fdt_start_offset, Error **errp);
void spapr_lmb_release(DeviceState *dev);
+int spapr_lmb_dt_populate(sPAPRDRConnector *drc, sPAPRMachineState *spapr,
+ void *fdt, int *fdt_start_offset, Error **errp);
+void spapr_phb_release(DeviceState *dev);
+int spapr_phb_dt_populate(sPAPRDRConnector *drc, sPAPRMachineState *spapr,
+ void *fdt, int *fdt_start_offset, Error **errp);
void spapr_rtc_read(sPAPRRTCState *rtc, struct tm *tm, uint32_t *ns);
int spapr_rtc_import_offset(sPAPRRTCState *rtc, int64_t legacy_offset);
@@ -839,4 +849,5 @@
#define SPAPR_OV5_XIVE_EXPLOIT 0x40
#define SPAPR_OV5_XIVE_BOTH 0x80 /* Only to advertise on the platform */
+void spapr_set_all_lpcrs(target_ulong value, target_ulong mask);
#endif /* HW_SPAPR_H */
diff --git a/include/hw/ppc/spapr_drc.h b/include/hw/ppc/spapr_drc.h
index f6ff32e..46b0f62 100644
--- a/include/hw/ppc/spapr_drc.h
+++ b/include/hw/ppc/spapr_drc.h
@@ -18,6 +18,7 @@
#include "qom/object.h"
#include "sysemu/sysemu.h"
#include "hw/qdev.h"
+#include "qapi/error.h"
#define TYPE_SPAPR_DR_CONNECTOR "spapr-dr-connector"
#define SPAPR_DR_CONNECTOR_GET_CLASS(obj) \
@@ -70,6 +71,14 @@
#define SPAPR_DRC_LMB(obj) OBJECT_CHECK(sPAPRDRConnector, (obj), \
TYPE_SPAPR_DRC_LMB)
+#define TYPE_SPAPR_DRC_PHB "spapr-drc-phb"
+#define SPAPR_DRC_PHB_GET_CLASS(obj) \
+ OBJECT_GET_CLASS(sPAPRDRConnectorClass, obj, TYPE_SPAPR_DRC_PHB)
+#define SPAPR_DRC_PHB_CLASS(klass) \
+ OBJECT_CLASS_CHECK(sPAPRDRConnectorClass, klass, TYPE_SPAPR_DRC_PHB)
+#define SPAPR_DRC_PHB(obj) OBJECT_CHECK(sPAPRDRConnector, (obj), \
+ TYPE_SPAPR_DRC_PHB)
+
/*
* Various hotplug types managed by sPAPRDRConnector
*
@@ -213,6 +222,8 @@
int fdt_start_offset;
} sPAPRDRConnector;
+struct sPAPRMachineState;
+
typedef struct sPAPRDRConnectorClass {
/*< private >*/
DeviceClass parent;
@@ -228,6 +239,9 @@
uint32_t (*isolate)(sPAPRDRConnector *drc);
uint32_t (*unisolate)(sPAPRDRConnector *drc);
void (*release)(DeviceState *dev);
+
+ int (*dt_populate)(sPAPRDRConnector *drc, struct sPAPRMachineState *spapr,
+ void *fdt, int *fdt_start_offset, Error **errp);
} sPAPRDRConnectorClass;
typedef struct sPAPRDRCPhysical {
@@ -255,8 +269,7 @@
int spapr_drc_populate_dt(void *fdt, int fdt_offset, Object *owner,
uint32_t drc_type_mask);
-void spapr_drc_attach(sPAPRDRConnector *drc, DeviceState *d, void *fdt,
- int fdt_start_offset, Error **errp);
+void spapr_drc_attach(sPAPRDRConnector *drc, DeviceState *d, Error **errp);
void spapr_drc_detach(sPAPRDRConnector *drc);
bool spapr_drc_needed(void *opaque);
diff --git a/include/hw/ppc/spapr_irq.h b/include/hw/ppc/spapr_irq.h
index 488511c..ec1ee64 100644
--- a/include/hw/ppc/spapr_irq.h
+++ b/include/hw/ppc/spapr_irq.h
@@ -47,6 +47,7 @@
int (*post_load)(sPAPRMachineState *spapr, int version_id);
void (*reset)(sPAPRMachineState *spapr, Error **errp);
void (*set_irq)(void *opaque, int srcno, int val);
+ const char *(*get_nodename)(sPAPRMachineState *spapr);
} sPAPRIrq;
extern sPAPRIrq spapr_irq_xics;
@@ -60,6 +61,7 @@
qemu_irq spapr_qirq(sPAPRMachineState *spapr, int irq);
int spapr_irq_post_load(sPAPRMachineState *spapr, int version_id);
void spapr_irq_reset(sPAPRMachineState *spapr, Error **errp);
+int spapr_irq_get_phandle(sPAPRMachineState *spapr, void *fdt, Error **errp);
/*
* XICS legacy routines
diff --git a/include/hw/ppc/spapr_xive.h b/include/hw/ppc/spapr_xive.h
index 9bec919..2d31f24 100644
--- a/include/hw/ppc/spapr_xive.h
+++ b/include/hw/ppc/spapr_xive.h
@@ -26,6 +26,9 @@
XiveENDSource end_source;
hwaddr end_base;
+ /* DT */
+ gchar *nodename;
+
/* Routing table */
XiveEAS *eat;
uint32_t nr_irqs;
diff --git a/include/hw/ppc/xics.h b/include/hw/ppc/xics.h
index d36bbe1..eb65ad7 100644
--- a/include/hw/ppc/xics.h
+++ b/include/hw/ppc/xics.h
@@ -195,6 +195,7 @@
void icp_kvm_realize(DeviceState *dev, Error **errp);
void ics_get_kvm_state(ICSState *ics);
+int ics_set_kvm_state_one(ICSState *ics, int srcno);
int ics_set_kvm_state(ICSState *ics);
void ics_synchronize_state(ICSState *ics);
void ics_kvm_set_irq(ICSState *ics, int srcno, int val);
diff --git a/include/hw/ppc/xics_spapr.h b/include/hw/ppc/xics_spapr.h
index b1ab27d..b8d924b 100644
--- a/include/hw/ppc/xics_spapr.h
+++ b/include/hw/ppc/xics_spapr.h
@@ -29,6 +29,8 @@
#include "hw/ppc/spapr.h"
+#define XICS_NODENAME "interrupt-controller"
+
void spapr_dt_xics(sPAPRMachineState *spapr, uint32_t nr_servers, void *fdt,
uint32_t phandle);
int xics_kvm_init(sPAPRMachineState *spapr, Error **errp);
diff --git a/include/hw/qdev-core.h b/include/hw/qdev-core.h
index e70a4bf..17f09aa 100644
--- a/include/hw/qdev-core.h
+++ b/include/hw/qdev-core.h
@@ -206,6 +206,7 @@
HotplugHandler *hotplug_handler;
int max_index;
bool realized;
+ int num_children;
QTAILQ_HEAD(, BusChild) children;
QLIST_ENTRY(BusState) sibling;
};
@@ -280,7 +281,19 @@
void qdev_init_nofail(DeviceState *dev);
void qdev_set_legacy_instance_id(DeviceState *dev, int alias_id,
int required_for_version);
+HotplugHandler *qdev_get_bus_hotplug_handler(DeviceState *dev);
HotplugHandler *qdev_get_machine_hotplug_handler(DeviceState *dev);
+/**
+ * qdev_get_hotplug_handler: Get handler responsible for device wiring
+ *
+ * Find HOTPLUG_HANDLER for @dev that provides [pre|un]plug callbacks for it.
+ *
+ * Note: in case @dev has a parent bus, it will be returned as handler unless
+ * machine handler overrides it.
+ *
+ * Returns: pointer to object that implements TYPE_HOTPLUG_HANDLER interface
+ * or NULL if there aren't any.
+ */
HotplugHandler *qdev_get_hotplug_handler(DeviceState *dev);
void qdev_unplug(DeviceState *dev, Error **errp);
void qdev_simple_device_unplug_cb(HotplugHandler *hotplug_dev,
diff --git a/include/hw/virtio/virtio-balloon.h b/include/hw/virtio/virtio-balloon.h
index e0df352..1afafb1 100644
--- a/include/hw/virtio/virtio-balloon.h
+++ b/include/hw/virtio/virtio-balloon.h
@@ -17,11 +17,14 @@
#include "standard-headers/linux/virtio_balloon.h"
#include "hw/virtio/virtio.h"
+#include "sysemu/iothread.h"
#define TYPE_VIRTIO_BALLOON "virtio-balloon-device"
#define VIRTIO_BALLOON(obj) \
OBJECT_CHECK(VirtIOBalloon, (obj), TYPE_VIRTIO_BALLOON)
+#define VIRTIO_BALLOON_FREE_PAGE_REPORT_CMD_ID_MIN 0x80000000
+
typedef struct virtio_balloon_stat VirtIOBalloonStat;
typedef struct virtio_balloon_stat_modern {
@@ -30,18 +33,44 @@
uint64_t val;
} VirtIOBalloonStatModern;
+typedef struct PartiallyBalloonedPage PartiallyBalloonedPage;
+
+enum virtio_balloon_free_page_report_status {
+ FREE_PAGE_REPORT_S_STOP = 0,
+ FREE_PAGE_REPORT_S_REQUESTED = 1,
+ FREE_PAGE_REPORT_S_START = 2,
+ FREE_PAGE_REPORT_S_DONE = 3,
+};
+
typedef struct VirtIOBalloon {
VirtIODevice parent_obj;
- VirtQueue *ivq, *dvq, *svq;
+ VirtQueue *ivq, *dvq, *svq, *free_page_vq;
+ uint32_t free_page_report_status;
uint32_t num_pages;
uint32_t actual;
+ uint32_t free_page_report_cmd_id;
uint64_t stats[VIRTIO_BALLOON_S_NR];
VirtQueueElement *stats_vq_elem;
size_t stats_vq_offset;
QEMUTimer *stats_timer;
+ IOThread *iothread;
+ QEMUBH *free_page_bh;
+ /*
+ * Lock to synchronize threads to access the free page reporting related
+ * fields (e.g. free_page_report_status).
+ */
+ QemuMutex free_page_lock;
+ QemuCond free_page_cond;
+ /*
+ * Set to block iothread to continue reading free page hints as the VM is
+ * stopped.
+ */
+ bool block_iothread;
+ NotifierWithReturn free_page_report_notify;
int64_t stats_last_update;
int64_t stats_poll_interval;
uint32_t host_features;
+ PartiallyBalloonedPage *pbp;
} VirtIOBalloon;
#endif
diff --git a/include/hw/virtio/virtio-blk.h b/include/hw/virtio/virtio-blk.h
index 5117431..cddcfbe 100644
--- a/include/hw/virtio/virtio-blk.h
+++ b/include/hw/virtio/virtio-blk.h
@@ -35,11 +35,11 @@
BlockConf conf;
IOThread *iothread;
char *serial;
- uint32_t scsi;
- uint32_t config_wce;
uint32_t request_merging;
uint16_t num_queues;
uint16_t queue_size;
+ uint32_t max_discard_sectors;
+ uint32_t max_write_zeroes_sectors;
};
struct VirtIOBlockDataPlane;
@@ -57,6 +57,8 @@
bool dataplane_disabled;
bool dataplane_started;
struct VirtIOBlockDataPlane *dataplane;
+ uint64_t host_features;
+ size_t config_size;
} VirtIOBlock;
typedef struct VirtIOBlockReq {
diff --git a/include/hw/virtio/virtio-gpu.h b/include/hw/virtio/virtio-gpu.h
index c8c599f..98504f9 100644
--- a/include/hw/virtio/virtio-gpu.h
+++ b/include/hw/virtio/virtio-gpu.h
@@ -61,12 +61,15 @@
enum virtio_gpu_conf_flags {
VIRTIO_GPU_FLAG_VIRGL_ENABLED = 1,
VIRTIO_GPU_FLAG_STATS_ENABLED,
+ VIRTIO_GPU_FLAG_EDID_ENABLED,
};
#define virtio_gpu_virgl_enabled(_cfg) \
(_cfg.flags & (1 << VIRTIO_GPU_FLAG_VIRGL_ENABLED))
#define virtio_gpu_stats_enabled(_cfg) \
(_cfg.flags & (1 << VIRTIO_GPU_FLAG_STATS_ENABLED))
+#define virtio_gpu_edid_enabled(_cfg) \
+ (_cfg.flags & (1 << VIRTIO_GPU_FLAG_EDID_ENABLED))
struct virtio_gpu_conf {
uint64_t max_hostmem;
@@ -81,7 +84,6 @@
VirtQueue *vq;
struct virtio_gpu_ctrl_hdr cmd_hdr;
uint32_t error;
- bool waiting;
bool finished;
QTAILQ_ENTRY(virtio_gpu_ctrl_command) next;
};
@@ -96,9 +98,6 @@
int enable;
- int config_size;
- DeviceState *qdev;
-
QTAILQ_HEAD(, virtio_gpu_simple_resource) reslist;
QTAILQ_HEAD(, virtio_gpu_ctrl_command) cmdq;
QTAILQ_HEAD(, virtio_gpu_ctrl_command) fenceq;
@@ -159,6 +158,8 @@
enum virtio_gpu_ctrl_type type);
void virtio_gpu_get_display_info(VirtIOGPU *g,
struct virtio_gpu_ctrl_command *cmd);
+void virtio_gpu_get_edid(VirtIOGPU *g,
+ struct virtio_gpu_ctrl_command *cmd);
int virtio_gpu_create_mapping_iov(VirtIOGPU *g,
struct virtio_gpu_resource_attach_backing *ab,
struct virtio_gpu_ctrl_command *cmd,
@@ -172,7 +173,6 @@
struct virtio_gpu_ctrl_command *cmd);
void virtio_gpu_virgl_fence_poll(VirtIOGPU *g);
void virtio_gpu_virgl_reset(VirtIOGPU *g);
-void virtio_gpu_gl_block(void *opaque, bool block);
int virtio_gpu_virgl_init(VirtIOGPU *g);
int virtio_gpu_virgl_get_num_capsets(VirtIOGPU *g);
#endif
diff --git a/include/hw/virtio/virtio-net.h b/include/hw/virtio/virtio-net.h
index a1a0be3..b96f0c6 100644
--- a/include/hw/virtio/virtio-net.h
+++ b/include/hw/virtio/virtio-net.h
@@ -17,6 +17,7 @@
#include "qemu/units.h"
#include "standard-headers/linux/virtio_net.h"
#include "hw/virtio/virtio.h"
+#include "net/announce.h"
#define TYPE_VIRTIO_NET "virtio-net-device"
#define VIRTIO_NET(obj) \
@@ -181,8 +182,7 @@
char *netclient_name;
char *netclient_type;
uint64_t curr_guest_offloads;
- QEMUTimer *announce_timer;
- int announce_counter;
+ AnnounceTimer announce_timer;
bool needs_vnet_hdr_swap;
bool mtu_bypass_backend;
};
diff --git a/include/hw/virtio/virtio.h b/include/hw/virtio/virtio.h
index 9c1fa07..ce95162 100644
--- a/include/hw/virtio/virtio.h
+++ b/include/hw/virtio/virtio.h
@@ -37,6 +37,21 @@
return QEMU_ALIGN_UP(addr, align);
}
+/*
+ * Calculate the number of bytes up to and including the given 'field' of
+ * 'container'.
+ */
+#define virtio_endof(container, field) \
+ (offsetof(container, field) + sizeof_field(container, field))
+
+typedef struct VirtIOFeature {
+ uint64_t flags;
+ size_t end;
+} VirtIOFeature;
+
+size_t virtio_feature_get_config_size(VirtIOFeature *features,
+ uint64_t host_features);
+
typedef struct VirtQueue VirtQueue;
#define VIRTQUEUE_MAX_SIZE 1024
diff --git a/include/hw/watchdog/cmsdk-apb-watchdog.h b/include/hw/watchdog/cmsdk-apb-watchdog.h
index ab8b598..6ae9531 100644
--- a/include/hw/watchdog/cmsdk-apb-watchdog.h
+++ b/include/hw/watchdog/cmsdk-apb-watchdog.h
@@ -38,6 +38,12 @@
#define CMSDK_APB_WATCHDOG(obj) OBJECT_CHECK(CMSDKAPBWatchdog, (obj), \
TYPE_CMSDK_APB_WATCHDOG)
+/*
+ * This shares the same struct (and cast macro) as the base
+ * cmsdk-apb-watchdog device.
+ */
+#define TYPE_LUMINARY_WATCHDOG "luminary-watchdog"
+
typedef struct CMSDKAPBWatchdog {
/*< private >*/
SysBusDevice parent_obj;
@@ -46,6 +52,7 @@
MemoryRegion iomem;
qemu_irq wdogint;
uint32_t wdogclk_frq;
+ bool is_luminary;
struct ptimer_state *timer;
uint32_t control;
@@ -54,6 +61,7 @@
uint32_t itcr;
uint32_t itop;
uint32_t resetstatus;
+ const uint32_t *id;
} CMSDKAPBWatchdog;
#endif
diff --git a/include/io/channel.h b/include/io/channel.h
index da2f138..59460cb 100644
--- a/include/io/channel.h
+++ b/include/io/channel.h
@@ -739,10 +739,13 @@
* addition, no two coroutine can be waiting on the same condition
* and channel at the same time.
*
- * This must only be called from coroutine context
+ * This must only be called from coroutine context. It is safe to
+ * reenter the coroutine externally while it is waiting; in this
+ * case the function will return even if @condition is not yet
+ * available.
*/
-void qio_channel_yield(QIOChannel *ioc,
- GIOCondition condition);
+void coroutine_fn qio_channel_yield(QIOChannel *ioc,
+ GIOCondition condition);
/**
* qio_channel_wait:
diff --git a/include/migration/misc.h b/include/migration/misc.h
index 4ebf24c..5cdbabd 100644
--- a/include/migration/misc.h
+++ b/include/migration/misc.h
@@ -14,11 +14,34 @@
#ifndef MIGRATION_MISC_H
#define MIGRATION_MISC_H
+#include "exec/cpu-common.h"
#include "qemu/notify.h"
+#include "qapi/qapi-types-net.h"
/* migration/ram.c */
+typedef enum PrecopyNotifyReason {
+ PRECOPY_NOTIFY_SETUP = 0,
+ PRECOPY_NOTIFY_BEFORE_BITMAP_SYNC = 1,
+ PRECOPY_NOTIFY_AFTER_BITMAP_SYNC = 2,
+ PRECOPY_NOTIFY_COMPLETE = 3,
+ PRECOPY_NOTIFY_CLEANUP = 4,
+ PRECOPY_NOTIFY_MAX = 5,
+} PrecopyNotifyReason;
+
+typedef struct PrecopyNotifyData {
+ enum PrecopyNotifyReason reason;
+ Error **errp;
+} PrecopyNotifyData;
+
+void precopy_infrastructure_init(void);
+void precopy_add_notifier(NotifierWithReturn *n);
+void precopy_remove_notifier(NotifierWithReturn *n);
+int precopy_notify(PrecopyNotifyReason reason, Error **errp);
+void precopy_enable_free_page_optimization(void);
+
void ram_mig_init(void);
+void qemu_guest_free_page_hint(void *addr, size_t len);
/* migration/block.c */
@@ -28,23 +51,14 @@
static inline void blk_mig_init(void) {}
#endif
-#define SELF_ANNOUNCE_ROUNDS 5
-
-static inline
-int64_t self_announce_delay(int round)
-{
- assert(round < SELF_ANNOUNCE_ROUNDS && round > 0);
- /* delay 50ms, 150ms, 250ms, ... */
- return 50 + (SELF_ANNOUNCE_ROUNDS - round - 1) * 100;
-}
-
+AnnounceParameters *migrate_announce_params(void);
/* migration/savevm.c */
void dump_vmstate_json_to_file(FILE *out_fp);
/* migration/migration.c */
void migration_object_init(void);
-void migration_object_finalize(void);
+void migration_shutdown(void);
void qemu_start_incoming_migration(const char *uri, Error **errp);
bool migration_is_idle(void);
void add_migration_state_change_notifier(Notifier *notify);
diff --git a/include/migration/vmstate.h b/include/migration/vmstate.h
index 067b126..a668ec7 100644
--- a/include/migration/vmstate.h
+++ b/include/migration/vmstate.h
@@ -851,6 +851,9 @@
#define VMSTATE_INT32_POSITIVE_LE(_f, _s) \
VMSTATE_SINGLE(_f, _s, 0, vmstate_info_int32_le, int32_t)
+#define VMSTATE_BOOL_TEST(_f, _s, _t) \
+ VMSTATE_SINGLE_TEST(_f, _s, _t, 0, vmstate_info_bool, bool)
+
#define VMSTATE_INT8_TEST(_f, _s, _t) \
VMSTATE_SINGLE_TEST(_f, _s, _t, 0, vmstate_info_int8, int8_t)
diff --git a/include/net/announce.h b/include/net/announce.h
new file mode 100644
index 0000000..892d302
--- /dev/null
+++ b/include/net/announce.h
@@ -0,0 +1,41 @@
+/*
+ * Self-announce facility
+ * (c) 2017-2019 Red Hat, Inc.
+ *
+ * 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 QEMU_NET_ANNOUNCE_H
+#define QEMU_NET_ANNOUNCE_H
+
+#include "qemu-common.h"
+#include "qapi/qapi-types-net.h"
+#include "qemu/timer.h"
+
+struct AnnounceTimer {
+ QEMUTimer *tm;
+ AnnounceParameters params;
+ QEMUClockType type;
+ int round;
+};
+
+/* Returns: update the timer to the next time point */
+int64_t qemu_announce_timer_step(AnnounceTimer *timer);
+
+/* Delete the underlying timer */
+void qemu_announce_timer_del(AnnounceTimer *timer);
+
+/*
+ * Under BQL/main thread
+ * Reset the timer to the given parameters/type/notifier.
+ */
+void qemu_announce_timer_reset(AnnounceTimer *timer,
+ AnnounceParameters *params,
+ QEMUClockType type,
+ QEMUTimerCB *cb,
+ void *opaque);
+
+void qemu_announce_self(AnnounceTimer *timer, AnnounceParameters *params);
+
+#endif
diff --git a/include/net/net.h b/include/net/net.h
index 075cc01..acf0451 100644
--- a/include/net/net.h
+++ b/include/net/net.h
@@ -60,6 +60,7 @@
typedef int (SetVnetBE)(NetClientState *, bool);
typedef struct SocketReadState SocketReadState;
typedef void (SocketReadStateFinalize)(SocketReadState *rs);
+typedef void (NetAnnounce)(NetClientState *);
typedef struct NetClientInfo {
NetClientDriver type;
@@ -80,6 +81,7 @@
SetVnetHdrLen *set_vnet_hdr_len;
SetVnetLE *set_vnet_le;
SetVnetBE *set_vnet_be;
+ NetAnnounce *announce;
} NetClientInfo;
struct NetClientState {
diff --git a/include/qemu/acl.h b/include/qemu/acl.h
deleted file mode 100644
index 73d2a71..0000000
--- a/include/qemu/acl.h
+++ /dev/null
@@ -1,66 +0,0 @@
-/*
- * QEMU access control list management
- *
- * Copyright (C) 2009 Red Hat, Inc
- *
- * 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.
- */
-
-#ifndef QEMU_ACL_H
-#define QEMU_ACL_H
-
-#include "qemu/queue.h"
-
-typedef struct qemu_acl_entry qemu_acl_entry;
-typedef struct qemu_acl qemu_acl;
-
-struct qemu_acl_entry {
- char *match;
- int deny;
-
- QTAILQ_ENTRY(qemu_acl_entry) next;
-};
-
-struct qemu_acl {
- char *aclname;
- unsigned int nentries;
- QTAILQ_HEAD(,qemu_acl_entry) entries;
- int defaultDeny;
-};
-
-qemu_acl *qemu_acl_init(const char *aclname);
-
-qemu_acl *qemu_acl_find(const char *aclname);
-
-int qemu_acl_party_is_allowed(qemu_acl *acl,
- const char *party);
-
-void qemu_acl_reset(qemu_acl *acl);
-
-int qemu_acl_append(qemu_acl *acl,
- int deny,
- const char *match);
-int qemu_acl_insert(qemu_acl *acl,
- int deny,
- const char *match,
- int index);
-int qemu_acl_remove(qemu_acl *acl,
- const char *match);
-
-#endif /* QEMU_ACL_H */
diff --git a/include/qemu/bitmap.h b/include/qemu/bitmap.h
index 509eedd..5c31334 100644
--- a/include/qemu/bitmap.h
+++ b/include/qemu/bitmap.h
@@ -221,6 +221,10 @@
static inline long bitmap_count_one(const unsigned long *bitmap, long nbits)
{
+ if (unlikely(!nbits)) {
+ return 0;
+ }
+
if (small_nbits(nbits)) {
return ctpopl(*bitmap & BITMAP_LAST_WORD_MASK(nbits));
} else {
@@ -228,6 +232,19 @@
}
}
+static inline long bitmap_count_one_with_offset(const unsigned long *bitmap,
+ long offset, long nbits)
+{
+ long aligned_offset = QEMU_ALIGN_DOWN(offset, BITS_PER_LONG);
+ long redundant_bits = offset - aligned_offset;
+ long bits_to_count = nbits + redundant_bits;
+ const unsigned long *bitmap_start = bitmap +
+ aligned_offset / BITS_PER_LONG;
+
+ return bitmap_count_one(bitmap_start, bits_to_count) -
+ bitmap_count_one(bitmap_start, redundant_bits);
+}
+
void bitmap_set(unsigned long *map, long i, long len);
void bitmap_set_atomic(unsigned long *map, long i, long len);
void bitmap_clear(unsigned long *map, long start, long nr);
diff --git a/include/qemu/bswap.h b/include/qemu/bswap.h
index a684c1a..5a70f78 100644
--- a/include/qemu/bswap.h
+++ b/include/qemu/bswap.h
@@ -255,9 +255,9 @@
/*
* the generic syntax is:
*
- * load: ld{type}{sign}{size}{endian}_p(ptr)
+ * load: ld{type}{sign}{size}_{endian}_p(ptr)
*
- * store: st{type}{size}{endian}_p(ptr, val)
+ * store: st{type}{size}_{endian}_p(ptr, val)
*
* Note there are small differences with the softmmu access API!
*
@@ -293,10 +293,10 @@
*
* For cases where the size to be used is not fixed at compile time,
* there are
- * stn{endian}_p(ptr, sz, val)
+ * stn_{endian}_p(ptr, sz, val)
* which stores @val to @ptr as an @endian-order number @sz bytes in size
* and
- * ldn{endian}_p(ptr, sz)
+ * ldn_{endian}_p(ptr, sz)
* which loads @sz bytes from @ptr as an unsigned @endian-order number
* and returns it in a uint64_t.
*/
diff --git a/include/qemu/filemonitor.h b/include/qemu/filemonitor.h
new file mode 100644
index 0000000..cd03183
--- /dev/null
+++ b/include/qemu/filemonitor.h
@@ -0,0 +1,128 @@
+/*
+ * QEMU file monitor helper
+ *
+ * Copyright (c) 2018 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * 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/>.
+ *
+ */
+
+#ifndef QEMU_FILE_MONITOR_H
+#define QEMU_FILE_MONITOR_H
+
+#include "qemu-common.h"
+
+
+typedef struct QFileMonitor QFileMonitor;
+
+typedef enum {
+ /* File has been created in a dir */
+ QFILE_MONITOR_EVENT_CREATED,
+ /* File has been modified in a dir */
+ QFILE_MONITOR_EVENT_MODIFIED,
+ /* File has been deleted in a dir */
+ QFILE_MONITOR_EVENT_DELETED,
+ /* File has attributes changed */
+ QFILE_MONITOR_EVENT_ATTRIBUTES,
+ /* Dir is no longer being monitored (due to deletion) */
+ QFILE_MONITOR_EVENT_IGNORED,
+} QFileMonitorEvent;
+
+
+/**
+ * QFileMonitorHandler:
+ * @id: id from qemu_file_monitor_add_watch()
+ * @event: the file change that occurred
+ * @filename: the name of the file affected
+ * @opaque: opaque data provided to qemu_file_monitor_add_watch()
+ *
+ * Invoked whenever a file changes. If @event is
+ * QFILE_MONITOR_EVENT_IGNORED, @filename will be
+ * empty.
+ *
+ */
+typedef void (*QFileMonitorHandler)(int id,
+ QFileMonitorEvent event,
+ const char *filename,
+ void *opaque);
+
+/**
+ * qemu_file_monitor_new:
+ * @errp: pointer to a NULL-initialized error object
+ *
+ * Create a handle for a file monitoring object.
+ *
+ * This object does locking internally to enable it to be
+ * safe to use from multiple threads
+ *
+ * If the platform does not support file monitoring, an
+ * error will be reported. Likewise if file monitoring
+ * is supported, but cannot be initialized
+ *
+ * Currently this is implemented on Linux platforms with
+ * the inotify subsystem.
+ *
+ * Returns: the new monitoring object, or NULL on error
+ */
+QFileMonitor *qemu_file_monitor_new(Error **errp);
+
+/**
+ * qemu_file_monitor_free:
+ * @mon: the file monitor context
+ *
+ * Free resources associated with the file monitor,
+ * including any currently registered watches.
+ */
+void qemu_file_monitor_free(QFileMonitor *mon);
+
+/**
+ * qemu_file_monitor_add_watch:
+ * @mon: the file monitor context
+ * @dirpath: the directory whose contents to watch
+ * @filename: optional filename to filter on
+ * @cb: the function to invoke when @dirpath has changes
+ * @opaque: data to pass to @cb
+ * @errp: pointer to a NULL-initialized error object
+ *
+ * Register to receive notifications of changes
+ * in the directory @dirpath. All files in the
+ * directory will be monitored. If the caller is
+ * only interested in one specific file, @filename
+ * can be used to filter events.
+ *
+ * Returns: a positive integer watch ID, or -1 on error
+ */
+int qemu_file_monitor_add_watch(QFileMonitor *mon,
+ const char *dirpath,
+ const char *filename,
+ QFileMonitorHandler cb,
+ void *opaque,
+ Error **errp);
+
+/**
+ * qemu_file_monitor_remove_watch:
+ * @mon: the file monitor context
+ * @dirpath: the directory whose contents to unwatch
+ * @id: id of the watch to remove
+ *
+ * Removes the file monitoring watch @id, associated
+ * with the directory @dirpath. This must never be
+ * called from a QFileMonitorHandler callback, or a
+ * deadlock will result.
+ */
+void qemu_file_monitor_remove_watch(QFileMonitor *mon,
+ const char *dirpath,
+ int id);
+
+#endif /* QEMU_FILE_MONITOR_H */
diff --git a/include/qemu/iov.h b/include/qemu/iov.h
index 5f433c7..48b4598 100644
--- a/include/qemu/iov.h
+++ b/include/qemu/iov.h
@@ -133,10 +133,70 @@
typedef struct QEMUIOVector {
struct iovec *iov;
int niov;
- int nalloc;
- size_t size;
+
+ /*
+ * For external @iov (qemu_iovec_init_external()) or allocated @iov
+ * (qemu_iovec_init()), @size is the cumulative size of iovecs and
+ * @local_iov is invalid and unused.
+ *
+ * For embedded @iov (QEMU_IOVEC_INIT_BUF() or qemu_iovec_init_buf()),
+ * @iov is equal to &@local_iov, and @size is valid, as it has same
+ * offset and type as @local_iov.iov_len, which is guaranteed by
+ * static assertion below.
+ *
+ * @nalloc is always valid and is -1 both for embedded and external
+ * cases. It is included in the union only to ensure the padding prior
+ * to the @size field will not result in a 0-length array.
+ */
+ union {
+ struct {
+ int nalloc;
+ struct iovec local_iov;
+ };
+ struct {
+ char __pad[sizeof(int) + offsetof(struct iovec, iov_len)];
+ size_t size;
+ };
+ };
} QEMUIOVector;
+QEMU_BUILD_BUG_ON(offsetof(QEMUIOVector, size) !=
+ offsetof(QEMUIOVector, local_iov.iov_len));
+
+#define QEMU_IOVEC_INIT_BUF(self, buf, len) \
+{ \
+ .iov = &(self).local_iov, \
+ .niov = 1, \
+ .nalloc = -1, \
+ .local_iov = { \
+ .iov_base = (void *)(buf), /* cast away const */ \
+ .iov_len = (len), \
+ }, \
+}
+
+/*
+ * qemu_iovec_init_buf
+ *
+ * Initialize embedded QEMUIOVector.
+ *
+ * Note: "const" is used over @buf pointer to make it simple to pass
+ * const pointers, appearing in read functions. Then this "const" is
+ * cast away by QEMU_IOVEC_INIT_BUF().
+ */
+static inline void qemu_iovec_init_buf(QEMUIOVector *qiov,
+ const void *buf, size_t len)
+{
+ *qiov = (QEMUIOVector) QEMU_IOVEC_INIT_BUF(*qiov, buf, len);
+}
+
+static inline void *qemu_iovec_buf(QEMUIOVector *qiov)
+{
+ /* Only supports embedded iov */
+ assert(qiov->nalloc == -1 && qiov->iov == &qiov->local_iov);
+
+ return qiov->local_iov.iov_base;
+}
+
void qemu_iovec_init(QEMUIOVector *qiov, int alloc_hint);
void qemu_iovec_init_external(QEMUIOVector *qiov, struct iovec *iov, int niov);
void qemu_iovec_add(QEMUIOVector *qiov, void *base, size_t len);
diff --git a/include/qemu/typedefs.h b/include/qemu/typedefs.h
index 5d1a2d8..e4a0a65 100644
--- a/include/qemu/typedefs.h
+++ b/include/qemu/typedefs.h
@@ -8,6 +8,7 @@
typedef struct AdapterInfo AdapterInfo;
typedef struct AddressSpace AddressSpace;
typedef struct AioContext AioContext;
+typedef struct AnnounceTimer AnnounceTimer;
typedef struct BdrvDirtyBitmap BdrvDirtyBitmap;
typedef struct BdrvDirtyBitmapIter BdrvDirtyBitmapIter;
typedef struct BlockBackend BlockBackend;
diff --git a/include/sysemu/block-backend.h b/include/sysemu/block-backend.h
index 832a4bf..e2066eb 100644
--- a/include/sysemu/block-backend.h
+++ b/include/sysemu/block-backend.h
@@ -156,6 +156,8 @@
int blk_co_flush(BlockBackend *blk);
int blk_flush(BlockBackend *blk);
int blk_commit_all(void);
+void blk_inc_in_flight(BlockBackend *blk);
+void blk_dec_in_flight(BlockBackend *blk);
void blk_drain(BlockBackend *blk);
void blk_drain_all(void);
void blk_set_on_error(BlockBackend *blk, BlockdevOnError on_read_error,
diff --git a/include/sysemu/sysemu.h b/include/sysemu/sysemu.h
index 4b5a6b7..89604a8 100644
--- a/include/sysemu/sysemu.h
+++ b/include/sysemu/sysemu.h
@@ -81,8 +81,6 @@
void qemu_add_machine_init_done_notifier(Notifier *notify);
void qemu_remove_machine_init_done_notifier(Notifier *notify);
-void qemu_announce_self(void);
-
extern int autostart;
typedef enum {
diff --git a/include/ui/spice-display.h b/include/ui/spice-display.h
index 87a84a5..53c3612 100644
--- a/include/ui/spice-display.h
+++ b/include/ui/spice-display.h
@@ -179,3 +179,7 @@
void qemu_spice_display_start(void);
void qemu_spice_display_stop(void);
int qemu_spice_display_is_running(SimpleSpiceDisplay *ssd);
+
+bool qemu_spice_fill_device_address(QemuConsole *con,
+ char *device_address,
+ size_t size);
diff --git a/io/channel.c b/io/channel.c
index 8dd0684..2a26c2a 100644
--- a/io/channel.c
+++ b/io/channel.c
@@ -400,15 +400,14 @@
}
-static void qio_channel_set_aio_fd_handlers(QIOChannel *ioc);
-
static void qio_channel_restart_read(void *opaque)
{
QIOChannel *ioc = opaque;
Coroutine *co = ioc->read_coroutine;
- ioc->read_coroutine = NULL;
- qio_channel_set_aio_fd_handlers(ioc);
+ /* Assert that aio_co_wake() reenters the coroutine directly */
+ assert(qemu_get_current_aio_context() ==
+ qemu_coroutine_get_aio_context(co));
aio_co_wake(co);
}
@@ -417,8 +416,9 @@
QIOChannel *ioc = opaque;
Coroutine *co = ioc->write_coroutine;
- ioc->write_coroutine = NULL;
- qio_channel_set_aio_fd_handlers(ioc);
+ /* Assert that aio_co_wake() reenters the coroutine directly */
+ assert(qemu_get_current_aio_context() ==
+ qemu_coroutine_get_aio_context(co));
aio_co_wake(co);
}
@@ -469,6 +469,16 @@
}
qio_channel_set_aio_fd_handlers(ioc);
qemu_coroutine_yield();
+
+ /* Allow interrupting the operation by reentering the coroutine other than
+ * through the aio_fd_handlers. */
+ if (condition == G_IO_IN && ioc->read_coroutine) {
+ ioc->read_coroutine = NULL;
+ qio_channel_set_aio_fd_handlers(ioc);
+ } else if (condition == G_IO_OUT && ioc->write_coroutine) {
+ ioc->write_coroutine = NULL;
+ qio_channel_set_aio_fd_handlers(ioc);
+ }
}
diff --git a/linux-user/elfload.c b/linux-user/elfload.c
index 3a50d58..6e8762b 100644
--- a/linux-user/elfload.c
+++ b/linux-user/elfload.c
@@ -602,6 +602,10 @@
GET_FEATURE_ID(aa64_fcma, ARM_HWCAP_A64_FCMA);
GET_FEATURE_ID(aa64_sve, ARM_HWCAP_A64_SVE);
GET_FEATURE_ID(aa64_pauth, ARM_HWCAP_A64_PACA | ARM_HWCAP_A64_PACG);
+ GET_FEATURE_ID(aa64_fhm, ARM_HWCAP_A64_ASIMDFHM);
+ GET_FEATURE_ID(aa64_jscvt, ARM_HWCAP_A64_JSCVT);
+ GET_FEATURE_ID(aa64_sb, ARM_HWCAP_A64_SB);
+ GET_FEATURE_ID(aa64_condm_4, ARM_HWCAP_A64_FLAGM);
#undef GET_FEATURE_ID
diff --git a/migration/block.c b/migration/block.c
index 0e24e18..83c633f 100644
--- a/migration/block.c
+++ b/migration/block.c
@@ -83,7 +83,6 @@
BlkMigDevState *bmds;
int64_t sector;
int nr_sectors;
- struct iovec iov;
QEMUIOVector qiov;
BlockAIOCB *aiocb;
@@ -314,9 +313,7 @@
blk->sector = cur_sector;
blk->nr_sectors = nr_sectors;
- blk->iov.iov_base = blk->buf;
- blk->iov.iov_len = nr_sectors * BDRV_SECTOR_SIZE;
- qemu_iovec_init_external(&blk->qiov, &blk->iov, 1);
+ qemu_iovec_init_buf(&blk->qiov, blk->buf, nr_sectors * BDRV_SECTOR_SIZE);
blk_mig_lock();
block_mig_state.submitted++;
@@ -556,9 +553,8 @@
blk->nr_sectors = nr_sectors;
if (is_async) {
- blk->iov.iov_base = blk->buf;
- blk->iov.iov_len = nr_sectors * BDRV_SECTOR_SIZE;
- qemu_iovec_init_external(&blk->qiov, &blk->iov, 1);
+ qemu_iovec_init_buf(&blk->qiov, blk->buf,
+ nr_sectors * BDRV_SECTOR_SIZE);
blk->aiocb = blk_aio_preadv(bmds->blk,
sector * BDRV_SECTOR_SIZE,
diff --git a/migration/colo.c b/migration/colo.c
index 398b239..5ba610d 100644
--- a/migration/colo.c
+++ b/migration/colo.c
@@ -872,8 +872,8 @@
/* Must be called after failover BH is completed */
if (mis->to_src_file) {
qemu_fclose(mis->to_src_file);
+ mis->to_src_file = NULL;
}
- migration_incoming_disable_colo();
rcu_unregister_thread();
return NULL;
diff --git a/migration/migration.c b/migration/migration.c
index 37e06b7..df6fd8e 100644
--- a/migration/migration.c
+++ b/migration/migration.c
@@ -31,6 +31,8 @@
#include "migration/vmstate.h"
#include "block/block.h"
#include "qapi/error.h"
+#include "qapi/clone-visitor.h"
+#include "qapi/qapi-visit-sockets.h"
#include "qapi/qapi-commands-migration.h"
#include "qapi/qapi-events-migration.h"
#include "qapi/qmp/qerror.h"
@@ -45,6 +47,7 @@
#include "migration/colo.h"
#include "hw/boards.h"
#include "monitor/monitor.h"
+#include "net/announce.h"
#define MAX_THROTTLE (32 << 20) /* Migration transfer speed throttling */
@@ -86,6 +89,15 @@
*/
#define DEFAULT_MIGRATE_MAX_POSTCOPY_BANDWIDTH 0
+/*
+ * Parameters for self_announce_delay giving a stream of RARP/ARP
+ * packets after migration.
+ */
+#define DEFAULT_MIGRATE_ANNOUNCE_INITIAL 50
+#define DEFAULT_MIGRATE_ANNOUNCE_MAX 550
+#define DEFAULT_MIGRATE_ANNOUNCE_ROUNDS 5
+#define DEFAULT_MIGRATE_ANNOUNCE_STEP 100
+
static NotifierList migration_state_notifiers =
NOTIFIER_LIST_INITIALIZER(migration_state_notifiers);
@@ -116,6 +128,7 @@
static int migration_maybe_pause(MigrationState *s,
int *current_active_state,
int new_state);
+static void migrate_fd_cancel(MigrationState *s);
void migration_object_init(void)
{
@@ -157,8 +170,13 @@
}
}
-void migration_object_finalize(void)
+void migration_shutdown(void)
{
+ /*
+ * Cancel the current migration - that will (eventually)
+ * stop the migration using this structure
+ */
+ migrate_fd_cancel(current_migration);
object_unref(OBJECT(current_migration));
}
@@ -197,6 +215,11 @@
}
qemu_event_reset(&mis->main_thread_load_event);
+
+ if (mis->socket_address_list) {
+ qapi_free_SocketAddressList(mis->socket_address_list);
+ mis->socket_address_list = NULL;
+ }
}
static void migrate_generate_event(int new_state)
@@ -312,6 +335,17 @@
migration_colo_enabled = true;
}
+void migrate_add_address(SocketAddress *address)
+{
+ MigrationIncomingState *mis = migration_incoming_get_current();
+ SocketAddressList *addrs;
+
+ addrs = g_new0(SocketAddressList, 1);
+ addrs->next = mis->socket_address_list;
+ mis->socket_address_list = addrs;
+ addrs->value = QAPI_CLONE(SocketAddress, address);
+}
+
void qemu_start_incoming_migration(const char *uri, Error **errp)
{
const char *p;
@@ -364,7 +398,7 @@
* This must happen after all error conditions are dealt with and
* we're sure the VM is going to be running on this host.
*/
- qemu_announce_self();
+ qemu_announce_self(&mis->announce_timer, migrate_announce_params());
if (multifd_load_cleanup(&local_err) != 0) {
error_report_err(local_err);
@@ -383,6 +417,9 @@
} else {
runstate_set(RUN_STATE_PAUSED);
}
+ } else if (migration_incoming_colo_enabled()) {
+ migration_incoming_disable_colo();
+ vm_start();
} else {
runstate_set(global_state_get_runstate());
}
@@ -739,10 +776,32 @@
params->max_postcopy_bandwidth = s->parameters.max_postcopy_bandwidth;
params->has_max_cpu_throttle = true;
params->max_cpu_throttle = s->parameters.max_cpu_throttle;
+ params->has_announce_initial = true;
+ params->announce_initial = s->parameters.announce_initial;
+ params->has_announce_max = true;
+ params->announce_max = s->parameters.announce_max;
+ params->has_announce_rounds = true;
+ params->announce_rounds = s->parameters.announce_rounds;
+ params->has_announce_step = true;
+ params->announce_step = s->parameters.announce_step;
return params;
}
+AnnounceParameters *migrate_announce_params(void)
+{
+ static AnnounceParameters ap;
+
+ MigrationState *s = migrate_get_current();
+
+ ap.initial = s->parameters.announce_initial;
+ ap.max = s->parameters.announce_max;
+ ap.rounds = s->parameters.announce_rounds;
+ ap.step = s->parameters.announce_step;
+
+ return ≈
+}
+
/*
* Return true if we're already in the middle of a migration
* (i.e. any of the active or setup states)
@@ -957,6 +1016,11 @@
error_setg(errp, "Postcopy is not supported");
return false;
}
+
+ if (cap_list[MIGRATION_CAPABILITY_X_IGNORE_SHARED]) {
+ error_setg(errp, "Postcopy is not compatible with ignore-shared");
+ return false;
+ }
}
return true;
@@ -966,6 +1030,12 @@
{
MigrationIncomingState *mis = migration_incoming_get_current();
+ if (mis->socket_address_list) {
+ info->has_socket_address = true;
+ info->socket_address =
+ QAPI_CLONE(SocketAddressList, mis->socket_address_list);
+ }
+
switch (mis->state) {
case MIGRATION_STATUS_NONE:
return;
@@ -1116,6 +1186,35 @@
return false;
}
+ if (params->has_announce_initial &&
+ params->announce_initial > 100000) {
+ error_setg(errp, QERR_INVALID_PARAMETER_VALUE,
+ "announce_initial",
+ "is invalid, it must be less than 100000 ms");
+ return false;
+ }
+ if (params->has_announce_max &&
+ params->announce_max > 100000) {
+ error_setg(errp, QERR_INVALID_PARAMETER_VALUE,
+ "announce_max",
+ "is invalid, it must be less than 100000 ms");
+ return false;
+ }
+ if (params->has_announce_rounds &&
+ params->announce_rounds > 1000) {
+ error_setg(errp, QERR_INVALID_PARAMETER_VALUE,
+ "announce_rounds",
+ "is invalid, it must be in the range of 0 to 1000");
+ return false;
+ }
+ if (params->has_announce_step &&
+ (params->announce_step < 1 ||
+ params->announce_step > 10000)) {
+ error_setg(errp, QERR_INVALID_PARAMETER_VALUE,
+ "announce_step",
+ "is invalid, it must be in the range of 1 to 10000 ms");
+ return false;
+ }
return true;
}
@@ -1190,6 +1289,18 @@
if (params->has_max_cpu_throttle) {
dest->max_cpu_throttle = params->max_cpu_throttle;
}
+ if (params->has_announce_initial) {
+ dest->announce_initial = params->announce_initial;
+ }
+ if (params->has_announce_max) {
+ dest->announce_max = params->announce_max;
+ }
+ if (params->has_announce_rounds) {
+ dest->announce_rounds = params->announce_rounds;
+ }
+ if (params->has_announce_step) {
+ dest->announce_step = params->announce_step;
+ }
}
static void migrate_params_apply(MigrateSetParameters *params, Error **errp)
@@ -1272,6 +1383,18 @@
if (params->has_max_cpu_throttle) {
s->parameters.max_cpu_throttle = params->max_cpu_throttle;
}
+ if (params->has_announce_initial) {
+ s->parameters.announce_initial = params->announce_initial;
+ }
+ if (params->has_announce_max) {
+ s->parameters.announce_max = params->announce_max;
+ }
+ if (params->has_announce_rounds) {
+ s->parameters.announce_rounds = params->announce_rounds;
+ }
+ if (params->has_announce_step) {
+ s->parameters.announce_step = params->announce_step;
+ }
}
void qmp_migrate_set_parameters(MigrateSetParameters *params, Error **errp)
@@ -1983,6 +2106,15 @@
return s->enabled_capabilities[MIGRATION_CAPABILITY_DIRTY_BITMAPS];
}
+bool migrate_ignore_shared(void)
+{
+ MigrationState *s;
+
+ s = migrate_get_current();
+
+ return s->enabled_capabilities[MIGRATION_CAPABILITY_X_IGNORE_SHARED];
+}
+
bool migrate_use_events(void)
{
MigrationState *s;
@@ -2826,6 +2958,13 @@
static MigThrError migration_detect_error(MigrationState *s)
{
int ret;
+ int state = s->state;
+
+ if (state == MIGRATION_STATUS_CANCELLING ||
+ state == MIGRATION_STATUS_CANCELLED) {
+ /* End the migration, but don't set the state to failed */
+ return MIG_THR_ERR_FATAL;
+ }
/* Try to detect any file errors */
ret = qemu_file_get_error(s->to_dst_file);
@@ -2835,7 +2974,7 @@
return MIG_THR_ERR_NONE;
}
- if (s->state == MIGRATION_STATUS_POSTCOPY_ACTIVE && ret == -EIO) {
+ if (state == MIGRATION_STATUS_POSTCOPY_ACTIVE && ret == -EIO) {
/*
* For postcopy, we allow the network to be down for a
* while. After that, it can be continued by a
@@ -2847,7 +2986,7 @@
* For precopy (or postcopy with error outside IO), we fail
* with no time.
*/
- migrate_set_state(&s->state, s->state, MIGRATION_STATUS_FAILED);
+ migrate_set_state(&s->state, state, MIGRATION_STATUS_FAILED);
trace_migration_thread_file_err();
/* Time to stop the migration, now. */
@@ -3042,6 +3181,7 @@
rcu_register_thread();
+ object_ref(OBJECT(s));
s->iteration_start_time = qemu_clock_get_ms(QEMU_CLOCK_REALTIME);
qemu_savevm_state_header(s->to_dst_file);
@@ -3138,6 +3278,7 @@
trace_migration_thread_after_loop();
migration_iteration_finish(s);
+ object_unref(OBJECT(s));
rcu_unregister_thread();
return NULL;
}
@@ -3274,6 +3415,18 @@
DEFINE_PROP_UINT8("max-cpu-throttle", MigrationState,
parameters.max_cpu_throttle,
DEFAULT_MIGRATE_MAX_CPU_THROTTLE),
+ DEFINE_PROP_SIZE("announce-initial", MigrationState,
+ parameters.announce_initial,
+ DEFAULT_MIGRATE_ANNOUNCE_INITIAL),
+ DEFINE_PROP_SIZE("announce-max", MigrationState,
+ parameters.announce_max,
+ DEFAULT_MIGRATE_ANNOUNCE_MAX),
+ DEFINE_PROP_SIZE("announce-rounds", MigrationState,
+ parameters.announce_rounds,
+ DEFAULT_MIGRATE_ANNOUNCE_ROUNDS),
+ DEFINE_PROP_SIZE("announce-step", MigrationState,
+ parameters.announce_step,
+ DEFAULT_MIGRATE_ANNOUNCE_STEP),
/* Migration capabilities */
DEFINE_PROP_MIG_CAP("x-xbzrle", MIGRATION_CAPABILITY_XBZRLE),
@@ -3346,6 +3499,10 @@
params->has_xbzrle_cache_size = true;
params->has_max_postcopy_bandwidth = true;
params->has_max_cpu_throttle = true;
+ params->has_announce_initial = true;
+ params->has_announce_max = true;
+ params->has_announce_rounds = true;
+ params->has_announce_step = true;
qemu_sem_init(&ms->postcopy_pause_sem, 0);
qemu_sem_init(&ms->postcopy_pause_rp_sem, 0);
diff --git a/migration/migration.h b/migration/migration.h
index dcd05d9..99e99e5 100644
--- a/migration/migration.h
+++ b/migration/migration.h
@@ -21,6 +21,7 @@
#include "qemu/coroutine_int.h"
#include "hw/qdev.h"
#include "io/channel.h"
+#include "net/announce.h"
struct PostcopyBlocktimeContext;
@@ -36,6 +37,9 @@
*/
QemuEvent main_thread_load_event;
+ /* For network announces */
+ AnnounceTimer announce_timer;
+
size_t largest_page_size;
bool have_fault_thread;
QemuThread fault_thread;
@@ -80,6 +84,9 @@
bool postcopy_recover_triggered;
QemuSemaphore postcopy_pause_sem_dst;
QemuSemaphore postcopy_pause_sem_fault;
+
+ /* List of listening socket addresses */
+ SocketAddressList *socket_address_list;
};
MigrationIncomingState *migration_incoming_get_current(void);
@@ -261,6 +268,7 @@
bool migrate_postcopy_ram(void);
bool migrate_zero_blocks(void);
bool migrate_dirty_bitmaps(void);
+bool migrate_ignore_shared(void);
bool migrate_auto_converge(void);
bool migrate_use_multifd(void);
@@ -300,9 +308,12 @@
void dirty_bitmap_mig_before_vm_start(void);
void init_dirty_bitmap_incoming_migration(void);
+void migrate_add_address(SocketAddress *address);
+
+int foreach_not_ignored_block(RAMBlockIterFunc func, void *opaque);
#define qemu_ram_foreach_block \
- #warning "Use qemu_ram_foreach_block_migratable in migration code"
+ #warning "Use foreach_not_ignored_block in migration code"
void migration_make_urgent_request(void);
void migration_consume_urgent_request(void);
diff --git a/migration/postcopy-ram.c b/migration/postcopy-ram.c
index fa09dba..e2aa57a 100644
--- a/migration/postcopy-ram.c
+++ b/migration/postcopy-ram.c
@@ -319,10 +319,10 @@
/* Callback from postcopy_ram_supported_by_host block iterator.
*/
-static int test_ramblock_postcopiable(const char *block_name, void *host_addr,
- ram_addr_t offset, ram_addr_t length, void *opaque)
+static int test_ramblock_postcopiable(RAMBlock *rb, void *opaque)
{
- RAMBlock *rb = qemu_ram_block_by_name(block_name);
+ const char *block_name = qemu_ram_get_idstr(rb);
+ ram_addr_t length = qemu_ram_get_used_length(rb);
size_t pagesize = qemu_ram_pagesize(rb);
if (length % pagesize) {
@@ -374,7 +374,7 @@
}
/* We don't support postcopy with shared RAM yet */
- if (qemu_ram_foreach_migratable_block(test_ramblock_postcopiable, NULL)) {
+ if (foreach_not_ignored_block(test_ramblock_postcopiable, NULL)) {
goto out;
}
@@ -443,9 +443,12 @@
* must be done right at the start prior to pre-copy.
* opaque should be the MIS.
*/
-static int init_range(const char *block_name, void *host_addr,
- ram_addr_t offset, ram_addr_t length, void *opaque)
+static int init_range(RAMBlock *rb, void *opaque)
{
+ const char *block_name = qemu_ram_get_idstr(rb);
+ void *host_addr = qemu_ram_get_host_addr(rb);
+ ram_addr_t offset = qemu_ram_get_offset(rb);
+ ram_addr_t length = qemu_ram_get_used_length(rb);
trace_postcopy_init_range(block_name, host_addr, offset, length);
/*
@@ -465,9 +468,12 @@
* At the end of migration, undo the effects of init_range
* opaque should be the MIS.
*/
-static int cleanup_range(const char *block_name, void *host_addr,
- ram_addr_t offset, ram_addr_t length, void *opaque)
+static int cleanup_range(RAMBlock *rb, void *opaque)
{
+ const char *block_name = qemu_ram_get_idstr(rb);
+ void *host_addr = qemu_ram_get_host_addr(rb);
+ ram_addr_t offset = qemu_ram_get_offset(rb);
+ ram_addr_t length = qemu_ram_get_used_length(rb);
MigrationIncomingState *mis = opaque;
struct uffdio_range range_struct;
trace_postcopy_cleanup_range(block_name, host_addr, offset, length);
@@ -502,7 +508,7 @@
*/
int postcopy_ram_incoming_init(MigrationIncomingState *mis)
{
- if (qemu_ram_foreach_migratable_block(init_range, NULL)) {
+ if (foreach_not_ignored_block(init_range, NULL)) {
return -1;
}
@@ -544,7 +550,7 @@
return -1;
}
- if (qemu_ram_foreach_migratable_block(cleanup_range, mis)) {
+ if (foreach_not_ignored_block(cleanup_range, mis)) {
return -1;
}
@@ -586,9 +592,12 @@
/*
* Disable huge pages on an area
*/
-static int nhp_range(const char *block_name, void *host_addr,
- ram_addr_t offset, ram_addr_t length, void *opaque)
+static int nhp_range(RAMBlock *rb, void *opaque)
{
+ const char *block_name = qemu_ram_get_idstr(rb);
+ void *host_addr = qemu_ram_get_host_addr(rb);
+ ram_addr_t offset = qemu_ram_get_offset(rb);
+ ram_addr_t length = qemu_ram_get_used_length(rb);
trace_postcopy_nhp_range(block_name, host_addr, offset, length);
/*
@@ -608,7 +617,7 @@
*/
int postcopy_ram_prepare_discard(MigrationIncomingState *mis)
{
- if (qemu_ram_foreach_migratable_block(nhp_range, mis)) {
+ if (foreach_not_ignored_block(nhp_range, mis)) {
return -1;
}
@@ -619,22 +628,20 @@
/*
* Mark the given area of RAM as requiring notification to unwritten areas
- * Used as a callback on qemu_ram_foreach_migratable_block.
+ * Used as a callback on foreach_not_ignored_block.
* host_addr: Base of area to mark
* offset: Offset in the whole ram arena
* length: Length of the section
* opaque: MigrationIncomingState pointer
* Returns 0 on success
*/
-static int ram_block_enable_notify(const char *block_name, void *host_addr,
- ram_addr_t offset, ram_addr_t length,
- void *opaque)
+static int ram_block_enable_notify(RAMBlock *rb, void *opaque)
{
MigrationIncomingState *mis = opaque;
struct uffdio_register reg_struct;
- reg_struct.range.start = (uintptr_t)host_addr;
- reg_struct.range.len = length;
+ reg_struct.range.start = (uintptr_t)qemu_ram_get_host_addr(rb);
+ reg_struct.range.len = qemu_ram_get_used_length(rb);
reg_struct.mode = UFFDIO_REGISTER_MODE_MISSING;
/* Now tell our userfault_fd that it's responsible for this area */
@@ -647,7 +654,6 @@
return -1;
}
if (reg_struct.ioctls & ((__u64)1 << _UFFDIO_ZEROPAGE)) {
- RAMBlock *rb = qemu_ram_block_by_name(block_name);
qemu_ram_set_uf_zeroable(rb);
}
@@ -1116,7 +1122,7 @@
mis->have_fault_thread = true;
/* Mark so that we get notified of accesses to unwritten areas */
- if (qemu_ram_foreach_migratable_block(ram_block_enable_notify, mis)) {
+ if (foreach_not_ignored_block(ram_block_enable_notify, mis)) {
error_report("ram_block_enable_notify failed");
return -1;
}
diff --git a/migration/ram.c b/migration/ram.c
index 59191c1..35bd621 100644
--- a/migration/ram.c
+++ b/migration/ram.c
@@ -159,18 +159,44 @@
return ret;
}
+static bool ramblock_is_ignored(RAMBlock *block)
+{
+ return !qemu_ram_is_migratable(block) ||
+ (migrate_ignore_shared() && qemu_ram_is_shared(block));
+}
+
/* Should be holding either ram_list.mutex, or the RCU lock. */
+#define RAMBLOCK_FOREACH_NOT_IGNORED(block) \
+ INTERNAL_RAMBLOCK_FOREACH(block) \
+ if (ramblock_is_ignored(block)) {} else
+
#define RAMBLOCK_FOREACH_MIGRATABLE(block) \
INTERNAL_RAMBLOCK_FOREACH(block) \
if (!qemu_ram_is_migratable(block)) {} else
#undef RAMBLOCK_FOREACH
+int foreach_not_ignored_block(RAMBlockIterFunc func, void *opaque)
+{
+ RAMBlock *block;
+ int ret = 0;
+
+ rcu_read_lock();
+ RAMBLOCK_FOREACH_NOT_IGNORED(block) {
+ ret = func(block, opaque);
+ if (ret) {
+ break;
+ }
+ }
+ rcu_read_unlock();
+ return ret;
+}
+
static void ramblock_recv_map_init(void)
{
RAMBlock *rb;
- RAMBLOCK_FOREACH_MIGRATABLE(rb) {
+ RAMBLOCK_FOREACH_NOT_IGNORED(rb) {
assert(!rb->receivedmap);
rb->receivedmap = bitmap_new(rb->max_length >> qemu_target_page_bits());
}
@@ -290,6 +316,8 @@
uint32_t last_version;
/* We are in the first round */
bool ram_bulk_stage;
+ /* The free page optimization is enabled */
+ bool fpo_enabled;
/* How many times we have dirty too many pages */
int dirty_rate_high_cnt;
/* these variables are used for bitmap sync */
@@ -316,7 +344,7 @@
uint64_t target_page_count;
/* number of dirty bits in the bitmap */
uint64_t migration_dirty_pages;
- /* protects modification of the bitmap */
+ /* Protects modification of the bitmap and migration dirty pages */
QemuMutex bitmap_mutex;
/* The RAMBlock used in the last src_page_requests */
RAMBlock *last_req_rb;
@@ -328,6 +356,41 @@
static RAMState *ram_state;
+static NotifierWithReturnList precopy_notifier_list;
+
+void precopy_infrastructure_init(void)
+{
+ notifier_with_return_list_init(&precopy_notifier_list);
+}
+
+void precopy_add_notifier(NotifierWithReturn *n)
+{
+ notifier_with_return_list_add(&precopy_notifier_list, n);
+}
+
+void precopy_remove_notifier(NotifierWithReturn *n)
+{
+ notifier_with_return_remove(n);
+}
+
+int precopy_notify(PrecopyNotifyReason reason, Error **errp)
+{
+ PrecopyNotifyData pnd;
+ pnd.reason = reason;
+ pnd.errp = errp;
+
+ return notifier_with_return_list_notify(&precopy_notifier_list, &pnd);
+}
+
+void precopy_enable_free_page_optimization(void)
+{
+ if (!ram_state) {
+ return;
+ }
+
+ ram_state->fpo_enabled = true;
+}
+
uint64_t ram_bytes_remaining(void)
{
return ram_state ? (ram_state->migration_dirty_pages * TARGET_PAGE_SIZE) :
@@ -1545,11 +1608,15 @@
unsigned long *bitmap = rb->bmap;
unsigned long next;
- if (!qemu_ram_is_migratable(rb)) {
+ if (ramblock_is_ignored(rb)) {
return size;
}
- if (rs->ram_bulk_stage && start > 0) {
+ /*
+ * When the free page optimization is enabled, we need to check the bitmap
+ * to send the non-free pages rather than all the pages in the bulk stage.
+ */
+ if (!rs->fpo_enabled && rs->ram_bulk_stage && start > 0) {
next = start + 1;
} else {
next = find_next_bit(bitmap, size, start);
@@ -1564,11 +1631,14 @@
{
bool ret;
+ qemu_mutex_lock(&rs->bitmap_mutex);
ret = test_and_clear_bit(page, rb->bmap);
if (ret) {
rs->migration_dirty_pages--;
}
+ qemu_mutex_unlock(&rs->bitmap_mutex);
+
return ret;
}
@@ -1594,7 +1664,7 @@
RAMBlock *block;
uint64_t summary = 0;
- RAMBLOCK_FOREACH_MIGRATABLE(block) {
+ RAMBLOCK_FOREACH_NOT_IGNORED(block) {
summary |= block->page_size;
}
@@ -1664,7 +1734,7 @@
qemu_mutex_lock(&rs->bitmap_mutex);
rcu_read_lock();
- RAMBLOCK_FOREACH_MIGRATABLE(block) {
+ RAMBLOCK_FOREACH_NOT_IGNORED(block) {
migration_bitmap_sync_range(rs, block, 0, block->used_length);
}
ram_counters.remaining = ram_bytes_remaining();
@@ -1712,6 +1782,25 @@
}
}
+static void migration_bitmap_sync_precopy(RAMState *rs)
+{
+ Error *local_err = NULL;
+
+ /*
+ * The current notifier usage is just an optimization to migration, so we
+ * don't stop the normal migration process in the error case.
+ */
+ if (precopy_notify(PRECOPY_NOTIFY_BEFORE_BITMAP_SYNC, &local_err)) {
+ error_report_err(local_err);
+ }
+
+ migration_bitmap_sync(rs);
+
+ if (precopy_notify(PRECOPY_NOTIFY_AFTER_BITMAP_SYNC, &local_err)) {
+ error_report_err(local_err);
+ }
+}
+
/**
* save_zero_page_to_file: send the zero page to the file
*
@@ -2388,7 +2477,7 @@
size_t pagesize_bits =
qemu_ram_pagesize(pss->block) >> TARGET_PAGE_BITS;
- if (!qemu_ram_is_migratable(pss->block)) {
+ if (ramblock_is_ignored(pss->block)) {
error_report("block %s should not be migrated !", pss->block->idstr);
return 0;
}
@@ -2486,19 +2575,30 @@
}
}
-uint64_t ram_bytes_total(void)
+static uint64_t ram_bytes_total_common(bool count_ignored)
{
RAMBlock *block;
uint64_t total = 0;
rcu_read_lock();
- RAMBLOCK_FOREACH_MIGRATABLE(block) {
- total += block->used_length;
+ if (count_ignored) {
+ RAMBLOCK_FOREACH_MIGRATABLE(block) {
+ total += block->used_length;
+ }
+ } else {
+ RAMBLOCK_FOREACH_NOT_IGNORED(block) {
+ total += block->used_length;
+ }
}
rcu_read_unlock();
return total;
}
+uint64_t ram_bytes_total(void)
+{
+ return ram_bytes_total_common(false);
+}
+
static void xbzrle_load_setup(void)
{
XBZRLE.decoded_buf = g_malloc(TARGET_PAGE_SIZE);
@@ -2547,7 +2647,7 @@
*/
memory_global_dirty_log_stop();
- RAMBLOCK_FOREACH_MIGRATABLE(block) {
+ RAMBLOCK_FOREACH_NOT_IGNORED(block) {
g_free(block->bmap);
block->bmap = NULL;
g_free(block->unsentmap);
@@ -2566,6 +2666,7 @@
rs->last_page = 0;
rs->last_version = ram_list.version;
rs->ram_bulk_stage = true;
+ rs->fpo_enabled = false;
}
#define MAX_WAIT 50 /* ms, half buffered_file limit */
@@ -2610,7 +2711,7 @@
{
struct RAMBlock *block;
- RAMBLOCK_FOREACH_MIGRATABLE(block) {
+ RAMBLOCK_FOREACH_NOT_IGNORED(block) {
unsigned long *bitmap = block->bmap;
unsigned long range = block->used_length >> TARGET_PAGE_BITS;
unsigned long run_start = find_next_zero_bit(bitmap, range, 0);
@@ -2688,7 +2789,7 @@
struct RAMBlock *block;
int ret;
- RAMBLOCK_FOREACH_MIGRATABLE(block) {
+ RAMBLOCK_FOREACH_NOT_IGNORED(block) {
PostcopyDiscardState *pds =
postcopy_discard_send_init(ms, block->idstr);
@@ -2896,7 +2997,7 @@
rs->last_sent_block = NULL;
rs->last_page = 0;
- RAMBLOCK_FOREACH_MIGRATABLE(block) {
+ RAMBLOCK_FOREACH_NOT_IGNORED(block) {
unsigned long pages = block->used_length >> TARGET_PAGE_BITS;
unsigned long *bitmap = block->bmap;
unsigned long *unsentmap = block->unsentmap;
@@ -3062,7 +3163,7 @@
/* Skip setting bitmap if there is no RAM */
if (ram_bytes_total()) {
- RAMBLOCK_FOREACH_MIGRATABLE(block) {
+ RAMBLOCK_FOREACH_NOT_IGNORED(block) {
pages = block->max_length >> TARGET_PAGE_BITS;
block->bmap = bitmap_new(pages);
bitmap_set(block->bmap, 0, pages);
@@ -3083,7 +3184,7 @@
ram_list_init_bitmaps();
memory_global_dirty_log_start();
- migration_bitmap_sync(rs);
+ migration_bitmap_sync_precopy(rs);
rcu_read_unlock();
qemu_mutex_unlock_ramlist();
@@ -3117,7 +3218,7 @@
* about dirty page logging as well.
*/
- RAMBLOCK_FOREACH_MIGRATABLE(block) {
+ RAMBLOCK_FOREACH_NOT_IGNORED(block) {
pages += bitmap_count_one(block->bmap,
block->used_length >> TARGET_PAGE_BITS);
}
@@ -3142,6 +3243,53 @@
}
/*
+ * This function clears bits of the free pages reported by the caller from the
+ * migration dirty bitmap. @addr is the host address corresponding to the
+ * start of the continuous guest free pages, and @len is the total bytes of
+ * those pages.
+ */
+void qemu_guest_free_page_hint(void *addr, size_t len)
+{
+ RAMBlock *block;
+ ram_addr_t offset;
+ size_t used_len, start, npages;
+ MigrationState *s = migrate_get_current();
+
+ /* This function is currently expected to be used during live migration */
+ if (!migration_is_setup_or_active(s->state)) {
+ return;
+ }
+
+ for (; len > 0; len -= used_len, addr += used_len) {
+ block = qemu_ram_block_from_host(addr, false, &offset);
+ if (unlikely(!block || offset >= block->used_length)) {
+ /*
+ * The implementation might not support RAMBlock resize during
+ * live migration, but it could happen in theory with future
+ * updates. So we add a check here to capture that case.
+ */
+ error_report_once("%s unexpected error", __func__);
+ return;
+ }
+
+ if (len <= block->used_length - offset) {
+ used_len = len;
+ } else {
+ used_len = block->used_length - offset;
+ }
+
+ start = offset >> TARGET_PAGE_BITS;
+ npages = used_len >> TARGET_PAGE_BITS;
+
+ qemu_mutex_lock(&ram_state->bitmap_mutex);
+ ram_state->migration_dirty_pages -=
+ bitmap_count_one_with_offset(block->bmap, start, npages);
+ bitmap_clear(block->bmap, start, npages);
+ qemu_mutex_unlock(&ram_state->bitmap_mutex);
+ }
+}
+
+/*
* Each of ram_save_setup, ram_save_iterate and ram_save_complete has
* long-running RCU critical section. When rcu-reclaims in the code
* start to become numerous it will be necessary to reduce the
@@ -3176,7 +3324,7 @@
rcu_read_lock();
- qemu_put_be64(f, ram_bytes_total() | RAM_SAVE_FLAG_MEM_SIZE);
+ qemu_put_be64(f, ram_bytes_total_common(true) | RAM_SAVE_FLAG_MEM_SIZE);
RAMBLOCK_FOREACH_MIGRATABLE(block) {
qemu_put_byte(f, strlen(block->idstr));
@@ -3185,6 +3333,10 @@
if (migrate_postcopy_ram() && block->page_size != qemu_host_page_size) {
qemu_put_be64(f, block->page_size);
}
+ if (migrate_ignore_shared()) {
+ qemu_put_be64(f, block->mr->addr);
+ qemu_put_byte(f, ramblock_is_ignored(block) ? 1 : 0);
+ }
}
rcu_read_unlock();
@@ -3312,7 +3464,7 @@
rcu_read_lock();
if (!migration_in_postcopy()) {
- migration_bitmap_sync(rs);
+ migration_bitmap_sync_precopy(rs);
}
ram_control_before_iterate(f, RAM_CONTROL_FINISH);
@@ -3361,7 +3513,7 @@
remaining_size < max_size) {
qemu_mutex_lock_iothread();
rcu_read_lock();
- migration_bitmap_sync(rs);
+ migration_bitmap_sync_precopy(rs);
rcu_read_unlock();
qemu_mutex_unlock_iothread();
remaining_size = rs->migration_dirty_pages * TARGET_PAGE_SIZE;
@@ -3443,7 +3595,7 @@
return NULL;
}
- if (!qemu_ram_is_migratable(block)) {
+ if (ramblock_is_ignored(block)) {
error_report("block %s should not be migrated !", id);
return NULL;
}
@@ -3698,7 +3850,7 @@
RAMBlock *block;
rcu_read_lock();
- RAMBLOCK_FOREACH_MIGRATABLE(block) {
+ RAMBLOCK_FOREACH_NOT_IGNORED(block) {
block->colo_cache = qemu_anon_ram_alloc(block->used_length,
NULL,
false);
@@ -3719,7 +3871,7 @@
if (ram_bytes_total()) {
RAMBlock *block;
- RAMBLOCK_FOREACH_MIGRATABLE(block) {
+ RAMBLOCK_FOREACH_NOT_IGNORED(block) {
unsigned long pages = block->max_length >> TARGET_PAGE_BITS;
block->bmap = bitmap_new(pages);
@@ -3734,7 +3886,7 @@
out_locked:
- RAMBLOCK_FOREACH_MIGRATABLE(block) {
+ RAMBLOCK_FOREACH_NOT_IGNORED(block) {
if (block->colo_cache) {
qemu_anon_ram_free(block->colo_cache, block->used_length);
block->colo_cache = NULL;
@@ -3751,14 +3903,14 @@
RAMBlock *block;
memory_global_dirty_log_stop();
- RAMBLOCK_FOREACH_MIGRATABLE(block) {
+ RAMBLOCK_FOREACH_NOT_IGNORED(block) {
g_free(block->bmap);
block->bmap = NULL;
}
rcu_read_lock();
- RAMBLOCK_FOREACH_MIGRATABLE(block) {
+ RAMBLOCK_FOREACH_NOT_IGNORED(block) {
if (block->colo_cache) {
qemu_anon_ram_free(block->colo_cache, block->used_length);
block->colo_cache = NULL;
@@ -3794,7 +3946,7 @@
{
RAMBlock *rb;
- RAMBLOCK_FOREACH_MIGRATABLE(rb) {
+ RAMBLOCK_FOREACH_NOT_IGNORED(rb) {
if (ramblock_is_pmem(rb)) {
pmem_persist(rb->host, rb->used_length);
}
@@ -3803,7 +3955,7 @@
xbzrle_load_cleanup();
compress_threads_load_cleanup();
- RAMBLOCK_FOREACH_MIGRATABLE(rb) {
+ RAMBLOCK_FOREACH_NOT_IGNORED(rb) {
g_free(rb->receivedmap);
rb->receivedmap = NULL;
}
@@ -4003,7 +4155,7 @@
memory_global_dirty_log_sync();
rcu_read_lock();
- RAMBLOCK_FOREACH_MIGRATABLE(block) {
+ RAMBLOCK_FOREACH_NOT_IGNORED(block) {
migration_bitmap_sync_range(ram_state, block, 0, block->used_length);
}
rcu_read_unlock();
@@ -4146,6 +4298,23 @@
ret = -EINVAL;
}
}
+ if (migrate_ignore_shared()) {
+ hwaddr addr = qemu_get_be64(f);
+ bool ignored = qemu_get_byte(f);
+ if (ignored != ramblock_is_ignored(block)) {
+ error_report("RAM block %s should %s be migrated",
+ id, ignored ? "" : "not");
+ ret = -EINVAL;
+ }
+ if (ramblock_is_ignored(block) &&
+ block->mr->addr != addr) {
+ error_report("Mismatched GPAs for block %s "
+ "%" PRId64 "!= %" PRId64,
+ id, (uint64_t)addr,
+ (uint64_t)block->mr->addr);
+ ret = -EINVAL;
+ }
+ }
ram_control_load_hook(f, RAM_CONTROL_BLOCK_REG,
block->idstr);
} else {
@@ -4216,7 +4385,7 @@
static bool ram_has_postcopy(void *opaque)
{
RAMBlock *rb;
- RAMBLOCK_FOREACH_MIGRATABLE(rb) {
+ RAMBLOCK_FOREACH_NOT_IGNORED(rb) {
if (ramblock_is_pmem(rb)) {
info_report("Block: %s, host: %p is a nvdimm memory, postcopy"
"is not supported now!", rb->idstr, rb->host);
@@ -4236,7 +4405,7 @@
trace_ram_dirty_bitmap_sync_start();
- RAMBLOCK_FOREACH_MIGRATABLE(block) {
+ RAMBLOCK_FOREACH_NOT_IGNORED(block) {
qemu_savevm_send_recv_bitmap(file, block->idstr);
trace_ram_dirty_bitmap_request(block->idstr);
ramblock_count++;
diff --git a/migration/rdma.c b/migration/rdma.c
index 54a3c11..63c118a 100644
--- a/migration/rdma.c
+++ b/migration/rdma.c
@@ -624,9 +624,12 @@
* in advanced before the migration starts. This tells us where the RAM blocks
* are so that we can register them individually.
*/
-static int qemu_rdma_init_one_block(const char *block_name, void *host_addr,
- ram_addr_t block_offset, ram_addr_t length, void *opaque)
+static int qemu_rdma_init_one_block(RAMBlock *rb, void *opaque)
{
+ const char *block_name = qemu_ram_get_idstr(rb);
+ void *host_addr = qemu_ram_get_host_addr(rb);
+ ram_addr_t block_offset = qemu_ram_get_offset(rb);
+ ram_addr_t length = qemu_ram_get_used_length(rb);
return rdma_add_block(opaque, block_name, host_addr, block_offset, length);
}
@@ -641,7 +644,7 @@
assert(rdma->blockmap == NULL);
memset(local, 0, sizeof *local);
- qemu_ram_foreach_migratable_block(qemu_rdma_init_one_block, rdma);
+ foreach_not_ignored_block(qemu_rdma_init_one_block, rdma);
trace_qemu_rdma_init_ram_blocks(local->nb_blocks);
rdma->dest_blocks = g_new0(RDMADestBlock,
rdma->local_ram_blocks.nb_blocks);
@@ -2321,7 +2324,9 @@
rdma->connected = false;
}
- qemu_set_fd_handler(rdma->channel->fd, NULL, NULL, NULL);
+ if (rdma->channel) {
+ qemu_set_fd_handler(rdma->channel->fd, NULL, NULL, NULL);
+ }
g_free(rdma->dest_blocks);
rdma->dest_blocks = NULL;
@@ -3611,13 +3616,16 @@
}
chunk_start = ram_chunk_start(block, chunk);
chunk_end = ram_chunk_end(block, chunk + reg->chunks);
+ /* avoid "-Waddress-of-packed-member" warning */
+ uint32_t tmp_rkey = 0;
if (qemu_rdma_register_and_get_keys(rdma, block,
- (uintptr_t)host_addr, NULL, ®_result->rkey,
+ (uintptr_t)host_addr, NULL, &tmp_rkey,
chunk, chunk_start, chunk_end)) {
error_report("cannot get rkey");
ret = -EINVAL;
goto out;
}
+ reg_result->rkey = tmp_rkey;
reg_result->host_addr = (uintptr_t)block->local_host_addr;
diff --git a/migration/savevm.c b/migration/savevm.c
index 3226604..1415001 100644
--- a/migration/savevm.c
+++ b/migration/savevm.c
@@ -57,13 +57,8 @@
#include "sysemu/replay.h"
#include "qjson.h"
#include "migration/colo.h"
-
-#ifndef ETH_P_RARP
-#define ETH_P_RARP 0x8035
-#endif
-#define ARP_HTYPE_ETH 0x0001
-#define ARP_PTYPE_IP 0x0800
-#define ARP_OP_REQUEST_REV 0x3
+#include "qemu/bitmap.h"
+#include "net/announce.h"
const unsigned int postcopy_ram_discard_version = 0;
@@ -125,67 +120,6 @@
* generic extendable format with an exception for two old entities.
*/
-static int announce_self_create(uint8_t *buf,
- uint8_t *mac_addr)
-{
- /* Ethernet header. */
- memset(buf, 0xff, 6); /* destination MAC addr */
- memcpy(buf + 6, mac_addr, 6); /* source MAC addr */
- *(uint16_t *)(buf + 12) = htons(ETH_P_RARP); /* ethertype */
-
- /* RARP header. */
- *(uint16_t *)(buf + 14) = htons(ARP_HTYPE_ETH); /* hardware addr space */
- *(uint16_t *)(buf + 16) = htons(ARP_PTYPE_IP); /* protocol addr space */
- *(buf + 18) = 6; /* hardware addr length (ethernet) */
- *(buf + 19) = 4; /* protocol addr length (IPv4) */
- *(uint16_t *)(buf + 20) = htons(ARP_OP_REQUEST_REV); /* opcode */
- memcpy(buf + 22, mac_addr, 6); /* source hw addr */
- memset(buf + 28, 0x00, 4); /* source protocol addr */
- memcpy(buf + 32, mac_addr, 6); /* target hw addr */
- memset(buf + 38, 0x00, 4); /* target protocol addr */
-
- /* Padding to get up to 60 bytes (ethernet min packet size, minus FCS). */
- memset(buf + 42, 0x00, 18);
-
- return 60; /* len (FCS will be added by hardware) */
-}
-
-static void qemu_announce_self_iter(NICState *nic, void *opaque)
-{
- uint8_t buf[60];
- int len;
-
- trace_qemu_announce_self_iter(qemu_ether_ntoa(&nic->conf->macaddr));
- len = announce_self_create(buf, nic->conf->macaddr.a);
-
- qemu_send_packet_raw(qemu_get_queue(nic), buf, len);
-}
-
-
-static void qemu_announce_self_once(void *opaque)
-{
- static int count = SELF_ANNOUNCE_ROUNDS;
- QEMUTimer *timer = *(QEMUTimer **)opaque;
-
- qemu_foreach_nic(qemu_announce_self_iter, NULL);
-
- if (--count) {
- /* delay 50ms, 150ms, 250ms, ... */
- timer_mod(timer, qemu_clock_get_ms(QEMU_CLOCK_REALTIME) +
- self_announce_delay(count));
- } else {
- timer_del(timer);
- timer_free(timer);
- }
-}
-
-void qemu_announce_self(void)
-{
- static QEMUTimer *timer;
- timer = timer_new_ms(QEMU_CLOCK_REALTIME, qemu_announce_self_once, &timer);
- qemu_announce_self_once(&timer);
-}
-
/***********************************************************/
/* savevm/loadvm support */
@@ -316,6 +250,8 @@
uint32_t len;
const char *name;
uint32_t target_page_bits;
+ uint32_t caps_count;
+ MigrationCapability *capabilities;
} SaveState;
static SaveState savevm_state = {
@@ -323,15 +259,51 @@
.global_section_id = 0,
};
+static bool should_validate_capability(int capability)
+{
+ assert(capability >= 0 && capability < MIGRATION_CAPABILITY__MAX);
+ /* Validate only new capabilities to keep compatibility. */
+ switch (capability) {
+ case MIGRATION_CAPABILITY_X_IGNORE_SHARED:
+ return true;
+ default:
+ return false;
+ }
+}
+
+static uint32_t get_validatable_capabilities_count(void)
+{
+ MigrationState *s = migrate_get_current();
+ uint32_t result = 0;
+ int i;
+ for (i = 0; i < MIGRATION_CAPABILITY__MAX; i++) {
+ if (should_validate_capability(i) && s->enabled_capabilities[i]) {
+ result++;
+ }
+ }
+ return result;
+}
+
static int configuration_pre_save(void *opaque)
{
SaveState *state = opaque;
const char *current_name = MACHINE_GET_CLASS(current_machine)->name;
+ MigrationState *s = migrate_get_current();
+ int i, j;
state->len = strlen(current_name);
state->name = current_name;
state->target_page_bits = qemu_target_page_bits();
+ state->caps_count = get_validatable_capabilities_count();
+ state->capabilities = g_renew(MigrationCapability, state->capabilities,
+ state->caps_count);
+ for (i = j = 0; i < MIGRATION_CAPABILITY__MAX; i++) {
+ if (should_validate_capability(i) && s->enabled_capabilities[i]) {
+ state->capabilities[j++] = i;
+ }
+ }
+
return 0;
}
@@ -347,6 +319,40 @@
return 0;
}
+static bool configuration_validate_capabilities(SaveState *state)
+{
+ bool ret = true;
+ MigrationState *s = migrate_get_current();
+ unsigned long *source_caps_bm;
+ int i;
+
+ source_caps_bm = bitmap_new(MIGRATION_CAPABILITY__MAX);
+ for (i = 0; i < state->caps_count; i++) {
+ MigrationCapability capability = state->capabilities[i];
+ set_bit(capability, source_caps_bm);
+ }
+
+ for (i = 0; i < MIGRATION_CAPABILITY__MAX; i++) {
+ bool source_state, target_state;
+ if (!should_validate_capability(i)) {
+ continue;
+ }
+ source_state = test_bit(i, source_caps_bm);
+ target_state = s->enabled_capabilities[i];
+ if (source_state != target_state) {
+ error_report("Capability %s is %s, but received capability is %s",
+ MigrationCapability_str(i),
+ target_state ? "on" : "off",
+ source_state ? "on" : "off");
+ ret = false;
+ /* Don't break here to report all failed capabilities */
+ }
+ }
+
+ g_free(source_caps_bm);
+ return ret;
+}
+
static int configuration_post_load(void *opaque, int version_id)
{
SaveState *state = opaque;
@@ -364,9 +370,53 @@
return -EINVAL;
}
+ if (!configuration_validate_capabilities(state)) {
+ return -EINVAL;
+ }
+
return 0;
}
+static int get_capability(QEMUFile *f, void *pv, size_t size,
+ const VMStateField *field)
+{
+ MigrationCapability *capability = pv;
+ char capability_str[UINT8_MAX + 1];
+ uint8_t len;
+ int i;
+
+ len = qemu_get_byte(f);
+ qemu_get_buffer(f, (uint8_t *)capability_str, len);
+ capability_str[len] = '\0';
+ for (i = 0; i < MIGRATION_CAPABILITY__MAX; i++) {
+ if (!strcmp(MigrationCapability_str(i), capability_str)) {
+ *capability = i;
+ return 0;
+ }
+ }
+ error_report("Received unknown capability %s", capability_str);
+ return -EINVAL;
+}
+
+static int put_capability(QEMUFile *f, void *pv, size_t size,
+ const VMStateField *field, QJSON *vmdesc)
+{
+ MigrationCapability *capability = pv;
+ const char *capability_str = MigrationCapability_str(*capability);
+ size_t len = strlen(capability_str);
+ assert(len <= UINT8_MAX);
+
+ qemu_put_byte(f, len);
+ qemu_put_buffer(f, (uint8_t *)capability_str, len);
+ return 0;
+}
+
+static const VMStateInfo vmstate_info_capability = {
+ .name = "capability",
+ .get = get_capability,
+ .put = put_capability,
+};
+
/* The target-page-bits subsection is present only if the
* target page size is not the same as the default (ie the
* minimum page size for a variable-page-size guest CPU).
@@ -391,6 +441,25 @@
}
};
+static bool vmstate_capabilites_needed(void *opaque)
+{
+ return get_validatable_capabilities_count() > 0;
+}
+
+static const VMStateDescription vmstate_capabilites = {
+ .name = "configuration/capabilities",
+ .version_id = 1,
+ .minimum_version_id = 1,
+ .needed = vmstate_capabilites_needed,
+ .fields = (VMStateField[]) {
+ VMSTATE_UINT32_V(caps_count, SaveState, 1),
+ VMSTATE_VARRAY_UINT32_ALLOC(capabilities, SaveState, caps_count, 1,
+ vmstate_info_capability,
+ MigrationCapability),
+ VMSTATE_END_OF_LIST()
+ }
+};
+
static const VMStateDescription vmstate_configuration = {
.name = "configuration",
.version_id = 1,
@@ -404,6 +473,7 @@
},
.subsections = (const VMStateDescription*[]) {
&vmstate_target_page_bits,
+ &vmstate_capabilites,
NULL
}
};
@@ -1018,6 +1088,7 @@
void qemu_savevm_state_setup(QEMUFile *f)
{
SaveStateEntry *se;
+ Error *local_err = NULL;
int ret;
trace_savevm_state_setup();
@@ -1039,6 +1110,10 @@
break;
}
}
+
+ if (precopy_notify(PRECOPY_NOTIFY_SETUP, &local_err)) {
+ error_report_err(local_err);
+ }
}
int qemu_savevm_state_resume_prepare(MigrationState *s)
@@ -1181,6 +1256,11 @@
SaveStateEntry *se;
int ret;
bool in_postcopy = migration_in_postcopy();
+ Error *local_err = NULL;
+
+ if (precopy_notify(PRECOPY_NOTIFY_COMPLETE, &local_err)) {
+ error_report_err(local_err);
+ }
trace_savevm_state_complete_precopy();
@@ -1313,6 +1393,11 @@
void qemu_savevm_state_cleanup(void)
{
SaveStateEntry *se;
+ Error *local_err = NULL;
+
+ if (precopy_notify(PRECOPY_NOTIFY_CLEANUP, &local_err)) {
+ error_report_err(local_err);
+ }
trace_savevm_state_cleanup();
QTAILQ_FOREACH(se, &savevm_state.handlers, entry) {
@@ -1765,13 +1850,14 @@
{
Error *local_err = NULL;
HandleRunBhData *data = opaque;
+ MigrationIncomingState *mis = migration_incoming_get_current();
/* TODO we should move all of this lot into postcopy_ram.c or a shared code
* in migration.c
*/
cpu_synchronize_all_post_init();
- qemu_announce_self();
+ qemu_announce_self(&mis->announce_timer, migrate_announce_params());
/* Make sure all file formats flush their mutable metadata.
* If we get an error here, just don't restart the VM yet. */
diff --git a/migration/socket.c b/migration/socket.c
index f4c8174..239527f 100644
--- a/migration/socket.c
+++ b/migration/socket.c
@@ -15,6 +15,7 @@
*/
#include "qemu/osdep.h"
+#include "qemu/cutils.h"
#include "qemu-common.h"
#include "qemu/error-report.h"
@@ -177,6 +178,7 @@
Error **errp)
{
QIONetListener *listener = qio_net_listener_new();
+ size_t i;
qio_net_listener_set_name(listener, "migration-socket-listener");
@@ -189,6 +191,15 @@
socket_accept_incoming_migration,
NULL, NULL,
g_main_context_get_thread_default());
+
+ for (i = 0; i < listener->nsioc; i++) {
+ SocketAddress *address =
+ qio_channel_socket_get_local_address(listener->sioc[i], errp);
+ if (!address) {
+ return;
+ }
+ migrate_add_address(address);
+ }
}
void tcp_start_incoming_migration(const char *host_port, Error **errp)
diff --git a/migration/trace-events b/migration/trace-events
index bd2d0cd..72e3fcb 100644
--- a/migration/trace-events
+++ b/migration/trace-events
@@ -52,7 +52,6 @@
vmstate_subsection_save_loop(const char *name, const char *sub) "%s/%s"
vmstate_subsection_save_top(const char *idstr) "%s"
vmstate_load(const char *idstr, const char *vmsd_name) "%s, %s"
-qemu_announce_self_iter(const char *mac) "%s"
# migration/vmstate.c
vmstate_load_field_error(const char *field, int ret) "field \"%s\" load failed, ret = %d"
diff --git a/monitor.c b/monitor.c
index 33ccbf3..defa129 100644
--- a/monitor.c
+++ b/monitor.c
@@ -51,7 +51,8 @@
#include "sysemu/balloon.h"
#include "qemu/timer.h"
#include "sysemu/hw_accel.h"
-#include "qemu/acl.h"
+#include "authz/list.h"
+#include "qapi/util.h"
#include "sysemu/tpm.h"
#include "qapi/qmp/qdict.h"
#include "qapi/qmp/qerror.h"
@@ -2016,93 +2017,148 @@
QLIST_INSERT_HEAD (&capture_head, s, entries);
}
-static qemu_acl *find_acl(Monitor *mon, const char *name)
+static QAuthZList *find_auth(Monitor *mon, const char *name)
{
- qemu_acl *acl = qemu_acl_find(name);
+ Object *obj;
+ Object *container;
- if (!acl) {
+ container = object_get_objects_root();
+ obj = object_resolve_path_component(container, name);
+ if (!obj) {
monitor_printf(mon, "acl: unknown list '%s'\n", name);
+ return NULL;
}
- return acl;
+
+ return QAUTHZ_LIST(obj);
}
static void hmp_acl_show(Monitor *mon, const QDict *qdict)
{
const char *aclname = qdict_get_str(qdict, "aclname");
- qemu_acl *acl = find_acl(mon, aclname);
- qemu_acl_entry *entry;
- int i = 0;
+ QAuthZList *auth = find_auth(mon, aclname);
+ QAuthZListRuleList *rules;
+ size_t i = 0;
- if (acl) {
- monitor_printf(mon, "policy: %s\n",
- acl->defaultDeny ? "deny" : "allow");
- QTAILQ_FOREACH(entry, &acl->entries, next) {
- i++;
- monitor_printf(mon, "%d: %s %s\n", i,
- entry->deny ? "deny" : "allow", entry->match);
- }
+ if (!auth) {
+ return;
+ }
+
+ monitor_printf(mon, "policy: %s\n",
+ QAuthZListPolicy_str(auth->policy));
+
+ rules = auth->rules;
+ while (rules) {
+ QAuthZListRule *rule = rules->value;
+ i++;
+ monitor_printf(mon, "%zu: %s %s\n", i,
+ QAuthZListPolicy_str(rule->policy),
+ rule->match);
+ rules = rules->next;
}
}
static void hmp_acl_reset(Monitor *mon, const QDict *qdict)
{
const char *aclname = qdict_get_str(qdict, "aclname");
- qemu_acl *acl = find_acl(mon, aclname);
+ QAuthZList *auth = find_auth(mon, aclname);
- if (acl) {
- qemu_acl_reset(acl);
- monitor_printf(mon, "acl: removed all rules\n");
+ if (!auth) {
+ return;
}
+
+ auth->policy = QAUTHZ_LIST_POLICY_DENY;
+ qapi_free_QAuthZListRuleList(auth->rules);
+ auth->rules = NULL;
+ monitor_printf(mon, "acl: removed all rules\n");
}
static void hmp_acl_policy(Monitor *mon, const QDict *qdict)
{
const char *aclname = qdict_get_str(qdict, "aclname");
const char *policy = qdict_get_str(qdict, "policy");
- qemu_acl *acl = find_acl(mon, aclname);
+ QAuthZList *auth = find_auth(mon, aclname);
+ int val;
+ Error *err = NULL;
- if (acl) {
- if (strcmp(policy, "allow") == 0) {
- acl->defaultDeny = 0;
+ if (!auth) {
+ return;
+ }
+
+ val = qapi_enum_parse(&QAuthZListPolicy_lookup,
+ policy,
+ QAUTHZ_LIST_POLICY_DENY,
+ &err);
+ if (err) {
+ error_free(err);
+ monitor_printf(mon, "acl: unknown policy '%s', "
+ "expected 'deny' or 'allow'\n", policy);
+ } else {
+ auth->policy = val;
+ if (auth->policy == QAUTHZ_LIST_POLICY_ALLOW) {
monitor_printf(mon, "acl: policy set to 'allow'\n");
- } else if (strcmp(policy, "deny") == 0) {
- acl->defaultDeny = 1;
- monitor_printf(mon, "acl: policy set to 'deny'\n");
} else {
- monitor_printf(mon, "acl: unknown policy '%s', "
- "expected 'deny' or 'allow'\n", policy);
+ monitor_printf(mon, "acl: policy set to 'deny'\n");
}
}
}
+static QAuthZListFormat hmp_acl_get_format(const char *match)
+{
+ if (strchr(match, '*')) {
+ return QAUTHZ_LIST_FORMAT_GLOB;
+ } else {
+ return QAUTHZ_LIST_FORMAT_EXACT;
+ }
+}
+
static void hmp_acl_add(Monitor *mon, const QDict *qdict)
{
const char *aclname = qdict_get_str(qdict, "aclname");
const char *match = qdict_get_str(qdict, "match");
- const char *policy = qdict_get_str(qdict, "policy");
+ const char *policystr = qdict_get_str(qdict, "policy");
int has_index = qdict_haskey(qdict, "index");
int index = qdict_get_try_int(qdict, "index", -1);
- qemu_acl *acl = find_acl(mon, aclname);
- int deny, ret;
+ QAuthZList *auth = find_auth(mon, aclname);
+ Error *err = NULL;
+ QAuthZListPolicy policy;
+ QAuthZListFormat format;
+ size_t i = 0;
- if (acl) {
- if (strcmp(policy, "allow") == 0) {
- deny = 0;
- } else if (strcmp(policy, "deny") == 0) {
- deny = 1;
- } else {
- monitor_printf(mon, "acl: unknown policy '%s', "
- "expected 'deny' or 'allow'\n", policy);
- return;
- }
- if (has_index)
- ret = qemu_acl_insert(acl, deny, match, index);
- else
- ret = qemu_acl_append(acl, deny, match);
- if (ret < 0)
- monitor_printf(mon, "acl: unable to add acl entry\n");
- else
- monitor_printf(mon, "acl: added rule at position %d\n", ret);
+ if (!auth) {
+ return;
+ }
+
+ policy = qapi_enum_parse(&QAuthZListPolicy_lookup,
+ policystr,
+ QAUTHZ_LIST_POLICY_DENY,
+ &err);
+ if (err) {
+ error_free(err);
+ monitor_printf(mon, "acl: unknown policy '%s', "
+ "expected 'deny' or 'allow'\n", policystr);
+ return;
+ }
+
+ format = hmp_acl_get_format(match);
+
+ if (has_index && index == 0) {
+ monitor_printf(mon, "acl: unable to add acl entry\n");
+ return;
+ }
+
+ if (has_index) {
+ i = qauthz_list_insert_rule(auth, match, policy,
+ format, index - 1, &err);
+ } else {
+ i = qauthz_list_append_rule(auth, match, policy,
+ format, &err);
+ }
+ if (err) {
+ monitor_printf(mon, "acl: unable to add rule: %s",
+ error_get_pretty(err));
+ error_free(err);
+ } else {
+ monitor_printf(mon, "acl: added rule at position %zu\n", i + 1);
}
}
@@ -2110,15 +2166,18 @@
{
const char *aclname = qdict_get_str(qdict, "aclname");
const char *match = qdict_get_str(qdict, "match");
- qemu_acl *acl = find_acl(mon, aclname);
- int ret;
+ QAuthZList *auth = find_auth(mon, aclname);
+ ssize_t i = 0;
- if (acl) {
- ret = qemu_acl_remove(acl, match);
- if (ret < 0)
- monitor_printf(mon, "acl: no matching acl entry\n");
- else
- monitor_printf(mon, "acl: removed rule at position %d\n", ret);
+ if (!auth) {
+ return;
+ }
+
+ i = qauthz_list_delete_rule(auth, match);
+ if (i >= 0) {
+ monitor_printf(mon, "acl: removed rule at position %zu\n", i + 1);
+ } else {
+ monitor_printf(mon, "acl: no matching acl entry\n");
}
}
diff --git a/nbd/client.c b/nbd/client.c
index 10a52ad..de7da48 100644
--- a/nbd/client.c
+++ b/nbd/client.c
@@ -1387,17 +1387,65 @@
return 0;
}
-/* nbd_receive_reply
+/* nbd_read_eof
+ * Tries to read @size bytes from @ioc.
* Returns 1 on success
* 0 on eof, when no data was read (errp is not set)
* negative errno on failure (errp is set)
*/
-int nbd_receive_reply(QIOChannel *ioc, NBDReply *reply, Error **errp)
+static inline int coroutine_fn
+nbd_read_eof(BlockDriverState *bs, QIOChannel *ioc, void *buffer, size_t size,
+ Error **errp)
+{
+ bool partial = false;
+
+ assert(size);
+ while (size > 0) {
+ struct iovec iov = { .iov_base = buffer, .iov_len = size };
+ ssize_t len;
+
+ len = qio_channel_readv(ioc, &iov, 1, errp);
+ if (len == QIO_CHANNEL_ERR_BLOCK) {
+ bdrv_dec_in_flight(bs);
+ qio_channel_yield(ioc, G_IO_IN);
+ bdrv_inc_in_flight(bs);
+ continue;
+ } else if (len < 0) {
+ return -EIO;
+ } else if (len == 0) {
+ if (partial) {
+ error_setg(errp,
+ "Unexpected end-of-file before all bytes were read");
+ return -EIO;
+ } else {
+ return 0;
+ }
+ }
+
+ partial = true;
+ size -= len;
+ buffer = (uint8_t*) buffer + len;
+ }
+ return 1;
+}
+
+/* nbd_receive_reply
+ *
+ * Decreases bs->in_flight while waiting for a new reply. This yield is where
+ * we wait indefinitely and the coroutine must be able to be safely reentered
+ * for nbd_client_attach_aio_context().
+ *
+ * Returns 1 on success
+ * 0 on eof, when no data was read (errp is not set)
+ * negative errno on failure (errp is set)
+ */
+int coroutine_fn nbd_receive_reply(BlockDriverState *bs, QIOChannel *ioc,
+ NBDReply *reply, Error **errp)
{
int ret;
const char *type;
- ret = nbd_read_eof(ioc, &reply->magic, sizeof(reply->magic), errp);
+ ret = nbd_read_eof(bs, ioc, &reply->magic, sizeof(reply->magic), errp);
if (ret <= 0) {
return ret;
}
diff --git a/nbd/nbd-internal.h b/nbd/nbd-internal.h
index 82aa221..049f83d 100644
--- a/nbd/nbd-internal.h
+++ b/nbd/nbd-internal.h
@@ -64,25 +64,6 @@
#define NBD_SET_TIMEOUT _IO(0xab, 9)
#define NBD_SET_FLAGS _IO(0xab, 10)
-/* nbd_read_eof
- * Tries to read @size bytes from @ioc.
- * Returns 1 on success
- * 0 on eof, when no data was read (errp is not set)
- * negative errno on failure (errp is set)
- */
-static inline int nbd_read_eof(QIOChannel *ioc, void *buffer, size_t size,
- Error **errp)
-{
- int ret;
-
- assert(size);
- ret = qio_channel_read_all_eof(ioc, buffer, size, errp);
- if (ret < 0) {
- ret = -EIO;
- }
- return ret;
-}
-
/* nbd_write
* Writes @size bytes to @ioc. Returns 0 on success.
*/
diff --git a/net/Makefile.objs b/net/Makefile.objs
index b2bf88a..8262f03 100644
--- a/net/Makefile.objs
+++ b/net/Makefile.objs
@@ -2,8 +2,11 @@
common-obj-y += socket.o
common-obj-y += dump.o
common-obj-y += eth.o
+common-obj-y += announce.o
common-obj-$(CONFIG_L2TPV3) += l2tpv3.o
-common-obj-$(CONFIG_POSIX) += vhost-user.o
+common-obj-$(call land,$(CONFIG_VIRTIO_NET),$(CONFIG_VHOST_NET_USER)) += vhost-user.o
+common-obj-$(call land,$(call lnot,$(CONFIG_VIRTIO_NET)),$(CONFIG_VHOST_NET_USER)) += vhost-user-stub.o
+common-obj-$(CONFIG_ALL) += vhost-user-stub.o
common-obj-$(CONFIG_SLIRP) += slirp.o
common-obj-$(CONFIG_VDE) += vde.o
common-obj-$(CONFIG_NETMAP) += netmap.o
diff --git a/net/announce.c b/net/announce.c
new file mode 100644
index 0000000..91e9a6e
--- /dev/null
+++ b/net/announce.c
@@ -0,0 +1,140 @@
+/*
+ * Self-announce
+ * (c) 2017-2019 Red Hat, Inc.
+ *
+ * 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 "net/announce.h"
+#include "net/net.h"
+#include "qapi/clone-visitor.h"
+#include "qapi/qapi-visit-net.h"
+#include "qapi/qapi-commands-net.h"
+#include "trace.h"
+
+int64_t qemu_announce_timer_step(AnnounceTimer *timer)
+{
+ int64_t step;
+
+ step = timer->params.initial +
+ (timer->params.rounds - timer->round - 1) *
+ timer->params.step;
+
+ if (step < 0 || step > timer->params.max) {
+ step = timer->params.max;
+ }
+ timer_mod(timer->tm, qemu_clock_get_ms(timer->type) + step);
+
+ return step;
+}
+
+void qemu_announce_timer_del(AnnounceTimer *timer)
+{
+ if (timer->tm) {
+ timer_del(timer->tm);
+ timer_free(timer->tm);
+ timer->tm = NULL;
+ }
+}
+
+/*
+ * Under BQL/main thread
+ * Reset the timer to the given parameters/type/notifier.
+ */
+void qemu_announce_timer_reset(AnnounceTimer *timer,
+ AnnounceParameters *params,
+ QEMUClockType type,
+ QEMUTimerCB *cb,
+ void *opaque)
+{
+ /*
+ * We're under the BQL, so the current timer can't
+ * be firing, so we should be able to delete it.
+ */
+ qemu_announce_timer_del(timer);
+
+ QAPI_CLONE_MEMBERS(AnnounceParameters, &timer->params, params);
+ timer->round = params->rounds;
+ timer->type = type;
+ timer->tm = timer_new_ms(type, cb, opaque);
+}
+
+#ifndef ETH_P_RARP
+#define ETH_P_RARP 0x8035
+#endif
+#define ARP_HTYPE_ETH 0x0001
+#define ARP_PTYPE_IP 0x0800
+#define ARP_OP_REQUEST_REV 0x3
+
+static int announce_self_create(uint8_t *buf,
+ uint8_t *mac_addr)
+{
+ /* Ethernet header. */
+ memset(buf, 0xff, 6); /* destination MAC addr */
+ memcpy(buf + 6, mac_addr, 6); /* source MAC addr */
+ *(uint16_t *)(buf + 12) = htons(ETH_P_RARP); /* ethertype */
+
+ /* RARP header. */
+ *(uint16_t *)(buf + 14) = htons(ARP_HTYPE_ETH); /* hardware addr space */
+ *(uint16_t *)(buf + 16) = htons(ARP_PTYPE_IP); /* protocol addr space */
+ *(buf + 18) = 6; /* hardware addr length (ethernet) */
+ *(buf + 19) = 4; /* protocol addr length (IPv4) */
+ *(uint16_t *)(buf + 20) = htons(ARP_OP_REQUEST_REV); /* opcode */
+ memcpy(buf + 22, mac_addr, 6); /* source hw addr */
+ memset(buf + 28, 0x00, 4); /* source protocol addr */
+ memcpy(buf + 32, mac_addr, 6); /* target hw addr */
+ memset(buf + 38, 0x00, 4); /* target protocol addr */
+
+ /* Padding to get up to 60 bytes (ethernet min packet size, minus FCS). */
+ memset(buf + 42, 0x00, 18);
+
+ return 60; /* len (FCS will be added by hardware) */
+}
+
+static void qemu_announce_self_iter(NICState *nic, void *opaque)
+{
+ uint8_t buf[60];
+ int len;
+
+ trace_qemu_announce_self_iter(qemu_ether_ntoa(&nic->conf->macaddr));
+ len = announce_self_create(buf, nic->conf->macaddr.a);
+
+ qemu_send_packet_raw(qemu_get_queue(nic), buf, len);
+
+ /* if the NIC provides it's own announcement support, use it as well */
+ if (nic->ncs->info->announce) {
+ nic->ncs->info->announce(nic->ncs);
+ }
+}
+static void qemu_announce_self_once(void *opaque)
+{
+ AnnounceTimer *timer = (AnnounceTimer *)opaque;
+
+ qemu_foreach_nic(qemu_announce_self_iter, NULL);
+
+ if (--timer->round) {
+ qemu_announce_timer_step(timer);
+ } else {
+ qemu_announce_timer_del(timer);
+ }
+}
+
+void qemu_announce_self(AnnounceTimer *timer, AnnounceParameters *params)
+{
+ qemu_announce_timer_reset(timer, params, QEMU_CLOCK_REALTIME,
+ qemu_announce_self_once, timer);
+ if (params->rounds) {
+ qemu_announce_self_once(timer);
+ } else {
+ qemu_announce_timer_del(timer);
+ }
+}
+
+void qmp_announce_self(AnnounceParameters *params, Error **errp)
+{
+ static AnnounceTimer announce_timer;
+ qemu_announce_self(&announce_timer, params);
+}
diff --git a/net/colo-compare.c b/net/colo-compare.c
index 3e515f3..bf10526 100644
--- a/net/colo-compare.c
+++ b/net/colo-compare.c
@@ -294,14 +294,6 @@
return true;
}
}
- if (ppkt->tcp_seq == spkt->tcp_seq && ppkt->seq_end == spkt->seq_end) {
- if (colo_compare_packet_payload(ppkt, spkt,
- ppkt->header_size, spkt->header_size,
- ppkt->payload_size)) {
- *mark = COLO_COMPARE_FREE_SECONDARY | COLO_COMPARE_FREE_PRIMARY;
- return true;
- }
- }
/* one part of secondary packet payload still need to be compared */
if (!after(ppkt->seq_end, spkt->seq_end)) {
diff --git a/net/net.c b/net/net.c
index 5dcff7f..f3a3c54 100644
--- a/net/net.c
+++ b/net/net.c
@@ -961,7 +961,7 @@
[NET_CLIENT_DRIVER_BRIDGE] = net_init_bridge,
#endif
[NET_CLIENT_DRIVER_HUBPORT] = net_init_hubport,
-#ifdef CONFIG_VHOST_NET_USED
+#ifdef CONFIG_VHOST_NET_USER
[NET_CLIENT_DRIVER_VHOST_USER] = net_init_vhost_user,
#endif
#ifdef CONFIG_L2TPV3
diff --git a/net/netmap.c b/net/netmap.c
index 2d11a8f..0cc8f54 100644
--- a/net/netmap.c
+++ b/net/netmap.c
@@ -154,65 +154,27 @@
qemu_flush_queued_packets(&s->nc);
}
-static ssize_t netmap_receive(NetClientState *nc,
- const uint8_t *buf, size_t size)
-{
- NetmapState *s = DO_UPCAST(NetmapState, nc, nc);
- struct netmap_ring *ring = s->tx;
- uint32_t i;
- uint32_t idx;
- uint8_t *dst;
-
- if (unlikely(!ring)) {
- /* Drop. */
- return size;
- }
-
- if (unlikely(size > ring->nr_buf_size)) {
- RD(5, "[netmap_receive] drop packet of size %d > %d\n",
- (int)size, ring->nr_buf_size);
- return size;
- }
-
- if (nm_ring_empty(ring)) {
- /* No available slots in the netmap TX ring. */
- netmap_write_poll(s, true);
- return 0;
- }
-
- i = ring->cur;
- idx = ring->slot[i].buf_idx;
- dst = (uint8_t *)NETMAP_BUF(ring, idx);
-
- ring->slot[i].len = size;
- ring->slot[i].flags = 0;
- pkt_copy(buf, dst, size);
- ring->cur = ring->head = nm_ring_next(ring, i);
- ioctl(s->nmd->fd, NIOCTXSYNC, NULL);
-
- return size;
-}
-
static ssize_t netmap_receive_iov(NetClientState *nc,
const struct iovec *iov, int iovcnt)
{
NetmapState *s = DO_UPCAST(NetmapState, nc, nc);
struct netmap_ring *ring = s->tx;
+ unsigned int tail = ring->tail;
+ ssize_t totlen = 0;
uint32_t last;
uint32_t idx;
uint8_t *dst;
int j;
uint32_t i;
- if (unlikely(!ring)) {
- /* Drop the packet. */
- return iov_size(iov, iovcnt);
- }
-
- last = i = ring->cur;
+ last = i = ring->head;
if (nm_ring_space(ring) < iovcnt) {
- /* Not enough netmap slots. */
+ /* Not enough netmap slots. Tell the kernel that we have seen the new
+ * available slots (so that it notifies us again when it has more
+ * ones), but without publishing any new slots to be processed
+ * (e.g., we don't advance ring->head). */
+ ring->cur = tail;
netmap_write_poll(s, true);
return 0;
}
@@ -222,14 +184,17 @@
int offset = 0;
int nm_frag_size;
+ totlen += iov_frag_size;
+
/* Split each iovec fragment over more netmap slots, if
necessary. */
while (iov_frag_size) {
nm_frag_size = MIN(iov_frag_size, ring->nr_buf_size);
- if (unlikely(nm_ring_empty(ring))) {
- /* We run out of netmap slots while splitting the
+ if (unlikely(i == tail)) {
+ /* We ran out of netmap slots while splitting the
iovec fragments. */
+ ring->cur = tail;
netmap_write_poll(s, true);
return 0;
}
@@ -251,12 +216,24 @@
/* The last slot must not have NS_MOREFRAG set. */
ring->slot[last].flags &= ~NS_MOREFRAG;
- /* Now update ring->cur and ring->head. */
- ring->cur = ring->head = i;
+ /* Now update ring->head and ring->cur to publish the new slots and
+ * the new wakeup point. */
+ ring->head = ring->cur = i;
ioctl(s->nmd->fd, NIOCTXSYNC, NULL);
- return iov_size(iov, iovcnt);
+ return totlen;
+}
+
+static ssize_t netmap_receive(NetClientState *nc,
+ const uint8_t *buf, size_t size)
+{
+ struct iovec iov;
+
+ iov.iov_base = (void *)buf;
+ iov.iov_len = size;
+
+ return netmap_receive_iov(nc, &iov, 1);
}
/* Complete a previous send (backend --> guest) and enable the
@@ -272,39 +249,46 @@
{
NetmapState *s = opaque;
struct netmap_ring *ring = s->rx;
+ unsigned int tail = ring->tail;
- /* Keep sending while there are available packets into the netmap
+ /* Keep sending while there are available slots in the netmap
RX ring and the forwarding path towards the peer is open. */
- while (!nm_ring_empty(ring)) {
- uint32_t i;
+ while (ring->head != tail) {
+ uint32_t i = ring->head;
uint32_t idx;
bool morefrag;
int iovcnt = 0;
int iovsize;
+ /* Get a (possibly multi-slot) packet. */
do {
- i = ring->cur;
idx = ring->slot[i].buf_idx;
morefrag = (ring->slot[i].flags & NS_MOREFRAG);
- s->iov[iovcnt].iov_base = (u_char *)NETMAP_BUF(ring, idx);
+ s->iov[iovcnt].iov_base = (void *)NETMAP_BUF(ring, idx);
s->iov[iovcnt].iov_len = ring->slot[i].len;
iovcnt++;
+ i = nm_ring_next(ring, i);
+ } while (i != tail && morefrag);
- ring->cur = ring->head = nm_ring_next(ring, i);
- } while (!nm_ring_empty(ring) && morefrag);
+ /* Advance ring->cur to tell the kernel that we have seen the slots. */
+ ring->cur = i;
- if (unlikely(nm_ring_empty(ring) && morefrag)) {
- RD(5, "[netmap_send] ran out of slots, with a pending"
- "incomplete packet\n");
+ if (unlikely(morefrag)) {
+ /* This is a truncated packet, so we can stop without releasing the
+ * incomplete slots by updating ring->head. We will hopefully
+ * re-read the complete packet the next time we are called. */
+ break;
}
iovsize = qemu_sendv_packet_async(&s->nc, s->iov, iovcnt,
netmap_send_completed);
+ /* Release the slots to the kernel. */
+ ring->head = i;
+
if (iovsize == 0) {
/* The peer does not receive anymore. Packet is queued, stop
- * reading from the backend until netmap_send_completed()
- */
+ * reading from the backend until netmap_send_completed(). */
netmap_read_poll(s, false);
break;
}
diff --git a/net/trace-events b/net/trace-events
index 7b594cf..3417ac0 100644
--- a/net/trace-events
+++ b/net/trace-events
@@ -1,5 +1,8 @@
# See docs/devel/tracing.txt for syntax documentation.
+# net/announce.c
+qemu_announce_self_iter(const char *mac) "%s"
+
# net/vhost-user.c
vhost_user_event(const char *chr, int event) "chr: %s got event: %d"
diff --git a/net/vhost-user-stub.c b/net/vhost-user-stub.c
new file mode 100644
index 0000000..52ab4e1
--- /dev/null
+++ b/net/vhost-user-stub.c
@@ -0,0 +1,23 @@
+/*
+ * vhost-user-stub.c
+ *
+ * Copyright (c) 2018 Red Hat, Inc.
+ *
+ * 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 "clients.h"
+#include "net/vhost_net.h"
+#include "net/vhost-user.h"
+#include "qemu/error-report.h"
+#include "qapi/error.h"
+
+int net_init_vhost_user(const Netdev *netdev, const char *name,
+ NetClientState *peer, Error **errp)
+{
+ error_setg(errp, "vhost-user requires frontend driver virtio-net-*");
+ return -1;
+}
diff --git a/net/vhost-user.c b/net/vhost-user.c
index a39f9c9..cd9659d 100644
--- a/net/vhost-user.c
+++ b/net/vhost-user.c
@@ -172,6 +172,17 @@
qemu_purge_queued_packets(nc);
}
+static int vhost_user_set_vnet_endianness(NetClientState *nc,
+ bool enable)
+{
+ /* Nothing to do. If the server supports
+ * VHOST_USER_PROTOCOL_F_CROSS_ENDIAN, it will get the
+ * vnet header endianness from there. If it doesn't, negotiation
+ * fails.
+ */
+ return 0;
+}
+
static bool vhost_user_has_vnet_hdr(NetClientState *nc)
{
assert(nc->info->type == NET_CLIENT_DRIVER_VHOST_USER);
@@ -193,6 +204,8 @@
.cleanup = net_vhost_user_cleanup,
.has_vnet_hdr = vhost_user_has_vnet_hdr,
.has_ufo = vhost_user_has_ufo,
+ .set_vnet_be = vhost_user_set_vnet_endianness,
+ .set_vnet_le = vhost_user_set_vnet_endianness,
};
static gboolean net_vhost_user_watch(GIOChannel *chan, GIOCondition cond,
diff --git a/python/qemu/__init__.py b/python/qemu/__init__.py
index 585cd2a..fd144c0 100644
--- a/python/qemu/__init__.py
+++ b/python/qemu/__init__.py
@@ -145,10 +145,9 @@
return False
# This can be used to add an unused monitor instance.
- def add_monitor_telnet(self, ip, port):
- args = 'tcp:%s:%d,server,nowait,telnet' % (ip, port)
+ def add_monitor_null(self):
self._args.append('-monitor')
- self._args.append(args)
+ self._args.append('null')
def add_fd(self, fd, fdset, opaque, opts=''):
"""
diff --git a/qapi/Makefile.objs b/qapi/Makefile.objs
index 87e4df1..77acca0 100644
--- a/qapi/Makefile.objs
+++ b/qapi/Makefile.objs
@@ -5,7 +5,7 @@
util-obj-y += qmp-event.o
util-obj-y += qapi-util.o
-QAPI_COMMON_MODULES = block-core block char common crypto introspect
+QAPI_COMMON_MODULES = authz block-core block char common crypto introspect
QAPI_COMMON_MODULES += job migration misc net rdma rocker run-state
QAPI_COMMON_MODULES += sockets tpm trace transaction ui
QAPI_TARGET_MODULES = target
diff --git a/qapi/authz.json b/qapi/authz.json
new file mode 100644
index 0000000..1c836a3
--- /dev/null
+++ b/qapi/authz.json
@@ -0,0 +1,58 @@
+# -*- Mode: Python -*-
+#
+# QAPI authz definitions
+
+##
+# @QAuthZListPolicy:
+#
+# The authorization policy result
+#
+# @deny: deny access
+# @allow: allow access
+#
+# Since: 4.0
+##
+{ 'enum': 'QAuthZListPolicy',
+ 'prefix': 'QAUTHZ_LIST_POLICY',
+ 'data': ['deny', 'allow']}
+
+##
+# @QAuthZListFormat:
+#
+# The authorization policy match format
+#
+# @exact: an exact string match
+# @glob: string with ? and * shell wildcard support
+#
+# Since: 4.0
+##
+{ 'enum': 'QAuthZListFormat',
+ 'prefix': 'QAUTHZ_LIST_FORMAT',
+ 'data': ['exact', 'glob']}
+
+##
+# @QAuthZListRule:
+#
+# A single authorization rule.
+#
+# @match: a string or glob to match against a user identity
+# @policy: the result to return if @match evaluates to true
+# @format: the format of the @match rule (default 'exact')
+#
+# Since: 4.0
+##
+{ 'struct': 'QAuthZListRule',
+ 'data': {'match': 'str',
+ 'policy': 'QAuthZListPolicy',
+ '*format': 'QAuthZListFormat'}}
+
+##
+# @QAuthZListRuleListHack:
+#
+# Not exposed via QMP; hack to generate QAuthZListRuleList
+# for use internally by the code.
+#
+# Since: 4.0
+##
+{ 'struct': 'QAuthZListRuleListHack',
+ 'data': { 'unused': ['QAuthZListRule'] } }
diff --git a/qapi/migration.json b/qapi/migration.json
index 7a795ec..5684733 100644
--- a/qapi/migration.json
+++ b/qapi/migration.json
@@ -6,6 +6,7 @@
##
{ 'include': 'common.json' }
+{ 'include': 'sockets.json' }
##
# @MigrationStats:
@@ -199,6 +200,8 @@
# @compression: migration compression statistics, only returned if compression
# feature is on and status is 'active' or 'completed' (Since 3.1)
#
+# @socket-address: Only used for tcp, to know what the real port is (Since 4.0)
+#
# Since: 0.14.0
##
{ 'struct': 'MigrationInfo',
@@ -213,7 +216,8 @@
'*error-desc': 'str',
'*postcopy-blocktime' : 'uint32',
'*postcopy-vcpu-blocktime': ['uint32'],
- '*compression': 'CompressionStats'} }
+ '*compression': 'CompressionStats',
+ '*socket-address': ['SocketAddress'] } }
##
# @query-migrate:
@@ -409,13 +413,16 @@
# devices (and thus take locks) immediately at the end of migration.
# (since 3.0)
#
+# @x-ignore-shared: If enabled, QEMU will not migrate shared memory (since 4.0)
+#
# Since: 1.2
##
{ 'enum': 'MigrationCapability',
'data': ['xbzrle', 'rdma-pin-all', 'auto-converge', 'zero-blocks',
'compress', 'events', 'postcopy-ram', 'x-colo', 'release-ram',
'block', 'return-path', 'pause-before-switchover', 'x-multifd',
- 'dirty-bitmaps', 'postcopy-blocktime', 'late-block-activate' ] }
+ 'dirty-bitmaps', 'postcopy-blocktime', 'late-block-activate',
+ 'x-ignore-shared' ] }
##
# @MigrationCapabilityStatus:
@@ -480,6 +487,18 @@
#
# Migration parameters enumeration
#
+# @announce-initial: Initial delay (in milliseconds) before sending the first
+# announce (Since 4.0)
+#
+# @announce-max: Maximum delay (in milliseconds) between packets in the
+# announcement (Since 4.0)
+#
+# @announce-rounds: Number of self-announce packets sent after migration
+# (Since 4.0)
+#
+# @announce-step: Increase in delay (in milliseconds) between subsequent
+# packets in the announcement (Since 4.0)
+#
# @compress-level: Set the compression level to be used in live migration,
# the compression level is an integer between 0 and 9, where 0 means
# no compression, 1 means the best compression speed, and 9 means best
@@ -557,10 +576,13 @@
#
# @max-cpu-throttle: maximum cpu throttle percentage.
# Defaults to 99. (Since 3.1)
+#
# Since: 2.4
##
{ 'enum': 'MigrationParameter',
- 'data': ['compress-level', 'compress-threads', 'decompress-threads',
+ 'data': ['announce-initial', 'announce-max',
+ 'announce-rounds', 'announce-step',
+ 'compress-level', 'compress-threads', 'decompress-threads',
'compress-wait-thread',
'cpu-throttle-initial', 'cpu-throttle-increment',
'tls-creds', 'tls-hostname', 'max-bandwidth',
@@ -572,6 +594,18 @@
##
# @MigrateSetParameters:
#
+# @announce-initial: Initial delay (in milliseconds) before sending the first
+# announce (Since 4.0)
+#
+# @announce-max: Maximum delay (in milliseconds) between packets in the
+# announcement (Since 4.0)
+#
+# @announce-rounds: Number of self-announce packets sent after migration
+# (Since 4.0)
+#
+# @announce-step: Increase in delay (in milliseconds) between subsequent
+# packets in the announcement (Since 4.0)
+#
# @compress-level: compression level
#
# @compress-threads: compression thread count
@@ -653,7 +687,11 @@
# TODO either fuse back into MigrationParameters, or make
# MigrationParameters members mandatory
{ 'struct': 'MigrateSetParameters',
- 'data': { '*compress-level': 'int',
+ 'data': { '*announce-initial': 'size',
+ '*announce-max': 'size',
+ '*announce-rounds': 'size',
+ '*announce-step': 'size',
+ '*compress-level': 'int',
'*compress-threads': 'int',
'*compress-wait-thread': 'bool',
'*decompress-threads': 'int',
@@ -692,6 +730,18 @@
#
# The optional members aren't actually optional.
#
+# @announce-initial: Initial delay (in milliseconds) before sending the
+# first announce (Since 4.0)
+#
+# @announce-max: Maximum delay (in milliseconds) between packets in the
+# announcement (Since 4.0)
+#
+# @announce-rounds: Number of self-announce packets sent after migration
+# (Since 4.0)
+#
+# @announce-step: Increase in delay (in milliseconds) between subsequent
+# packets in the announcement (Since 4.0)
+#
# @compress-level: compression level
#
# @compress-threads: compression thread count
@@ -769,7 +819,11 @@
# Since: 2.4
##
{ 'struct': 'MigrationParameters',
- 'data': { '*compress-level': 'uint8',
+ 'data': { '*announce-initial': 'size',
+ '*announce-max': 'size',
+ '*announce-rounds': 'size',
+ '*announce-step': 'size',
+ '*compress-level': 'uint8',
'*compress-threads': 'uint8',
'*compress-wait-thread': 'bool',
'*decompress-threads': 'uint8',
@@ -1339,7 +1393,7 @@
# Example:
#
# -> { "execute": "query-colo-status" }
-# <- { "return": { "mode": "primary", "active": true, "reason": "request" } }
+# <- { "return": { "mode": "primary", "reason": "request" } }
#
# Since: 3.1
##
diff --git a/qapi/net.json b/qapi/net.json
index a1a0f39..5f7bff1 100644
--- a/qapi/net.json
+++ b/qapi/net.json
@@ -684,3 +684,46 @@
##
{ 'event': 'NIC_RX_FILTER_CHANGED',
'data': { '*name': 'str', 'path': 'str' } }
+
+##
+# @AnnounceParameters:
+#
+# Parameters for self-announce timers
+#
+# @initial: Initial delay (in ms) before sending the first GARP/RARP
+# announcement
+#
+# @max: Maximum delay (in ms) between GARP/RARP announcement packets
+#
+# @rounds: Number of self-announcement attempts
+#
+# @step: Delay increase (in ms) after each self-announcement attempt
+#
+# Since: 4.0
+##
+
+{ 'struct': 'AnnounceParameters',
+ 'data': { 'initial': 'int',
+ 'max': 'int',
+ 'rounds': 'int',
+ 'step': 'int' } }
+
+##
+# @announce-self:
+#
+# Trigger generation of broadcast RARP frames to update network switches.
+# This can be useful when network bonds fail-over the active slave.
+#
+# @params: AnnounceParameters giving timing and repetition count of announce
+#
+# Example:
+#
+# -> { "execute": "announce-self"
+# "arguments": {
+# "initial": 50, "max": 550, "rounds": 10, "step": 50 } }
+# <- { "return": {} }
+#
+# Since: 4.0
+##
+{ 'command': 'announce-self', 'boxed': true,
+ 'data' : 'AnnounceParameters'}
diff --git a/qapi/qapi-schema.json b/qapi/qapi-schema.json
index db61bfd..a34899c 100644
--- a/qapi/qapi-schema.json
+++ b/qapi/qapi-schema.json
@@ -92,6 +92,7 @@
{ 'include': 'rocker.json' }
{ 'include': 'tpm.json' }
{ 'include': 'ui.json' }
+{ 'include': 'authz.json' }
{ 'include': 'migration.json' }
{ 'include': 'transaction.json' }
{ 'include': 'trace.json' }
diff --git a/qapi/ui.json b/qapi/ui.json
index 7d9c4bd..c5d1d7f 100644
--- a/qapi/ui.json
+++ b/qapi/ui.json
@@ -1085,12 +1085,42 @@
#
# Display (user interface) type.
#
+# @default: The default user interface, selecting from the first available
+# of gtk, sdl, cocoa, and vnc.
+#
+# @none: No user interface or video output display. The guest will
+# still see an emulated graphics card, but its output will not
+# be displayed to the QEMU user.
+#
+# @gtk: The GTK user interface.
+#
+# @sdl: The SDL user interface.
+#
+# @egl-headless: No user interface, offload GL operations to a local
+# DRI device. Graphical display need to be paired with
+# VNC or Spice. (Since 3.1)
+#
+# @curses: Display video output via curses. For graphics device
+# models which support a text mode, QEMU can display this
+# output using a curses/ncurses interface. Nothing is
+# displayed when the graphics device is in graphical mode or
+# if the graphics device does not support a text
+# mode. Generally only the VGA device models support text
+# mode.
+#
+# @cocoa: The Cocoa user interface.
+#
+# @spice-app: Set up a Spice server and run the default associated
+# application to connect to it. The server will redirect
+# the serial console and QEMU monitors. (Since 4.0)
+#
# Since: 2.12
#
##
{ 'enum' : 'DisplayType',
'data' : [ 'default', 'none', 'gtk', 'sdl',
- 'egl-headless', 'curses', 'cocoa' ] }
+ 'egl-headless', 'curses', 'cocoa',
+ 'spice-app'] }
##
# @DisplayOptions:
diff --git a/qdev-monitor.c b/qdev-monitor.c
index 07147c6..d432098 100644
--- a/qdev-monitor.c
+++ b/qdev-monitor.c
@@ -414,7 +414,7 @@
static inline bool qbus_is_full(BusState *bus)
{
BusClass *bus_class = BUS_GET_CLASS(bus);
- return bus_class->max_dev && bus->max_index >= bus_class->max_dev;
+ return bus_class->max_dev && bus->num_children >= bus_class->max_dev;
}
/*
@@ -862,6 +862,7 @@
DeviceClass *dc = DEVICE_GET_CLASS(dev);
HotplugHandler *hotplug_ctrl;
HotplugHandlerClass *hdc;
+ Error *local_err = NULL;
if (dev->parent_bus && !qbus_is_hotpluggable(dev->parent_bus)) {
error_setg(errp, QERR_BUS_NO_HOTPLUG, dev->parent_bus->name);
@@ -890,10 +891,14 @@
* otherwise just remove it synchronously */
hdc = HOTPLUG_HANDLER_GET_CLASS(hotplug_ctrl);
if (hdc->unplug_request) {
- hotplug_handler_unplug_request(hotplug_ctrl, dev, errp);
+ hotplug_handler_unplug_request(hotplug_ctrl, dev, &local_err);
} else {
- hotplug_handler_unplug(hotplug_ctrl, dev, errp);
+ hotplug_handler_unplug(hotplug_ctrl, dev, &local_err);
+ if (!local_err) {
+ object_unparent(OBJECT(dev));
+ }
}
+ error_propagate(errp, local_err);
}
void qmp_device_del(const char *id, Error **errp)
diff --git a/qemu-doc.texi b/qemu-doc.texi
index 83be010..ae3c3f9 100644
--- a/qemu-doc.texi
+++ b/qemu-doc.texi
@@ -2049,6 +2049,15 @@
Cirrus (default) or any other PCI VGA graphics card
@end itemize
+The Boston board emulation supports the following devices:
+
+@itemize @minus
+@item
+Xilinx FPGA, which includes a PCIe root port and an UART
+@item
+Intel EG20T PCH connects the I/O peripherals, but only the SATA bus is emulated
+@end itemize
+
The ACER Pica emulation supports:
@itemize @minus
@@ -2062,19 +2071,6 @@
IDE controller
@end itemize
-The mipssim pseudo board emulation provides an environment similar
-to what the proprietary MIPS emulator uses for running Linux.
-It supports:
-
-@itemize @minus
-@item
-A range of MIPS CPUs, default is the 24Kf
-@item
-PC style serial port
-@item
-MIPSnet network emulation
-@end itemize
-
The MIPS Magnum R4000 emulation supports:
@itemize @minus
@@ -2090,6 +2086,32 @@
G364 framebuffer
@end itemize
+The Fulong 2E emulation supports:
+
+@itemize @minus
+@item
+Loongson 2E CPU
+@item
+Bonito64 system controller as North Bridge
+@item
+VT82C686 chipset as South Bridge
+@item
+RTL8139D as a network card chipset
+@end itemize
+
+The mipssim pseudo board emulation provides an environment similar
+to what the proprietary MIPS emulator uses for running Linux.
+It supports:
+
+@itemize @minus
+@item
+A range of MIPS CPUs, default is the 24Kf
+@item
+PC style serial port
+@item
+MIPSnet network emulation
+@end itemize
+
@node nanoMIPS System emulator
@subsection nanoMIPS System emulator
@cindex system emulation (nanoMIPS)
diff --git a/qemu-img.c b/qemu-img.c
index 25288c4..660c018 100644
--- a/qemu-img.c
+++ b/qemu-img.c
@@ -503,7 +503,7 @@
if (qemu_opts_foreach(&qemu_object_opts,
user_creatable_add_opts_foreach,
- NULL, NULL)) {
+ NULL, &error_fatal)) {
goto fail;
}
@@ -753,7 +753,7 @@
if (qemu_opts_foreach(&qemu_object_opts,
user_creatable_add_opts_foreach,
- NULL, NULL)) {
+ NULL, &error_fatal)) {
return 1;
}
@@ -966,7 +966,7 @@
if (qemu_opts_foreach(&qemu_object_opts,
user_creatable_add_opts_foreach,
- NULL, NULL)) {
+ NULL, &error_fatal)) {
return 1;
}
@@ -1349,7 +1349,7 @@
if (qemu_opts_foreach(&qemu_object_opts,
user_creatable_add_opts_foreach,
- NULL, NULL)) {
+ NULL, &error_fatal)) {
ret = 2;
goto out4;
}
@@ -1670,7 +1670,6 @@
{
int n, ret;
QEMUIOVector qiov;
- struct iovec iov;
assert(nb_sectors <= s->buf_sectors);
while (nb_sectors > 0) {
@@ -1686,9 +1685,7 @@
bs_sectors = s->src_sectors[src_cur];
n = MIN(nb_sectors, bs_sectors - (sector_num - src_cur_offset));
- iov.iov_base = buf;
- iov.iov_len = n << BDRV_SECTOR_BITS;
- qemu_iovec_init_external(&qiov, &iov, 1);
+ qemu_iovec_init_buf(&qiov, buf, n << BDRV_SECTOR_BITS);
ret = blk_co_preadv(
blk, (sector_num - src_cur_offset) << BDRV_SECTOR_BITS,
@@ -1712,7 +1709,6 @@
{
int ret;
QEMUIOVector qiov;
- struct iovec iov;
while (nb_sectors > 0) {
int n = nb_sectors;
@@ -1740,9 +1736,7 @@
(s->compressed &&
!buffer_is_zero(buf, n * BDRV_SECTOR_SIZE)))
{
- iov.iov_base = buf;
- iov.iov_len = n << BDRV_SECTOR_BITS;
- qemu_iovec_init_external(&qiov, &iov, 1);
+ qemu_iovec_init_buf(&qiov, buf, n << BDRV_SECTOR_BITS);
ret = blk_co_pwritev(s->target, sector_num << BDRV_SECTOR_BITS,
n << BDRV_SECTOR_BITS, &qiov, flags);
@@ -2159,7 +2153,7 @@
if (qemu_opts_foreach(&qemu_object_opts,
user_creatable_add_opts_foreach,
- NULL, NULL)) {
+ NULL, &error_fatal)) {
goto fail_getopt;
}
@@ -2713,7 +2707,7 @@
if (qemu_opts_foreach(&qemu_object_opts,
user_creatable_add_opts_foreach,
- NULL, NULL)) {
+ NULL, &error_fatal)) {
return 1;
}
@@ -2790,6 +2784,7 @@
BlockDriverState *file;
bool has_offset;
int64_t map;
+ char *filename = NULL;
/* As an optimization, we could cache the current range of unallocated
* clusters in each file of the chain, and avoid querying the same
@@ -2817,6 +2812,11 @@
has_offset = !!(ret & BDRV_BLOCK_OFFSET_VALID);
+ if (file && has_offset) {
+ bdrv_refresh_filename(file);
+ filename = file->filename;
+ }
+
*e = (MapEntry) {
.start = offset,
.length = bytes,
@@ -2825,8 +2825,8 @@
.offset = map,
.has_offset = has_offset,
.depth = depth,
- .has_filename = file && has_offset,
- .filename = file && has_offset ? file->filename : NULL,
+ .has_filename = filename,
+ .filename = filename,
};
return 0;
@@ -2932,7 +2932,7 @@
if (qemu_opts_foreach(&qemu_object_opts,
user_creatable_add_opts_foreach,
- NULL, NULL)) {
+ NULL, &error_fatal)) {
return 1;
}
@@ -3081,7 +3081,7 @@
if (qemu_opts_foreach(&qemu_object_opts,
user_creatable_add_opts_foreach,
- NULL, NULL)) {
+ NULL, &error_fatal)) {
return 1;
}
@@ -3123,11 +3123,18 @@
break;
case SNAPSHOT_DELETE:
- bdrv_snapshot_delete_by_id_or_name(bs, snapshot_name, &err);
- if (err) {
- error_reportf_err(err, "Could not delete snapshot '%s': ",
- snapshot_name);
+ ret = bdrv_snapshot_find(bs, &sn, snapshot_name);
+ if (ret < 0) {
+ error_report("Could not delete snapshot '%s': snapshot not "
+ "found", snapshot_name);
ret = 1;
+ } else {
+ ret = bdrv_snapshot_delete(bs, sn.id_str, sn.name, &err);
+ if (ret < 0) {
+ error_reportf_err(err, "Could not delete snapshot '%s': ",
+ snapshot_name);
+ ret = 1;
+ }
}
break;
}
@@ -3241,7 +3248,7 @@
if (qemu_opts_foreach(&qemu_object_opts,
user_creatable_add_opts_foreach,
- NULL, NULL)) {
+ NULL, &error_fatal)) {
return 1;
}
@@ -3327,20 +3334,17 @@
qdict_put_bool(options, BDRV_OPT_FORCE_SHARE, true);
}
+ bdrv_refresh_filename(bs);
overlay_filename = bs->exact_filename[0] ? bs->exact_filename
: bs->filename;
- out_real_path = g_malloc(PATH_MAX);
-
- bdrv_get_full_backing_filename_from_filename(overlay_filename,
- out_baseimg,
- out_real_path,
- PATH_MAX,
- &local_err);
+ out_real_path =
+ bdrv_get_full_backing_filename_from_filename(overlay_filename,
+ out_baseimg,
+ &local_err);
if (local_err) {
error_reportf_err(local_err,
"Could not resolve backing filename: ");
ret = -1;
- g_free(out_real_path);
goto out;
}
@@ -3621,7 +3625,7 @@
if (qemu_opts_foreach(&qemu_object_opts,
user_creatable_add_opts_foreach,
- NULL, NULL)) {
+ NULL, &error_fatal)) {
return 1;
}
@@ -3865,7 +3869,7 @@
if (qemu_opts_foreach(&qemu_object_opts,
user_creatable_add_opts_foreach,
- NULL, NULL)) {
+ NULL, &error_fatal)) {
ret = -1;
goto out_no_progress;
}
@@ -4509,7 +4513,7 @@
if (qemu_opts_foreach(&qemu_object_opts,
user_creatable_add_opts_foreach,
- NULL, NULL)) {
+ NULL, &error_fatal)) {
ret = -1;
goto out;
}
@@ -4786,7 +4790,7 @@
if (qemu_opts_foreach(&qemu_object_opts,
user_creatable_add_opts_foreach,
- NULL, NULL)) {
+ NULL, &error_fatal)) {
goto out;
}
diff --git a/qemu-options.hx b/qemu-options.hx
index 77bd98e..1cf9aac 100644
--- a/qemu-options.hx
+++ b/qemu-options.hx
@@ -1211,6 +1211,7 @@
ETEXI
DEF("display", HAS_ARG, QEMU_OPTION_display,
+ "-display spice-app[,gl=on|off]\n"
"-display sdl[,frame=on|off][,alt_grab=on|off][,ctrl_grab=on|off]\n"
" [,window_close=on|off][,gl=on|core|es|off]\n"
"-display gtk[,grab_on_hover=on|off][,gl=on|off]|\n"
@@ -1262,6 +1263,10 @@
@item egl-headless
Offload all OpenGL operations to a local DRI device. For any graphical display,
this display needs to be paired with either VNC or SPICE displays.
+@item spice-app
+Start QEMU as a Spice server and launch the default Spice client
+application. The Spice server will redirect the serial consoles and
+QEMU monitors. (Since 4.0)
@end table
ETEXI
@@ -4360,6 +4365,111 @@
.....
@end example
+
+
+@item -object authz-simple,id=@var{id},identity=@var{string}
+
+Create an authorization object that will control access to network services.
+
+The @option{identity} parameter is identifies the user and its format
+depends on the network service that authorization object is associated
+with. For authorizing based on TLS x509 certificates, the identity must
+be the x509 distinguished name. Note that care must be taken to escape
+any commas in the distinguished name.
+
+An example authorization object to validate a x509 distinguished name
+would look like:
+@example
+ # $QEMU \
+ ...
+ -object 'authz-simple,id=auth0,identity=CN=laptop.example.com,,O=Example Org,,L=London,,ST=London,,C=GB' \
+ ...
+@end example
+
+Note the use of quotes due to the x509 distinguished name containing
+whitespace, and escaping of ','.
+
+@item -object authz-listfile,id=@var{id},filename=@var{path},refresh=@var{yes|no}
+
+Create an authorization object that will control access to network services.
+
+The @option{filename} parameter is the fully qualified path to a file
+containing the access control list rules in JSON format.
+
+An example set of rules that match against SASL usernames might look
+like:
+
+@example
+ @{
+ "rules": [
+ @{ "match": "fred", "policy": "allow", "format": "exact" @},
+ @{ "match": "bob", "policy": "allow", "format": "exact" @},
+ @{ "match": "danb", "policy": "deny", "format": "glob" @},
+ @{ "match": "dan*", "policy": "allow", "format": "exact" @},
+ ],
+ "policy": "deny"
+ @}
+@end example
+
+When checking access the object will iterate over all the rules and
+the first rule to match will have its @option{policy} value returned
+as the result. If no rules match, then the default @option{policy}
+value is returned.
+
+The rules can either be an exact string match, or they can use the
+simple UNIX glob pattern matching to allow wildcards to be used.
+
+If @option{refresh} is set to true the file will be monitored
+and automatically reloaded whenever its content changes.
+
+As with the @code{authz-simple} object, the format of the identity
+strings being matched depends on the network service, but is usually
+a TLS x509 distinguished name, or a SASL username.
+
+An example authorization object to validate a SASL username
+would look like:
+@example
+ # $QEMU \
+ ...
+ -object authz-simple,id=auth0,filename=/etc/qemu/vnc-sasl.acl,refresh=yes
+ ...
+@end example
+
+@item -object authz-pam,id=@var{id},service=@var{string}
+
+Create an authorization object that will control access to network services.
+
+The @option{service} parameter provides the name of a PAM service to use
+for authorization. It requires that a file @code{/etc/pam.d/@var{service}}
+exist to provide the configuration for the @code{account} subsystem.
+
+An example authorization object to validate a TLS x509 distinguished
+name would look like:
+
+@example
+ # $QEMU \
+ ...
+ -object authz-pam,id=auth0,service=qemu-vnc
+ ...
+@end example
+
+There would then be a corresponding config file for PAM at
+@code{/etc/pam.d/qemu-vnc} that contains:
+
+@example
+account requisite pam_listfile.so item=user sense=allow \
+ file=/etc/qemu/vnc.allow
+@end example
+
+Finally the @code{/etc/qemu/vnc.allow} file would contain
+the list of x509 distingished names that are permitted
+access
+
+@example
+CN=laptop.example.com,O=Example Home,L=London,ST=London,C=GB
+@end example
+
+
@end table
ETEXI
diff --git a/qom/object.c b/qom/object.c
index b8c7320..05a8567 100644
--- a/qom/object.c
+++ b/qom/object.c
@@ -646,16 +646,20 @@
goto error;
}
- object_property_add_child(parent, id, obj, &local_err);
- if (local_err) {
- goto error;
+ if (id != NULL) {
+ object_property_add_child(parent, id, obj, &local_err);
+ if (local_err) {
+ goto error;
+ }
}
uc = (UserCreatable *)object_dynamic_cast(obj, TYPE_USER_CREATABLE);
if (uc) {
user_creatable_complete(uc, &local_err);
if (local_err) {
- object_unparent(obj);
+ if (id != NULL) {
+ object_unparent(obj);
+ }
goto error;
}
}
diff --git a/qom/object_interfaces.c b/qom/object_interfaces.c
index db85d1e..cb58099 100644
--- a/qom/object_interfaces.c
+++ b/qom/object_interfaces.c
@@ -75,16 +75,20 @@
goto out;
}
- object_property_add_child(object_get_objects_root(),
- id, obj, &local_err);
- if (local_err) {
- goto out;
+ if (id != NULL) {
+ object_property_add_child(object_get_objects_root(),
+ id, obj, &local_err);
+ if (local_err) {
+ goto out;
+ }
}
user_creatable_complete(USER_CREATABLE(obj), &local_err);
if (local_err) {
- object_property_del(object_get_objects_root(),
- id, &error_abort);
+ if (id != NULL) {
+ object_property_del(object_get_objects_root(),
+ id, &error_abort);
+ }
goto out;
}
out:
diff --git a/roms/Makefile b/roms/Makefile
index a6043ef..78d5dd1 100644
--- a/roms/Makefile
+++ b/roms/Makefile
@@ -47,10 +47,7 @@
# We need that to combine multiple images (legacy bios,
# efi ia32, efi x64) into a single rom binary.
#
-# We try to find it in the path. You can also pass the location on
-# the command line, i.e. "make EFIROM=/path/to/EfiRom efirom"
-#
-EFIROM ?= $(shell which EfiRom 2>/dev/null)
+EFIROM = edk2/BaseTools/Source/C/bin/EfiRom
default:
@echo "nothing is build by default"
@@ -59,8 +56,7 @@
@echo " vgabios -- update vgabios binaries (seabios)"
@echo " sgabios -- update sgabios binaries"
@echo " pxerom -- update nic roms (bios only)"
- @echo " efirom -- update nic roms (bios+efi, this needs"
- @echo " the EfiRom utility from edk2 / tianocore)"
+ @echo " efirom -- update nic roms (bios+efi)"
@echo " slof -- update slof.bin"
@echo " skiboot -- update skiboot.lid"
@echo " u-boot.e500 -- update u-boot.e500"
@@ -106,7 +102,7 @@
efirom: $(patsubst %,efi-rom-%,$(pxerom_variants))
-efi-rom-%: build-pxe-roms build-efi-roms
+efi-rom-%: build-pxe-roms build-efi-roms $(EFIROM)
$(EFIROM) -f "0x$(VID)" -i "0x$(DID)" -l 0x02 \
-b ipxe/src/bin/$(VID)$(DID).rom \
-ec ipxe/src/bin-i386-efi/$(VID)$(DID).efidrv \
@@ -124,6 +120,8 @@
$(patsubst %,bin-i386-efi/%.efidrv,$(pxerom_targets)) \
$(patsubst %,bin-x86_64-efi/%.efidrv,$(pxerom_targets))
+$(EFIROM):
+ $(MAKE) -C edk2/BaseTools
slof:
$(MAKE) -C SLOF CROSS=$(powerpc64_cross_prefix) qemu
@@ -150,6 +148,7 @@
$(MAKE) -C sgabios clean
rm -f sgabios/.depend
$(MAKE) -C ipxe/src veryclean
+ $(MAKE) -C edk2/BaseTools clean
$(MAKE) -C SLOF clean
rm -rf u-boot/build.e500
$(MAKE) -C u-boot-sam460ex distclean
diff --git a/roms/edk2 b/roms/edk2
new file mode 160000
index 0000000..8558838
--- /dev/null
+++ b/roms/edk2
@@ -0,0 +1 @@
+Subproject commit 85588389222a3636baf0f9ed8227f2434af4c3f9
diff --git a/rules.mak b/rules.mak
index 86e033d..19f3d2c 100644
--- a/rules.mak
+++ b/rules.mak
@@ -327,7 +327,7 @@
# ../water/ice.mo-libs = -licemaker
# ../water/ice.mo-objs = ../water/ice1.o ../water/ice2.o
#
-# Note that 'hot' didn't include 'season/' in the input, so 'summer.o' is not
+# Note that 'hot' didn't include 'water/' in the input, so 'steam.o' is not
# included.
#
define unnest-vars
diff --git a/scripts/qapi/commands.py b/scripts/qapi/commands.py
index ebf4889..6d66bf6 100644
--- a/scripts/qapi/commands.py
+++ b/scripts/qapi/commands.py
@@ -239,7 +239,7 @@
QAPISchemaModularCVisitor.__init__(
self, prefix, 'qapi-commands',
' * Schema-defined QAPI/QMP commands', __doc__)
- self._regy = QAPIGenCCode()
+ self._regy = QAPIGenCCode(None)
self._visited_ret_types = {}
def _begin_user_module(self, name):
diff --git a/scripts/qapi/common.py b/scripts/qapi/common.py
index c327ae5..f07869e 100644
--- a/scripts/qapi/common.py
+++ b/scripts/qapi/common.py
@@ -1089,6 +1089,9 @@
self.ifcond = typ.ifcond
else:
self.ifcond = listify_cond(self._ifcond)
+ if self.info:
+ self.module = os.path.relpath(self.info['file'],
+ os.path.dirname(schema.fname))
def is_implicit(self):
return not self.info
@@ -1262,6 +1265,7 @@
self.element_type = schema.lookup_type(self._element_type_name)
assert self.element_type
self.element_type.check(schema)
+ self.module = self.element_type.module
self.ifcond = self.element_type.ifcond
def is_implicit(self):
@@ -1603,7 +1607,7 @@
class QAPISchema(object):
def __init__(self, fname):
- self._fname = fname
+ self.fname = fname
if sys.version_info[0] >= 3:
f = open(fname, 'r', encoding='utf-8')
else:
@@ -1626,9 +1630,6 @@
self._entity_list.append(ent)
if ent.name is not None:
self._entity_dict[ent.name] = ent
- if ent.info:
- ent.module = os.path.relpath(ent.info['file'],
- os.path.dirname(self._fname))
def lookup_entity(self, name, typ=None):
ent = self._entity_dict.get(name)
@@ -2017,8 +2018,8 @@
return cgen(code, **kwds)
-def guardname(filename):
- return re.sub(r'[^A-Za-z0-9_]', '_', filename).upper()
+def c_fname(filename):
+ return re.sub(r'[^A-Za-z0-9_]', '_', filename)
def guardstart(name):
@@ -2027,7 +2028,7 @@
#define %(name)s
''',
- name=guardname(name))
+ name=c_fname(name).upper())
def guardend(name):
@@ -2035,7 +2036,7 @@
#endif /* %(name)s */
''',
- name=guardname(name))
+ name=c_fname(name).upper())
def gen_if(ifcond):
@@ -2158,7 +2159,8 @@
class QAPIGen(object):
- def __init__(self):
+ def __init__(self, fname):
+ self.fname = fname
self._preamble = ''
self._body = ''
@@ -2168,18 +2170,17 @@
def add(self, text):
self._body += text
- def get_content(self, fname=None):
- return (self._top(fname) + self._preamble + self._body
- + self._bottom(fname))
+ def get_content(self):
+ return self._top() + self._preamble + self._body + self._bottom()
- def _top(self, fname):
+ def _top(self):
return ''
- def _bottom(self, fname):
+ def _bottom(self):
return ''
- def write(self, output_dir, fname):
- pathname = os.path.join(output_dir, fname)
+ def write(self, output_dir):
+ pathname = os.path.join(output_dir, self.fname)
dir = os.path.dirname(pathname)
if dir:
try:
@@ -2192,7 +2193,7 @@
f = open(fd, 'r+', encoding='utf-8')
else:
f = os.fdopen(fd, 'r+')
- text = self.get_content(fname)
+ text = self.get_content()
oldtext = f.read(len(text) + 1)
if text != oldtext:
f.seek(0)
@@ -2229,8 +2230,8 @@
class QAPIGenCCode(QAPIGen):
- def __init__(self):
- QAPIGen.__init__(self)
+ def __init__(self, fname):
+ QAPIGen.__init__(self, fname)
self._start_if = None
def start_if(self, ifcond):
@@ -2248,20 +2249,20 @@
self._preamble = _wrap_ifcond(self._start_if[0],
self._start_if[2], self._preamble)
- def get_content(self, fname=None):
+ def get_content(self):
assert self._start_if is None
- return QAPIGen.get_content(self, fname)
+ return QAPIGen.get_content(self)
class QAPIGenC(QAPIGenCCode):
- def __init__(self, blurb, pydoc):
- QAPIGenCCode.__init__(self)
+ def __init__(self, fname, blurb, pydoc):
+ QAPIGenCCode.__init__(self, fname)
self._blurb = blurb
self._copyright = '\n * '.join(re.findall(r'^Copyright .*', pydoc,
re.MULTILINE))
- def _top(self, fname):
+ def _top(self):
return mcgen('''
/* AUTOMATICALLY GENERATED, DO NOT MODIFY */
@@ -2277,28 +2278,28 @@
''',
blurb=self._blurb, copyright=self._copyright)
- def _bottom(self, fname):
+ def _bottom(self):
return mcgen('''
/* Dummy declaration to prevent empty .o file */
-char dummy_%(name)s;
+char qapi_dummy_%(name)s;
''',
- name=c_name(fname))
+ name=c_fname(self.fname))
class QAPIGenH(QAPIGenC):
- def _top(self, fname):
- return QAPIGenC._top(self, fname) + guardstart(fname)
+ def _top(self):
+ return QAPIGenC._top(self) + guardstart(self.fname)
- def _bottom(self, fname):
- return guardend(fname)
+ def _bottom(self):
+ return guardend(self.fname)
class QAPIGenDoc(QAPIGen):
- def _top(self, fname):
- return (QAPIGen._top(self, fname)
+ def _top(self):
+ return (QAPIGen._top(self)
+ '@c AUTOMATICALLY GENERATED, DO NOT MODIFY\n\n')
@@ -2307,12 +2308,14 @@
def __init__(self, prefix, what, blurb, pydoc):
self._prefix = prefix
self._what = what
- self._genc = QAPIGenC(blurb, pydoc)
- self._genh = QAPIGenH(blurb, pydoc)
+ self._genc = QAPIGenC(self._prefix + self._what + '.c',
+ blurb, pydoc)
+ self._genh = QAPIGenH(self._prefix + self._what + '.h',
+ blurb, pydoc)
def write(self, output_dir):
- self._genc.write(output_dir, self._prefix + self._what + '.c')
- self._genh.write(output_dir, self._prefix + self._what + '.h')
+ self._genc.write(output_dir)
+ self._genh.write(output_dir)
class QAPISchemaModularCVisitor(QAPISchemaVisitor):
@@ -2335,22 +2338,31 @@
def _is_builtin_module(name):
return not name
+ def _module_dirname(self, what, name):
+ if self._is_user_module(name):
+ return os.path.dirname(name)
+ return ''
+
def _module_basename(self, what, name):
ret = '' if self._is_builtin_module(name) else self._prefix
if self._is_user_module(name):
- dirname, basename = os.path.split(name)
+ basename = os.path.basename(name)
ret += what
if name != self._main_module:
ret += '-' + os.path.splitext(basename)[0]
- ret = os.path.join(dirname, ret)
else:
name = name[2:] if name else 'builtin'
ret += re.sub(r'-', '-' + name + '-', what)
return ret
+ def _module_filename(self, what, name):
+ return os.path.join(self._module_dirname(what, name),
+ self._module_basename(what, name))
+
def _add_module(self, name, blurb):
- genc = QAPIGenC(blurb, self._pydoc)
- genh = QAPIGenH(blurb, self._pydoc)
+ basename = self._module_filename(self._what, name)
+ genc = QAPIGenC(basename + '.c', blurb, self._pydoc)
+ genh = QAPIGenH(basename + '.h', blurb, self._pydoc)
self._module[name] = (genc, genh)
self._set_module(name)
@@ -2370,10 +2382,9 @@
for name in self._module:
if self._is_builtin_module(name) and not opt_builtins:
continue
- basename = self._module_basename(self._what, name)
(genc, genh) = self._module[name]
- genc.write(output_dir, basename + '.c')
- genh.write(output_dir, basename + '.h')
+ genc.write(output_dir)
+ genh.write(output_dir)
def _begin_user_module(self, name):
pass
@@ -2391,8 +2402,9 @@
self._begin_user_module(name)
def visit_include(self, name, info):
- basename = self._module_basename(self._what, name)
+ relname = os.path.relpath(self._module_filename(self._what, name),
+ os.path.dirname(self._genh.fname))
self._genh.preamble_add(mcgen('''
-#include "%(basename)s.h"
+#include "%(relname)s.h"
''',
- basename=basename))
+ relname=relname))
diff --git a/scripts/qapi/doc.py b/scripts/qapi/doc.py
index c03b690..5c8c136 100755
--- a/scripts/qapi/doc.py
+++ b/scripts/qapi/doc.py
@@ -207,11 +207,11 @@
class QAPISchemaGenDocVisitor(qapi.common.QAPISchemaVisitor):
def __init__(self, prefix):
self._prefix = prefix
- self._gen = qapi.common.QAPIGenDoc()
+ self._gen = qapi.common.QAPIGenDoc(self._prefix + 'qapi-doc.texi')
self.cur_doc = None
def write(self, output_dir):
- self._gen.write(output_dir, self._prefix + 'qapi-doc.texi')
+ self._gen.write(output_dir)
def visit_enum_type(self, name, info, ifcond, members, prefix):
doc = self.cur_doc
diff --git a/stubs/ram-block.c b/stubs/ram-block.c
index cfa5d86..73c0a3e 100644
--- a/stubs/ram-block.c
+++ b/stubs/ram-block.c
@@ -2,6 +2,21 @@
#include "exec/ramlist.h"
#include "exec/cpu-common.h"
+void *qemu_ram_get_host_addr(RAMBlock *rb)
+{
+ return 0;
+}
+
+ram_addr_t qemu_ram_get_offset(RAMBlock *rb)
+{
+ return 0;
+}
+
+ram_addr_t qemu_ram_get_used_length(RAMBlock *rb)
+{
+ return 0;
+}
+
void ram_block_notifier_add(RAMBlockNotifier *n)
{
}
diff --git a/target/arm/arm-powerctl.c b/target/arm/arm-powerctl.c
index f9de516..f77a950 100644
--- a/target/arm/arm-powerctl.c
+++ b/target/arm/arm-powerctl.c
@@ -228,6 +228,62 @@
return QEMU_ARM_POWERCTL_RET_SUCCESS;
}
+static void arm_set_cpu_on_and_reset_async_work(CPUState *target_cpu_state,
+ run_on_cpu_data data)
+{
+ ARMCPU *target_cpu = ARM_CPU(target_cpu_state);
+
+ /* Initialize the cpu we are turning on */
+ cpu_reset(target_cpu_state);
+ target_cpu_state->halted = 0;
+
+ /* Finally set the power status */
+ assert(qemu_mutex_iothread_locked());
+ target_cpu->power_state = PSCI_ON;
+}
+
+int arm_set_cpu_on_and_reset(uint64_t cpuid)
+{
+ CPUState *target_cpu_state;
+ ARMCPU *target_cpu;
+
+ assert(qemu_mutex_iothread_locked());
+
+ /* Retrieve the cpu we are powering up */
+ target_cpu_state = arm_get_cpu_by_id(cpuid);
+ if (!target_cpu_state) {
+ /* The cpu was not found */
+ return QEMU_ARM_POWERCTL_INVALID_PARAM;
+ }
+
+ target_cpu = ARM_CPU(target_cpu_state);
+ if (target_cpu->power_state == PSCI_ON) {
+ qemu_log_mask(LOG_GUEST_ERROR,
+ "[ARM]%s: CPU %" PRId64 " is already on\n",
+ __func__, cpuid);
+ return QEMU_ARM_POWERCTL_ALREADY_ON;
+ }
+
+ /*
+ * If another CPU has powered the target on we are in the state
+ * ON_PENDING and additional attempts to power on the CPU should
+ * fail (see 6.6 Implementation CPU_ON/CPU_OFF races in the PSCI
+ * spec)
+ */
+ if (target_cpu->power_state == PSCI_ON_PENDING) {
+ qemu_log_mask(LOG_GUEST_ERROR,
+ "[ARM]%s: CPU %" PRId64 " is already powering on\n",
+ __func__, cpuid);
+ return QEMU_ARM_POWERCTL_ON_PENDING;
+ }
+
+ async_run_on_cpu(target_cpu_state, arm_set_cpu_on_and_reset_async_work,
+ RUN_ON_CPU_NULL);
+
+ /* We are good to go */
+ return QEMU_ARM_POWERCTL_RET_SUCCESS;
+}
+
static void arm_set_cpu_off_async_work(CPUState *target_cpu_state,
run_on_cpu_data data)
{
diff --git a/target/arm/arm-powerctl.h b/target/arm/arm-powerctl.h
index 0435392..37c8a04 100644
--- a/target/arm/arm-powerctl.h
+++ b/target/arm/arm-powerctl.h
@@ -74,4 +74,20 @@
*/
int arm_reset_cpu(uint64_t cpuid);
+/*
+ * arm_set_cpu_on_and_reset:
+ * @cpuid: the id of the CPU we want to star
+ *
+ * Start the cpu designated by @cpuid and put it through its normal
+ * CPU reset process. The CPU will start in the way it is architected
+ * to start after a power-on reset.
+ *
+ * Returns: QEMU_ARM_POWERCTL_RET_SUCCESS on success.
+ * QEMU_ARM_POWERCTL_INVALID_PARAM if there is no CPU with that ID.
+ * QEMU_ARM_POWERCTL_ALREADY_ON if the CPU is already on.
+ * QEMU_ARM_POWERCTL_ON_PENDING if the CPU is already partway through
+ * powering on.
+ */
+int arm_set_cpu_on_and_reset(uint64_t cpuid);
+
#endif
diff --git a/target/arm/cpu.c b/target/arm/cpu.c
index 8ea6569..96f0ff0 100644
--- a/target/arm/cpu.c
+++ b/target/arm/cpu.c
@@ -22,6 +22,7 @@
#include "target/arm/idau.h"
#include "qemu/error-report.h"
#include "qapi/error.h"
+#include "qapi/visitor.h"
#include "cpu.h"
#include "internals.h"
#include "qemu-common.h"
@@ -771,9 +772,21 @@
pmsav7_dregion,
qdev_prop_uint32, uint32_t);
-/* M profile: initial value of the Secure VTOR */
-static Property arm_cpu_initsvtor_property =
- DEFINE_PROP_UINT32("init-svtor", ARMCPU, init_svtor, 0);
+static void arm_get_init_svtor(Object *obj, Visitor *v, const char *name,
+ void *opaque, Error **errp)
+{
+ ARMCPU *cpu = ARM_CPU(obj);
+
+ visit_type_uint32(v, name, &cpu->init_svtor, errp);
+}
+
+static void arm_set_init_svtor(Object *obj, Visitor *v, const char *name,
+ void *opaque, Error **errp)
+{
+ ARMCPU *cpu = ARM_CPU(obj);
+
+ visit_type_uint32(v, name, &cpu->init_svtor, errp);
+}
void arm_cpu_post_init(Object *obj)
{
@@ -845,8 +858,14 @@
qdev_prop_allow_set_link_before_realize,
OBJ_PROP_LINK_STRONG,
&error_abort);
- qdev_property_add_static(DEVICE(obj), &arm_cpu_initsvtor_property,
- &error_abort);
+ /*
+ * M profile: initial value of the Secure VTOR. We can't just use
+ * a simple DEFINE_PROP_UINT32 for this because we want to permit
+ * the property to be set after realize.
+ */
+ object_property_add(obj, "init-svtor", "uint32",
+ arm_get_init_svtor, arm_set_init_svtor,
+ NULL, NULL, &error_abort);
}
qdev_property_add_static(DEVICE(obj), &arm_cpu_cfgend_property,
@@ -995,7 +1014,6 @@
}
if (arm_feature(env, ARM_FEATURE_VFP4)) {
set_feature(env, ARM_FEATURE_VFP3);
- set_feature(env, ARM_FEATURE_VFP_FP16);
}
if (arm_feature(env, ARM_FEATURE_VFP3)) {
set_feature(env, ARM_FEATURE_VFP);
@@ -1656,7 +1674,6 @@
cpu->dtb_compatible = "arm,cortex-a9";
set_feature(&cpu->env, ARM_FEATURE_V7);
set_feature(&cpu->env, ARM_FEATURE_VFP3);
- set_feature(&cpu->env, ARM_FEATURE_VFP_FP16);
set_feature(&cpu->env, ARM_FEATURE_NEON);
set_feature(&cpu->env, ARM_FEATURE_THUMB2EE);
set_feature(&cpu->env, ARM_FEATURE_EL3);
@@ -2003,6 +2020,9 @@
t = cpu->isar.id_isar6;
t = FIELD_DP32(t, ID_ISAR6, JSCVT, 1);
t = FIELD_DP32(t, ID_ISAR6, DP, 1);
+ t = FIELD_DP32(t, ID_ISAR6, FHM, 1);
+ t = FIELD_DP32(t, ID_ISAR6, SB, 1);
+ t = FIELD_DP32(t, ID_ISAR6, SPECRES, 1);
cpu->isar.id_isar6 = t;
t = cpu->id_mmfr4;
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
index 1eea1a4..5f23c62 100644
--- a/target/arm/cpu.h
+++ b/target/arm/cpu.h
@@ -1060,7 +1060,8 @@
#define SCTLR_R (1U << 9) /* up to v6; RAZ in v7 */
#define SCTLR_UMA (1U << 9) /* v8 onward, AArch64 only */
#define SCTLR_F (1U << 10) /* up to v6 */
-#define SCTLR_SW (1U << 10) /* v7, RES0 in v8 */
+#define SCTLR_SW (1U << 10) /* v7 */
+#define SCTLR_EnRCTX (1U << 10) /* in v8.0-PredInv */
#define SCTLR_Z (1U << 11) /* in v7, RES1 in v8 */
#define SCTLR_EOS (1U << 11) /* v8.5-ExS */
#define SCTLR_I (1U << 12)
@@ -1730,6 +1731,27 @@
FIELD(ID_DFR0, PERFMON, 24, 4)
FIELD(ID_DFR0, TRACEFILT, 28, 4)
+FIELD(MVFR0, SIMDREG, 0, 4)
+FIELD(MVFR0, FPSP, 4, 4)
+FIELD(MVFR0, FPDP, 8, 4)
+FIELD(MVFR0, FPTRAP, 12, 4)
+FIELD(MVFR0, FPDIVIDE, 16, 4)
+FIELD(MVFR0, FPSQRT, 20, 4)
+FIELD(MVFR0, FPSHVEC, 24, 4)
+FIELD(MVFR0, FPROUND, 28, 4)
+
+FIELD(MVFR1, FPFTZ, 0, 4)
+FIELD(MVFR1, FPDNAN, 4, 4)
+FIELD(MVFR1, SIMDLS, 8, 4)
+FIELD(MVFR1, SIMDINT, 12, 4)
+FIELD(MVFR1, SIMDSP, 16, 4)
+FIELD(MVFR1, SIMDHP, 20, 4)
+FIELD(MVFR1, FPHP, 24, 4)
+FIELD(MVFR1, SIMDFMAC, 28, 4)
+
+FIELD(MVFR2, SIMDMISC, 0, 4)
+FIELD(MVFR2, FPMISC, 4, 4)
+
QEMU_BUILD_BUG_ON(ARRAY_SIZE(((ARMCPU *)0)->ccsidr) <= R_V7M_CSSELR_INDEX_MASK);
/* If adding a feature bit which corresponds to a Linux ELF
@@ -1747,7 +1769,6 @@
ARM_FEATURE_THUMB2,
ARM_FEATURE_PMSA, /* no MMU; may have Memory Protection Unit */
ARM_FEATURE_VFP3,
- ARM_FEATURE_VFP_FP16,
ARM_FEATURE_NEON,
ARM_FEATURE_M, /* Microcontroller profile. */
ARM_FEATURE_OMAPCP, /* OMAP specific CP15 ops handling. */
@@ -2538,25 +2559,18 @@
/**
* write_cpustate_to_list:
* @cpu: ARMCPU
- * @kvm_sync: true if this is for syncing back to KVM
*
* For each register listed in the ARMCPU cpreg_indexes list, write
* its value from the ARMCPUState structure into the cpreg_values list.
* This is used to copy info from TCG's working data structures into
* KVM or for outbound migration.
*
- * @kvm_sync is true if we are doing this in order to sync the
- * register state back to KVM. In this case we will only update
- * values in the list if the previous list->cpustate sync actually
- * successfully wrote the CPU state. Otherwise we will keep the value
- * that is in the list.
- *
* Returns: true if all register values were read correctly,
* false if some register was unknown or could not be read.
* Note that we do not stop early on failure -- we will attempt
* reading all registers in the list.
*/
-bool write_cpustate_to_list(ARMCPU *cpu, bool kvm_sync);
+bool write_cpustate_to_list(ARMCPU *cpu);
#define ARM_CPUID_TI915T 0x54029152
#define ARM_CPUID_TI925T 0x54029252
@@ -3029,11 +3043,20 @@
(env->cp15.sctlr_el[1] & SCTLR_B) != 0;
}
+static inline uint64_t arm_sctlr(CPUARMState *env, int el)
+{
+ if (el == 0) {
+ /* FIXME: ARMv8.1-VHE S2 translation regime. */
+ return env->cp15.sctlr_el[1];
+ } else {
+ return env->cp15.sctlr_el[el];
+ }
+}
+
+
/* Return true if the processor is in big-endian mode. */
static inline bool arm_cpu_data_is_big_endian(CPUARMState *env)
{
- int cur_el;
-
/* In 32bit endianness is determined by looking at CPSR's E bit */
if (!is_a64(env)) {
return
@@ -3052,15 +3075,12 @@
arm_sctlr_b(env) ||
#endif
((env->uncached_cpsr & CPSR_E) ? 1 : 0);
+ } else {
+ int cur_el = arm_current_el(env);
+ uint64_t sctlr = arm_sctlr(env, cur_el);
+
+ return (sctlr & (cur_el ? SCTLR_EE : SCTLR_E0E)) != 0;
}
-
- cur_el = arm_current_el(env);
-
- if (cur_el == 0) {
- return (env->cp15.sctlr_el[1] & SCTLR_E0E) != 0;
- }
-
- return (env->cp15.sctlr_el[cur_el] & SCTLR_EE) != 0;
}
#include "exec/cpu-all.h"
@@ -3283,6 +3303,21 @@
return FIELD_EX32(id->id_isar6, ID_ISAR6, DP) != 0;
}
+static inline bool isar_feature_aa32_fhm(const ARMISARegisters *id)
+{
+ return FIELD_EX32(id->id_isar6, ID_ISAR6, FHM) != 0;
+}
+
+static inline bool isar_feature_aa32_sb(const ARMISARegisters *id)
+{
+ return FIELD_EX32(id->id_isar6, ID_ISAR6, SB) != 0;
+}
+
+static inline bool isar_feature_aa32_predinv(const ARMISARegisters *id)
+{
+ return FIELD_EX32(id->id_isar6, ID_ISAR6, SPECRES) != 0;
+}
+
static inline bool isar_feature_aa32_fp16_arith(const ARMISARegisters *id)
{
/*
@@ -3294,6 +3329,41 @@
}
/*
+ * We always set the FP and SIMD FP16 fields to indicate identical
+ * levels of support (assuming SIMD is implemented at all), so
+ * we only need one set of accessors.
+ */
+static inline bool isar_feature_aa32_fp16_spconv(const ARMISARegisters *id)
+{
+ return FIELD_EX64(id->mvfr1, MVFR1, FPHP) > 0;
+}
+
+static inline bool isar_feature_aa32_fp16_dpconv(const ARMISARegisters *id)
+{
+ return FIELD_EX64(id->mvfr1, MVFR1, FPHP) > 1;
+}
+
+static inline bool isar_feature_aa32_vsel(const ARMISARegisters *id)
+{
+ return FIELD_EX64(id->mvfr2, MVFR2, FPMISC) >= 1;
+}
+
+static inline bool isar_feature_aa32_vcvt_dr(const ARMISARegisters *id)
+{
+ return FIELD_EX64(id->mvfr2, MVFR2, FPMISC) >= 2;
+}
+
+static inline bool isar_feature_aa32_vrint(const ARMISARegisters *id)
+{
+ return FIELD_EX64(id->mvfr2, MVFR2, FPMISC) >= 3;
+}
+
+static inline bool isar_feature_aa32_vminmaxnm(const ARMISARegisters *id)
+{
+ return FIELD_EX64(id->mvfr2, MVFR2, FPMISC) >= 4;
+}
+
+/*
* 64-bit feature tests via id registers.
*/
static inline bool isar_feature_aa64_aes(const ARMISARegisters *id)
@@ -3356,6 +3426,21 @@
return FIELD_EX64(id->id_aa64isar0, ID_AA64ISAR0, DP) != 0;
}
+static inline bool isar_feature_aa64_fhm(const ARMISARegisters *id)
+{
+ return FIELD_EX64(id->id_aa64isar0, ID_AA64ISAR0, FHM) != 0;
+}
+
+static inline bool isar_feature_aa64_condm_4(const ARMISARegisters *id)
+{
+ return FIELD_EX64(id->id_aa64isar0, ID_AA64ISAR0, TS) != 0;
+}
+
+static inline bool isar_feature_aa64_condm_5(const ARMISARegisters *id)
+{
+ return FIELD_EX64(id->id_aa64isar0, ID_AA64ISAR0, TS) >= 2;
+}
+
static inline bool isar_feature_aa64_jscvt(const ARMISARegisters *id)
{
return FIELD_EX64(id->id_aa64isar1, ID_AA64ISAR1, JSCVT) != 0;
@@ -3381,6 +3466,21 @@
FIELD_DP64(0, ID_AA64ISAR1, GPI, 0xf))) != 0;
}
+static inline bool isar_feature_aa64_sb(const ARMISARegisters *id)
+{
+ return FIELD_EX64(id->id_aa64isar1, ID_AA64ISAR1, SB) != 0;
+}
+
+static inline bool isar_feature_aa64_predinv(const ARMISARegisters *id)
+{
+ return FIELD_EX64(id->id_aa64isar1, ID_AA64ISAR1, SPECRES) != 0;
+}
+
+static inline bool isar_feature_aa64_frint(const ARMISARegisters *id)
+{
+ return FIELD_EX64(id->id_aa64isar1, ID_AA64ISAR1, FRINTTS) != 0;
+}
+
static inline bool isar_feature_aa64_fp16(const ARMISARegisters *id)
{
/* We always set the AdvSIMD and FP fields identically wrt FP16. */
diff --git a/target/arm/cpu64.c b/target/arm/cpu64.c
index 69e4134..228906f 100644
--- a/target/arm/cpu64.c
+++ b/target/arm/cpu64.c
@@ -308,6 +308,8 @@
t = FIELD_DP64(t, ID_AA64ISAR0, SM3, 1);
t = FIELD_DP64(t, ID_AA64ISAR0, SM4, 1);
t = FIELD_DP64(t, ID_AA64ISAR0, DP, 1);
+ t = FIELD_DP64(t, ID_AA64ISAR0, FHM, 1);
+ t = FIELD_DP64(t, ID_AA64ISAR0, TS, 2); /* v8.5-CondM */
cpu->isar.id_aa64isar0 = t;
t = cpu->isar.id_aa64isar1;
@@ -317,6 +319,9 @@
t = FIELD_DP64(t, ID_AA64ISAR1, API, 0);
t = FIELD_DP64(t, ID_AA64ISAR1, GPA, 1);
t = FIELD_DP64(t, ID_AA64ISAR1, GPI, 0);
+ t = FIELD_DP64(t, ID_AA64ISAR1, SB, 1);
+ t = FIELD_DP64(t, ID_AA64ISAR1, SPECRES, 1);
+ t = FIELD_DP64(t, ID_AA64ISAR1, FRINTTS, 1);
cpu->isar.id_aa64isar1 = t;
t = cpu->isar.id_aa64pfr0;
@@ -347,6 +352,9 @@
u = cpu->isar.id_isar6;
u = FIELD_DP32(u, ID_ISAR6, JSCVT, 1);
u = FIELD_DP32(u, ID_ISAR6, DP, 1);
+ u = FIELD_DP32(u, ID_ISAR6, FHM, 1);
+ u = FIELD_DP32(u, ID_ISAR6, SB, 1);
+ u = FIELD_DP32(u, ID_ISAR6, SPECRES, 1);
cpu->isar.id_isar6 = u;
/*
diff --git a/target/arm/helper-a64.c b/target/arm/helper-a64.c
index 70850e5..796ef34 100644
--- a/target/arm/helper-a64.c
+++ b/target/arm/helper-a64.c
@@ -61,6 +61,36 @@
return revbit64(x);
}
+void HELPER(msr_i_spsel)(CPUARMState *env, uint32_t imm)
+{
+ update_spsel(env, imm);
+}
+
+static void daif_check(CPUARMState *env, uint32_t op,
+ uint32_t imm, uintptr_t ra)
+{
+ /* DAIF update to PSTATE. This is OK from EL0 only if UMA is set. */
+ if (arm_current_el(env) == 0 && !(env->cp15.sctlr_el[1] & SCTLR_UMA)) {
+ raise_exception_ra(env, EXCP_UDEF,
+ syn_aa64_sysregtrap(0, extract32(op, 0, 3),
+ extract32(op, 3, 3), 4,
+ imm, 0x1f, 0),
+ exception_target_el(env), ra);
+ }
+}
+
+void HELPER(msr_i_daifset)(CPUARMState *env, uint32_t imm)
+{
+ daif_check(env, 0x1e, imm, GETPC());
+ env->daif |= (imm << 6) & PSTATE_DAIF;
+}
+
+void HELPER(msr_i_daifclear)(CPUARMState *env, uint32_t imm)
+{
+ daif_check(env, 0x1f, imm, GETPC());
+ env->daif &= ~((imm << 6) & PSTATE_DAIF);
+}
+
/* Convert a softfloat float_relation_ (as returned by
* the float*_compare functions) to the correct ARM
* NZCV flag state.
diff --git a/target/arm/helper-a64.h b/target/arm/helper-a64.h
index aff8d6c..a915c12 100644
--- a/target/arm/helper-a64.h
+++ b/target/arm/helper-a64.h
@@ -19,6 +19,9 @@
DEF_HELPER_FLAGS_2(udiv64, TCG_CALL_NO_RWG_SE, i64, i64, i64)
DEF_HELPER_FLAGS_2(sdiv64, TCG_CALL_NO_RWG_SE, s64, s64, s64)
DEF_HELPER_FLAGS_1(rbit64, TCG_CALL_NO_RWG_SE, i64, i64)
+DEF_HELPER_2(msr_i_spsel, void, env, i32)
+DEF_HELPER_2(msr_i_daifset, void, env, i32)
+DEF_HELPER_2(msr_i_daifclear, void, env, i32)
DEF_HELPER_3(vfp_cmph_a64, i64, f16, f16, ptr)
DEF_HELPER_3(vfp_cmpeh_a64, i64, f16, f16, ptr)
DEF_HELPER_3(vfp_cmps_a64, i64, f32, f32, ptr)
diff --git a/target/arm/helper.c b/target/arm/helper.c
index fbaa801..2607d39 100644
--- a/target/arm/helper.c
+++ b/target/arm/helper.c
@@ -265,7 +265,7 @@
return true;
}
-bool write_cpustate_to_list(ARMCPU *cpu, bool kvm_sync)
+bool write_cpustate_to_list(ARMCPU *cpu)
{
/* Write the coprocessor state from cpu->env to the (index,value) list. */
int i;
@@ -274,7 +274,6 @@
for (i = 0; i < cpu->cpreg_array_len; i++) {
uint32_t regidx = kvm_to_cpreg_id(cpu->cpreg_indexes[i]);
const ARMCPRegInfo *ri;
- uint64_t newval;
ri = get_arm_cp_reginfo(cpu->cp_regs, regidx);
if (!ri) {
@@ -284,29 +283,7 @@
if (ri->type & ARM_CP_NO_RAW) {
continue;
}
-
- newval = read_raw_cp_reg(&cpu->env, ri);
- if (kvm_sync) {
- /*
- * Only sync if the previous list->cpustate sync succeeded.
- * Rather than tracking the success/failure state for every
- * item in the list, we just recheck "does the raw write we must
- * have made in write_list_to_cpustate() read back OK" here.
- */
- uint64_t oldval = cpu->cpreg_values[i];
-
- if (oldval == newval) {
- continue;
- }
-
- write_raw_cp_reg(&cpu->env, ri, oldval);
- if (read_raw_cp_reg(&cpu->env, ri) != oldval) {
- continue;
- }
-
- write_raw_cp_reg(&cpu->env, ri, newval);
- }
- cpu->cpreg_values[i] = newval;
+ cpu->cpreg_values[i] = read_raw_cp_reg(&cpu->env, ri);
}
return ok;
}
@@ -5742,6 +5719,50 @@
};
#endif
+static CPAccessResult access_predinv(CPUARMState *env, const ARMCPRegInfo *ri,
+ bool isread)
+{
+ int el = arm_current_el(env);
+
+ if (el == 0) {
+ uint64_t sctlr = arm_sctlr(env, el);
+ if (!(sctlr & SCTLR_EnRCTX)) {
+ return CP_ACCESS_TRAP;
+ }
+ } else if (el == 1) {
+ uint64_t hcr = arm_hcr_el2_eff(env);
+ if (hcr & HCR_NV) {
+ return CP_ACCESS_TRAP_EL2;
+ }
+ }
+ return CP_ACCESS_OK;
+}
+
+static const ARMCPRegInfo predinv_reginfo[] = {
+ { .name = "CFP_RCTX", .state = ARM_CP_STATE_AA64,
+ .opc0 = 1, .opc1 = 3, .crn = 7, .crm = 3, .opc2 = 4,
+ .type = ARM_CP_NOP, .access = PL0_W, .accessfn = access_predinv },
+ { .name = "DVP_RCTX", .state = ARM_CP_STATE_AA64,
+ .opc0 = 1, .opc1 = 3, .crn = 7, .crm = 3, .opc2 = 5,
+ .type = ARM_CP_NOP, .access = PL0_W, .accessfn = access_predinv },
+ { .name = "CPP_RCTX", .state = ARM_CP_STATE_AA64,
+ .opc0 = 1, .opc1 = 3, .crn = 7, .crm = 3, .opc2 = 7,
+ .type = ARM_CP_NOP, .access = PL0_W, .accessfn = access_predinv },
+ /*
+ * Note the AArch32 opcodes have a different OPC1.
+ */
+ { .name = "CFPRCTX", .state = ARM_CP_STATE_AA32,
+ .cp = 15, .opc1 = 0, .crn = 7, .crm = 3, .opc2 = 4,
+ .type = ARM_CP_NOP, .access = PL0_W, .accessfn = access_predinv },
+ { .name = "DVPRCTX", .state = ARM_CP_STATE_AA32,
+ .cp = 15, .opc1 = 0, .crn = 7, .crm = 3, .opc2 = 5,
+ .type = ARM_CP_NOP, .access = PL0_W, .accessfn = access_predinv },
+ { .name = "CPPRCTX", .state = ARM_CP_STATE_AA32,
+ .cp = 15, .opc1 = 0, .crn = 7, .crm = 3, .opc2 = 7,
+ .type = ARM_CP_NOP, .access = PL0_W, .accessfn = access_predinv },
+ REGINFO_SENTINEL
+};
+
void register_cp_regs_for_features(ARMCPU *cpu)
{
/* Register all the coprocessor registers based on feature bits */
@@ -6641,6 +6662,17 @@
define_arm_cp_regs(cpu, pauth_reginfo);
}
#endif
+
+ /*
+ * While all v8.0 cpus support aarch64, QEMU does have configurations
+ * that do not set ID_AA64ISAR1, e.g. user-only qemu-arm -cpu max,
+ * which will set ID_ISAR6.
+ */
+ if (arm_feature(&cpu->env, ARM_FEATURE_AARCH64)
+ ? cpu_isar_feature(aa64_predinv, cpu)
+ : cpu_isar_feature(aa32_predinv, cpu)) {
+ define_arm_cp_regs(cpu, predinv_reginfo);
+ }
}
void arm_cpu_register_gdb_regs_for_features(ARMCPU *cpu)
@@ -12877,12 +12909,8 @@
flags = FIELD_DP32(flags, TBFLAG_A64, ZCR_LEN, zcr_len);
}
- if (current_el == 0) {
- /* FIXME: ARMv8.1-VHE S2 translation regime. */
- sctlr = env->cp15.sctlr_el[1];
- } else {
- sctlr = env->cp15.sctlr_el[current_el];
- }
+ sctlr = arm_sctlr(env, current_el);
+
if (cpu_isar_feature(aa64_pauth, cpu)) {
/*
* In order to save space in flags, we record only whether
diff --git a/target/arm/helper.h b/target/arm/helper.h
index 747cb64..a09566f 100644
--- a/target/arm/helper.h
+++ b/target/arm/helper.h
@@ -77,9 +77,6 @@
DEF_HELPER_3(set_cp_reg64, void, env, ptr, i64)
DEF_HELPER_2(get_cp_reg64, i64, env, ptr)
-DEF_HELPER_3(msr_i_pstate, void, env, i32, i32)
-DEF_HELPER_1(clear_pstate_ss, void, env)
-
DEF_HELPER_2(get_r13_banked, i32, env, i32)
DEF_HELPER_3(set_r13_banked, void, env, i32, i32)
@@ -677,6 +674,20 @@
DEF_HELPER_FLAGS_5(gvec_sqsub_d, TCG_CALL_NO_RWG,
void, ptr, ptr, ptr, ptr, i32)
+DEF_HELPER_FLAGS_5(gvec_fmlal_a32, TCG_CALL_NO_RWG,
+ void, ptr, ptr, ptr, ptr, i32)
+DEF_HELPER_FLAGS_5(gvec_fmlal_a64, TCG_CALL_NO_RWG,
+ void, ptr, ptr, ptr, ptr, i32)
+DEF_HELPER_FLAGS_5(gvec_fmlal_idx_a32, TCG_CALL_NO_RWG,
+ void, ptr, ptr, ptr, ptr, i32)
+DEF_HELPER_FLAGS_5(gvec_fmlal_idx_a64, TCG_CALL_NO_RWG,
+ void, ptr, ptr, ptr, ptr, i32)
+
+DEF_HELPER_FLAGS_2(frint32_s, TCG_CALL_NO_RWG, f32, f32, ptr)
+DEF_HELPER_FLAGS_2(frint64_s, TCG_CALL_NO_RWG, f32, f32, ptr)
+DEF_HELPER_FLAGS_2(frint32_d, TCG_CALL_NO_RWG, f64, f64, ptr)
+DEF_HELPER_FLAGS_2(frint64_d, TCG_CALL_NO_RWG, f64, f64, ptr)
+
#ifdef TARGET_AARCH64
#include "helper-a64.h"
#include "helper-sve.h"
diff --git a/target/arm/internals.h b/target/arm/internals.h
index a4bd1be..587a1dd 100644
--- a/target/arm/internals.h
+++ b/target/arm/internals.h
@@ -968,4 +968,19 @@
ARMVAParameters aa64_va_parameters(CPUARMState *env, uint64_t va,
ARMMMUIdx mmu_idx, bool data);
+static inline int exception_target_el(CPUARMState *env)
+{
+ int target_el = MAX(1, arm_current_el(env));
+
+ /*
+ * No such thing as secure EL1 if EL3 is aarch32,
+ * so update the target EL to EL3 in this case.
+ */
+ if (arm_is_secure(env) && !arm_el_is_aa64(env, 3) && target_el == 1) {
+ target_el = 3;
+ }
+
+ return target_el;
+}
+
#endif
diff --git a/target/arm/kvm.c b/target/arm/kvm.c
index e00ccf9..79a79f0 100644
--- a/target/arm/kvm.c
+++ b/target/arm/kvm.c
@@ -18,6 +18,7 @@
#include "qemu/error-report.h"
#include "sysemu/sysemu.h"
#include "sysemu/kvm.h"
+#include "sysemu/kvm_int.h"
#include "kvm_arm.h"
#include "cpu.h"
#include "trace.h"
@@ -162,6 +163,15 @@
env->features = arm_host_cpu_features.features;
}
+int kvm_arm_get_max_vm_ipa_size(MachineState *ms)
+{
+ KVMState *s = KVM_STATE(ms->accelerator);
+ int ret;
+
+ ret = kvm_check_extension(s, KVM_CAP_ARM_VM_IPA_SIZE);
+ return ret > 0 ? ret : 40;
+}
+
int kvm_arch_init(MachineState *ms, KVMState *s)
{
/* For ARM interrupt delivery is always asynchronous,
diff --git a/target/arm/kvm32.c b/target/arm/kvm32.c
index a75e04c..5032798 100644
--- a/target/arm/kvm32.c
+++ b/target/arm/kvm32.c
@@ -125,9 +125,6 @@
if (extract32(id_pfr0, 12, 4) == 1) {
set_feature(&features, ARM_FEATURE_THUMB2EE);
}
- if (extract32(ahcf->isar.mvfr1, 20, 4) == 1) {
- set_feature(&features, ARM_FEATURE_VFP_FP16);
- }
if (extract32(ahcf->isar.mvfr1, 12, 4) == 1) {
set_feature(&features, ARM_FEATURE_NEON);
}
@@ -387,8 +384,24 @@
return ret;
}
- write_cpustate_to_list(cpu, true);
-
+ /* Note that we do not call write_cpustate_to_list()
+ * here, so we are only writing the tuple list back to
+ * KVM. This is safe because nothing can change the
+ * CPUARMState cp15 fields (in particular gdb accesses cannot)
+ * and so there are no changes to sync. In fact syncing would
+ * be wrong at this point: for a constant register where TCG and
+ * KVM disagree about its value, the preceding write_list_to_cpustate()
+ * would not have had any effect on the CPUARMState value (since the
+ * register is read-only), and a write_cpustate_to_list() here would
+ * then try to write the TCG value back into KVM -- this would either
+ * fail or incorrectly change the value the guest sees.
+ *
+ * If we ever want to allow the user to modify cp15 registers via
+ * the gdb stub, we would need to be more clever here (for instance
+ * tracking the set of registers kvm_arch_get_registers() successfully
+ * managed to update the CPUARMState with, and only allowing those
+ * to be written back up into the kernel).
+ */
if (!write_list_to_kvmstate(cpu, level)) {
return EINVAL;
}
diff --git a/target/arm/kvm64.c b/target/arm/kvm64.c
index e3ba149..089af9c 100644
--- a/target/arm/kvm64.c
+++ b/target/arm/kvm64.c
@@ -838,8 +838,6 @@
return ret;
}
- write_cpustate_to_list(cpu, true);
-
if (!write_list_to_kvmstate(cpu, level)) {
return EINVAL;
}
diff --git a/target/arm/kvm_arm.h b/target/arm/kvm_arm.h
index 6393455..2a07333 100644
--- a/target/arm/kvm_arm.h
+++ b/target/arm/kvm_arm.h
@@ -208,6 +208,14 @@
void kvm_arm_set_cpu_features_from_host(ARMCPU *cpu);
/**
+ * kvm_arm_get_max_vm_ipa_size - Returns the number of bits in the
+ * IPA address space supported by KVM
+ *
+ * @ms: Machine state handle
+ */
+int kvm_arm_get_max_vm_ipa_size(MachineState *ms);
+
+/**
* kvm_arm_sync_mpstate_to_kvm
* @cpu: ARMCPU
*
@@ -239,6 +247,11 @@
cpu->host_cpu_probe_failed = true;
}
+static inline int kvm_arm_get_max_vm_ipa_size(MachineState *ms)
+{
+ return -ENOENT;
+}
+
static inline int kvm_arm_vgic_probe(void)
{
return 0;
diff --git a/target/arm/machine.c b/target/arm/machine.c
index 124192b..b292549 100644
--- a/target/arm/machine.c
+++ b/target/arm/machine.c
@@ -630,7 +630,7 @@
abort();
}
} else {
- if (!write_cpustate_to_list(cpu, false)) {
+ if (!write_cpustate_to_list(cpu)) {
/* This should never fail. */
abort();
}
diff --git a/target/arm/op_helper.c b/target/arm/op_helper.c
index c998ead..8698b4d 100644
--- a/target/arm/op_helper.c
+++ b/target/arm/op_helper.c
@@ -68,20 +68,6 @@
cpu_loop_exit_restore(cs, ra);
}
-static int exception_target_el(CPUARMState *env)
-{
- int target_el = MAX(1, arm_current_el(env));
-
- /* No such thing as secure EL1 if EL3 is aarch32, so update the target EL
- * to EL3 in this case.
- */
- if (arm_is_secure(env) && !arm_el_is_aa64(env, 3) && target_el == 1) {
- target_el = 3;
- }
-
- return target_el;
-}
-
uint32_t HELPER(neon_tbl)(uint32_t ireg, uint32_t def, void *vn,
uint32_t maxindex)
{
@@ -875,39 +861,6 @@
return res;
}
-void HELPER(msr_i_pstate)(CPUARMState *env, uint32_t op, uint32_t imm)
-{
- /* MSR_i to update PSTATE. This is OK from EL0 only if UMA is set.
- * Note that SPSel is never OK from EL0; we rely on handle_msr_i()
- * to catch that case at translate time.
- */
- if (arm_current_el(env) == 0 && !(env->cp15.sctlr_el[1] & SCTLR_UMA)) {
- uint32_t syndrome = syn_aa64_sysregtrap(0, extract32(op, 0, 3),
- extract32(op, 3, 3), 4,
- imm, 0x1f, 0);
- raise_exception(env, EXCP_UDEF, syndrome, exception_target_el(env));
- }
-
- switch (op) {
- case 0x05: /* SPSel */
- update_spsel(env, imm);
- break;
- case 0x1e: /* DAIFSet */
- env->daif |= (imm << 6) & PSTATE_DAIF;
- break;
- case 0x1f: /* DAIFClear */
- env->daif &= ~((imm << 6) & PSTATE_DAIF);
- break;
- default:
- g_assert_not_reached();
- }
-}
-
-void HELPER(clear_pstate_ss)(CPUARMState *env)
-{
- env->pstate &= ~PSTATE_SS;
-}
-
void HELPER(pre_hvc)(CPUARMState *env)
{
ARMCPU *cpu = arm_env_get_cpu(env);
diff --git a/target/arm/translate-a64.c b/target/arm/translate-a64.c
index c56e878..1959046 100644
--- a/target/arm/translate-a64.c
+++ b/target/arm/translate-a64.c
@@ -421,17 +421,6 @@
s->base.is_jmp = DISAS_NORETURN;
}
-static void gen_ss_advance(DisasContext *s)
-{
- /* If the singlestep state is Active-not-pending, advance to
- * Active-pending.
- */
- if (s->ss_active) {
- s->pstate_ss = 0;
- gen_helper_clear_pstate_ss(cpu_env);
- }
-}
-
static void gen_step_complete_exception(DisasContext *s)
{
/* We just completed step of an insn. Move from Active-not-pending
@@ -1637,39 +1626,128 @@
reset_btype(s);
gen_goto_tb(s, 0, s->pc);
return;
+
+ case 7: /* SB */
+ if (crm != 0 || !dc_isar_feature(aa64_sb, s)) {
+ goto do_unallocated;
+ }
+ /*
+ * TODO: There is no speculation barrier opcode for TCG;
+ * MB and end the TB instead.
+ */
+ tcg_gen_mb(TCG_MO_ALL | TCG_BAR_SC);
+ gen_goto_tb(s, 0, s->pc);
+ return;
+
default:
+ do_unallocated:
unallocated_encoding(s);
return;
}
}
+static void gen_xaflag(void)
+{
+ TCGv_i32 z = tcg_temp_new_i32();
+
+ tcg_gen_setcondi_i32(TCG_COND_EQ, z, cpu_ZF, 0);
+
+ /*
+ * (!C & !Z) << 31
+ * (!(C | Z)) << 31
+ * ~((C | Z) << 31)
+ * ~-(C | Z)
+ * (C | Z) - 1
+ */
+ tcg_gen_or_i32(cpu_NF, cpu_CF, z);
+ tcg_gen_subi_i32(cpu_NF, cpu_NF, 1);
+
+ /* !(Z & C) */
+ tcg_gen_and_i32(cpu_ZF, z, cpu_CF);
+ tcg_gen_xori_i32(cpu_ZF, cpu_ZF, 1);
+
+ /* (!C & Z) << 31 -> -(Z & ~C) */
+ tcg_gen_andc_i32(cpu_VF, z, cpu_CF);
+ tcg_gen_neg_i32(cpu_VF, cpu_VF);
+
+ /* C | Z */
+ tcg_gen_or_i32(cpu_CF, cpu_CF, z);
+
+ tcg_temp_free_i32(z);
+}
+
+static void gen_axflag(void)
+{
+ tcg_gen_sari_i32(cpu_VF, cpu_VF, 31); /* V ? -1 : 0 */
+ tcg_gen_andc_i32(cpu_CF, cpu_CF, cpu_VF); /* C & !V */
+
+ /* !(Z | V) -> !(!ZF | V) -> ZF & !V -> ZF & ~VF */
+ tcg_gen_andc_i32(cpu_ZF, cpu_ZF, cpu_VF);
+
+ tcg_gen_movi_i32(cpu_NF, 0);
+ tcg_gen_movi_i32(cpu_VF, 0);
+}
+
/* MSR (immediate) - move immediate to processor state field */
static void handle_msr_i(DisasContext *s, uint32_t insn,
unsigned int op1, unsigned int op2, unsigned int crm)
{
+ TCGv_i32 t1;
int op = op1 << 3 | op2;
+
+ /* End the TB by default, chaining is ok. */
+ s->base.is_jmp = DISAS_TOO_MANY;
+
switch (op) {
+ case 0x00: /* CFINV */
+ if (crm != 0 || !dc_isar_feature(aa64_condm_4, s)) {
+ goto do_unallocated;
+ }
+ tcg_gen_xori_i32(cpu_CF, cpu_CF, 1);
+ s->base.is_jmp = DISAS_NEXT;
+ break;
+
+ case 0x01: /* XAFlag */
+ if (crm != 0 || !dc_isar_feature(aa64_condm_5, s)) {
+ goto do_unallocated;
+ }
+ gen_xaflag();
+ s->base.is_jmp = DISAS_NEXT;
+ break;
+
+ case 0x02: /* AXFlag */
+ if (crm != 0 || !dc_isar_feature(aa64_condm_5, s)) {
+ goto do_unallocated;
+ }
+ gen_axflag();
+ s->base.is_jmp = DISAS_NEXT;
+ break;
+
case 0x05: /* SPSel */
if (s->current_el == 0) {
- unallocated_encoding(s);
- return;
+ goto do_unallocated;
}
- /* fall through */
- case 0x1e: /* DAIFSet */
- case 0x1f: /* DAIFClear */
- {
- TCGv_i32 tcg_imm = tcg_const_i32(crm);
- TCGv_i32 tcg_op = tcg_const_i32(op);
- gen_a64_set_pc_im(s->pc - 4);
- gen_helper_msr_i_pstate(cpu_env, tcg_op, tcg_imm);
- tcg_temp_free_i32(tcg_imm);
- tcg_temp_free_i32(tcg_op);
- /* For DAIFClear, exit the cpu loop to re-evaluate pending IRQs. */
- gen_a64_set_pc_im(s->pc);
- s->base.is_jmp = (op == 0x1f ? DISAS_EXIT : DISAS_JUMP);
+ t1 = tcg_const_i32(crm & PSTATE_SP);
+ gen_helper_msr_i_spsel(cpu_env, t1);
+ tcg_temp_free_i32(t1);
break;
- }
+
+ case 0x1e: /* DAIFSet */
+ t1 = tcg_const_i32(crm);
+ gen_helper_msr_i_daifset(cpu_env, t1);
+ tcg_temp_free_i32(t1);
+ break;
+
+ case 0x1f: /* DAIFClear */
+ t1 = tcg_const_i32(crm);
+ gen_helper_msr_i_daifclear(cpu_env, t1);
+ tcg_temp_free_i32(t1);
+ /* For DAIFClear, exit the cpu loop to re-evaluate pending IRQs. */
+ s->base.is_jmp = DISAS_UPDATE;
+ break;
+
default:
+ do_unallocated:
unallocated_encoding(s);
return;
}
@@ -1698,7 +1776,6 @@
}
static void gen_set_nzcv(TCGv_i64 tcg_rt)
-
{
TCGv_i32 nzcv = tcg_temp_new_i32();
@@ -4482,11 +4559,10 @@
}
/* Add/subtract (with carry)
- * 31 30 29 28 27 26 25 24 23 22 21 20 16 15 10 9 5 4 0
- * +--+--+--+------------------------+------+---------+------+-----+
- * |sf|op| S| 1 1 0 1 0 0 0 0 | rm | opcode2 | Rn | Rd |
- * +--+--+--+------------------------+------+---------+------+-----+
- * [000000]
+ * 31 30 29 28 27 26 25 24 23 22 21 20 16 15 10 9 5 4 0
+ * +--+--+--+------------------------+------+-------------+------+-----+
+ * |sf|op| S| 1 1 0 1 0 0 0 0 | rm | 0 0 0 0 0 0 | Rn | Rd |
+ * +--+--+--+------------------------+------+-------------+------+-----+
*/
static void disas_adc_sbc(DisasContext *s, uint32_t insn)
@@ -4494,11 +4570,6 @@
unsigned int sf, op, setflags, rm, rn, rd;
TCGv_i64 tcg_y, tcg_rn, tcg_rd;
- if (extract32(insn, 10, 6) != 0) {
- unallocated_encoding(s);
- return;
- }
-
sf = extract32(insn, 31, 1);
op = extract32(insn, 30, 1);
setflags = extract32(insn, 29, 1);
@@ -4523,6 +4594,84 @@
}
}
+/*
+ * Rotate right into flags
+ * 31 30 29 21 15 10 5 4 0
+ * +--+--+--+-----------------+--------+-----------+------+--+------+
+ * |sf|op| S| 1 1 0 1 0 0 0 0 | imm6 | 0 0 0 0 1 | Rn |o2| mask |
+ * +--+--+--+-----------------+--------+-----------+------+--+------+
+ */
+static void disas_rotate_right_into_flags(DisasContext *s, uint32_t insn)
+{
+ int mask = extract32(insn, 0, 4);
+ int o2 = extract32(insn, 4, 1);
+ int rn = extract32(insn, 5, 5);
+ int imm6 = extract32(insn, 15, 6);
+ int sf_op_s = extract32(insn, 29, 3);
+ TCGv_i64 tcg_rn;
+ TCGv_i32 nzcv;
+
+ if (sf_op_s != 5 || o2 != 0 || !dc_isar_feature(aa64_condm_4, s)) {
+ unallocated_encoding(s);
+ return;
+ }
+
+ tcg_rn = read_cpu_reg(s, rn, 1);
+ tcg_gen_rotri_i64(tcg_rn, tcg_rn, imm6);
+
+ nzcv = tcg_temp_new_i32();
+ tcg_gen_extrl_i64_i32(nzcv, tcg_rn);
+
+ if (mask & 8) { /* N */
+ tcg_gen_shli_i32(cpu_NF, nzcv, 31 - 3);
+ }
+ if (mask & 4) { /* Z */
+ tcg_gen_not_i32(cpu_ZF, nzcv);
+ tcg_gen_andi_i32(cpu_ZF, cpu_ZF, 4);
+ }
+ if (mask & 2) { /* C */
+ tcg_gen_extract_i32(cpu_CF, nzcv, 1, 1);
+ }
+ if (mask & 1) { /* V */
+ tcg_gen_shli_i32(cpu_VF, nzcv, 31 - 0);
+ }
+
+ tcg_temp_free_i32(nzcv);
+}
+
+/*
+ * Evaluate into flags
+ * 31 30 29 21 15 14 10 5 4 0
+ * +--+--+--+-----------------+---------+----+---------+------+--+------+
+ * |sf|op| S| 1 1 0 1 0 0 0 0 | opcode2 | sz | 0 0 1 0 | Rn |o3| mask |
+ * +--+--+--+-----------------+---------+----+---------+------+--+------+
+ */
+static void disas_evaluate_into_flags(DisasContext *s, uint32_t insn)
+{
+ int o3_mask = extract32(insn, 0, 5);
+ int rn = extract32(insn, 5, 5);
+ int o2 = extract32(insn, 15, 6);
+ int sz = extract32(insn, 14, 1);
+ int sf_op_s = extract32(insn, 29, 3);
+ TCGv_i32 tmp;
+ int shift;
+
+ if (sf_op_s != 1 || o2 != 0 || o3_mask != 0xd ||
+ !dc_isar_feature(aa64_condm_4, s)) {
+ unallocated_encoding(s);
+ return;
+ }
+ shift = sz ? 16 : 24; /* SETF16 or SETF8 */
+
+ tmp = tcg_temp_new_i32();
+ tcg_gen_extrl_i64_i32(tmp, cpu_reg(s, rn));
+ tcg_gen_shli_i32(cpu_NF, tmp, shift);
+ tcg_gen_shli_i32(cpu_VF, tmp, shift - 1);
+ tcg_gen_mov_i32(cpu_ZF, cpu_NF);
+ tcg_gen_xor_i32(cpu_VF, cpu_VF, cpu_NF);
+ tcg_temp_free_i32(tmp);
+}
+
/* Conditional compare (immediate / register)
* 31 30 29 28 27 26 25 24 23 22 21 20 16 15 12 11 10 9 5 4 3 0
* +--+--+--+------------------------+--------+------+----+--+------+--+-----+
@@ -5152,47 +5301,81 @@
}
}
-/* Data processing - register */
+/*
+ * Data processing - register
+ * 31 30 29 28 25 21 20 16 10 0
+ * +--+---+--+---+-------+-----+-------+-------+---------+
+ * | |op0| |op1| 1 0 1 | op2 | | op3 | |
+ * +--+---+--+---+-------+-----+-------+-------+---------+
+ */
static void disas_data_proc_reg(DisasContext *s, uint32_t insn)
{
- switch (extract32(insn, 24, 5)) {
- case 0x0a: /* Logical (shifted register) */
- disas_logic_reg(s, insn);
- break;
- case 0x0b: /* Add/subtract */
- if (insn & (1 << 21)) { /* (extended register) */
- disas_add_sub_ext_reg(s, insn);
+ int op0 = extract32(insn, 30, 1);
+ int op1 = extract32(insn, 28, 1);
+ int op2 = extract32(insn, 21, 4);
+ int op3 = extract32(insn, 10, 6);
+
+ if (!op1) {
+ if (op2 & 8) {
+ if (op2 & 1) {
+ /* Add/sub (extended register) */
+ disas_add_sub_ext_reg(s, insn);
+ } else {
+ /* Add/sub (shifted register) */
+ disas_add_sub_reg(s, insn);
+ }
} else {
- disas_add_sub_reg(s, insn);
+ /* Logical (shifted register) */
+ disas_logic_reg(s, insn);
}
- break;
- case 0x1b: /* Data-processing (3 source) */
- disas_data_proc_3src(s, insn);
- break;
- case 0x1a:
- switch (extract32(insn, 21, 3)) {
- case 0x0: /* Add/subtract (with carry) */
+ return;
+ }
+
+ switch (op2) {
+ case 0x0:
+ switch (op3) {
+ case 0x00: /* Add/subtract (with carry) */
disas_adc_sbc(s, insn);
break;
- case 0x2: /* Conditional compare */
- disas_cc(s, insn); /* both imm and reg forms */
+
+ case 0x01: /* Rotate right into flags */
+ case 0x21:
+ disas_rotate_right_into_flags(s, insn);
break;
- case 0x4: /* Conditional select */
- disas_cond_select(s, insn);
+
+ case 0x02: /* Evaluate into flags */
+ case 0x12:
+ case 0x22:
+ case 0x32:
+ disas_evaluate_into_flags(s, insn);
break;
- case 0x6: /* Data-processing */
- if (insn & (1 << 30)) { /* (1 source) */
- disas_data_proc_1src(s, insn);
- } else { /* (2 source) */
- disas_data_proc_2src(s, insn);
- }
- break;
+
default:
- unallocated_encoding(s);
- break;
+ goto do_unallocated;
}
break;
+
+ case 0x2: /* Conditional compare */
+ disas_cc(s, insn); /* both imm and reg forms */
+ break;
+
+ case 0x4: /* Conditional select */
+ disas_cond_select(s, insn);
+ break;
+
+ case 0x6: /* Data-processing */
+ if (op0) { /* (1 source) */
+ disas_data_proc_1src(s, insn);
+ } else { /* (2 source) */
+ disas_data_proc_2src(s, insn);
+ }
+ break;
+ case 0x8 ... 0xf: /* (3 source) */
+ disas_data_proc_3src(s, insn);
+ break;
+
default:
+ do_unallocated:
unallocated_encoding(s);
break;
}
@@ -5505,55 +5688,73 @@
/* Floating-point data-processing (1 source) - single precision */
static void handle_fp_1src_single(DisasContext *s, int opcode, int rd, int rn)
{
+ void (*gen_fpst)(TCGv_i32, TCGv_i32, TCGv_ptr);
+ TCGv_i32 tcg_op, tcg_res;
TCGv_ptr fpst;
- TCGv_i32 tcg_op;
- TCGv_i32 tcg_res;
+ int rmode = -1;
- fpst = get_fpstatus_ptr(false);
tcg_op = read_fp_sreg(s, rn);
tcg_res = tcg_temp_new_i32();
switch (opcode) {
case 0x0: /* FMOV */
tcg_gen_mov_i32(tcg_res, tcg_op);
- break;
+ goto done;
case 0x1: /* FABS */
gen_helper_vfp_abss(tcg_res, tcg_op);
- break;
+ goto done;
case 0x2: /* FNEG */
gen_helper_vfp_negs(tcg_res, tcg_op);
- break;
+ goto done;
case 0x3: /* FSQRT */
gen_helper_vfp_sqrts(tcg_res, tcg_op, cpu_env);
- break;
+ goto done;
case 0x8: /* FRINTN */
case 0x9: /* FRINTP */
case 0xa: /* FRINTM */
case 0xb: /* FRINTZ */
case 0xc: /* FRINTA */
- {
- TCGv_i32 tcg_rmode = tcg_const_i32(arm_rmode_to_sf(opcode & 7));
-
- gen_helper_set_rmode(tcg_rmode, tcg_rmode, fpst);
- gen_helper_rints(tcg_res, tcg_op, fpst);
-
- gen_helper_set_rmode(tcg_rmode, tcg_rmode, fpst);
- tcg_temp_free_i32(tcg_rmode);
+ rmode = arm_rmode_to_sf(opcode & 7);
+ gen_fpst = gen_helper_rints;
break;
- }
case 0xe: /* FRINTX */
- gen_helper_rints_exact(tcg_res, tcg_op, fpst);
+ gen_fpst = gen_helper_rints_exact;
break;
case 0xf: /* FRINTI */
- gen_helper_rints(tcg_res, tcg_op, fpst);
+ gen_fpst = gen_helper_rints;
+ break;
+ case 0x10: /* FRINT32Z */
+ rmode = float_round_to_zero;
+ gen_fpst = gen_helper_frint32_s;
+ break;
+ case 0x11: /* FRINT32X */
+ gen_fpst = gen_helper_frint32_s;
+ break;
+ case 0x12: /* FRINT64Z */
+ rmode = float_round_to_zero;
+ gen_fpst = gen_helper_frint64_s;
+ break;
+ case 0x13: /* FRINT64X */
+ gen_fpst = gen_helper_frint64_s;
break;
default:
- abort();
+ g_assert_not_reached();
}
- write_fp_sreg(s, rd, tcg_res);
-
+ fpst = get_fpstatus_ptr(false);
+ if (rmode >= 0) {
+ TCGv_i32 tcg_rmode = tcg_const_i32(rmode);
+ gen_helper_set_rmode(tcg_rmode, tcg_rmode, fpst);
+ gen_fpst(tcg_res, tcg_op, fpst);
+ gen_helper_set_rmode(tcg_rmode, tcg_rmode, fpst);
+ tcg_temp_free_i32(tcg_rmode);
+ } else {
+ gen_fpst(tcg_res, tcg_op, fpst);
+ }
tcg_temp_free_ptr(fpst);
+
+ done:
+ write_fp_sreg(s, rd, tcg_res);
tcg_temp_free_i32(tcg_op);
tcg_temp_free_i32(tcg_res);
}
@@ -5561,9 +5762,10 @@
/* Floating-point data-processing (1 source) - double precision */
static void handle_fp_1src_double(DisasContext *s, int opcode, int rd, int rn)
{
+ void (*gen_fpst)(TCGv_i64, TCGv_i64, TCGv_ptr);
+ TCGv_i64 tcg_op, tcg_res;
TCGv_ptr fpst;
- TCGv_i64 tcg_op;
- TCGv_i64 tcg_res;
+ int rmode = -1;
switch (opcode) {
case 0x0: /* FMOV */
@@ -5571,48 +5773,65 @@
return;
}
- fpst = get_fpstatus_ptr(false);
tcg_op = read_fp_dreg(s, rn);
tcg_res = tcg_temp_new_i64();
switch (opcode) {
case 0x1: /* FABS */
gen_helper_vfp_absd(tcg_res, tcg_op);
- break;
+ goto done;
case 0x2: /* FNEG */
gen_helper_vfp_negd(tcg_res, tcg_op);
- break;
+ goto done;
case 0x3: /* FSQRT */
gen_helper_vfp_sqrtd(tcg_res, tcg_op, cpu_env);
- break;
+ goto done;
case 0x8: /* FRINTN */
case 0x9: /* FRINTP */
case 0xa: /* FRINTM */
case 0xb: /* FRINTZ */
case 0xc: /* FRINTA */
- {
- TCGv_i32 tcg_rmode = tcg_const_i32(arm_rmode_to_sf(opcode & 7));
-
- gen_helper_set_rmode(tcg_rmode, tcg_rmode, fpst);
- gen_helper_rintd(tcg_res, tcg_op, fpst);
-
- gen_helper_set_rmode(tcg_rmode, tcg_rmode, fpst);
- tcg_temp_free_i32(tcg_rmode);
+ rmode = arm_rmode_to_sf(opcode & 7);
+ gen_fpst = gen_helper_rintd;
break;
- }
case 0xe: /* FRINTX */
- gen_helper_rintd_exact(tcg_res, tcg_op, fpst);
+ gen_fpst = gen_helper_rintd_exact;
break;
case 0xf: /* FRINTI */
- gen_helper_rintd(tcg_res, tcg_op, fpst);
+ gen_fpst = gen_helper_rintd;
+ break;
+ case 0x10: /* FRINT32Z */
+ rmode = float_round_to_zero;
+ gen_fpst = gen_helper_frint32_d;
+ break;
+ case 0x11: /* FRINT32X */
+ gen_fpst = gen_helper_frint32_d;
+ break;
+ case 0x12: /* FRINT64Z */
+ rmode = float_round_to_zero;
+ gen_fpst = gen_helper_frint64_d;
+ break;
+ case 0x13: /* FRINT64X */
+ gen_fpst = gen_helper_frint64_d;
break;
default:
- abort();
+ g_assert_not_reached();
}
- write_fp_dreg(s, rd, tcg_res);
-
+ fpst = get_fpstatus_ptr(false);
+ if (rmode >= 0) {
+ TCGv_i32 tcg_rmode = tcg_const_i32(rmode);
+ gen_helper_set_rmode(tcg_rmode, tcg_rmode, fpst);
+ gen_fpst(tcg_res, tcg_op, fpst);
+ gen_helper_set_rmode(tcg_rmode, tcg_rmode, fpst);
+ tcg_temp_free_i32(tcg_rmode);
+ } else {
+ gen_fpst(tcg_res, tcg_op, fpst);
+ }
tcg_temp_free_ptr(fpst);
+
+ done:
+ write_fp_dreg(s, rd, tcg_res);
tcg_temp_free_i64(tcg_op);
tcg_temp_free_i64(tcg_res);
}
@@ -5731,6 +5950,13 @@
handle_fp_fcvt(s, opcode, rd, rn, dtype, type);
break;
}
+
+ case 0x10 ... 0x13: /* FRINT{32,64}{X,Z} */
+ if (type > 1 || !dc_isar_feature(aa64_frint, s)) {
+ unallocated_encoding(s);
+ return;
+ }
+ /* fall through */
case 0x0 ... 0x3:
case 0x8 ... 0xc:
case 0xe ... 0xf:
@@ -5740,14 +5966,12 @@
if (!fp_access_check(s)) {
return;
}
-
handle_fp_1src_single(s, opcode, rd, rn);
break;
case 1:
if (!fp_access_check(s)) {
return;
}
-
handle_fp_1src_double(s, opcode, rd, rn);
break;
case 3:
@@ -5759,13 +5983,13 @@
if (!fp_access_check(s)) {
return;
}
-
handle_fp_1src_half(s, opcode, rd, rn);
break;
default:
unallocated_encoding(s);
}
break;
+
default:
unallocated_encoding(s);
break;
@@ -9293,6 +9517,14 @@
case 0x59: /* FRINTX */
gen_helper_rintd_exact(tcg_rd, tcg_rn, tcg_fpstatus);
break;
+ case 0x1e: /* FRINT32Z */
+ case 0x5e: /* FRINT32X */
+ gen_helper_frint32_d(tcg_rd, tcg_rn, tcg_fpstatus);
+ break;
+ case 0x1f: /* FRINT64Z */
+ case 0x5f: /* FRINT64X */
+ gen_helper_frint64_d(tcg_rd, tcg_rn, tcg_fpstatus);
+ break;
default:
g_assert_not_reached();
}
@@ -10917,9 +11149,29 @@
if (!fp_access_check(s)) {
return;
}
-
handle_3same_float(s, size, elements, fpopcode, rd, rn, rm);
return;
+
+ case 0x1d: /* FMLAL */
+ case 0x3d: /* FMLSL */
+ case 0x59: /* FMLAL2 */
+ case 0x79: /* FMLSL2 */
+ if (size & 1 || !dc_isar_feature(aa64_fhm, s)) {
+ unallocated_encoding(s);
+ return;
+ }
+ if (fp_access_check(s)) {
+ int is_s = extract32(insn, 23, 1);
+ int is_2 = extract32(insn, 29, 1);
+ int data = (is_2 << 1) | is_s;
+ tcg_gen_gvec_3_ptr(vec_full_reg_offset(s, rd),
+ vec_full_reg_offset(s, rn),
+ vec_full_reg_offset(s, rm), cpu_env,
+ is_q ? 16 : 8, vec_full_reg_size(s),
+ data, gen_helper_gvec_fmlal_a64);
+ }
+ return;
+
default:
unallocated_encoding(s);
return;
@@ -11923,8 +12175,7 @@
}
break;
case 0xc ... 0xf:
- case 0x16 ... 0x1d:
- case 0x1f:
+ case 0x16 ... 0x1f:
{
/* Floating point: U, size[1] and opcode indicate operation;
* size[0] indicates single or double precision.
@@ -12067,6 +12318,19 @@
}
need_fpstatus = true;
break;
+ case 0x1e: /* FRINT32Z */
+ case 0x1f: /* FRINT64Z */
+ need_rmode = true;
+ rmode = FPROUNDING_ZERO;
+ /* fall through */
+ case 0x5e: /* FRINT32X */
+ case 0x5f: /* FRINT64X */
+ need_fpstatus = true;
+ if ((size == 3 && !is_q) || !dc_isar_feature(aa64_frint, s)) {
+ unallocated_encoding(s);
+ return;
+ }
+ break;
default:
unallocated_encoding(s);
return;
@@ -12232,6 +12496,14 @@
case 0x7c: /* URSQRTE */
gen_helper_rsqrte_u32(tcg_res, tcg_op, tcg_fpstatus);
break;
+ case 0x1e: /* FRINT32Z */
+ case 0x5e: /* FRINT32X */
+ gen_helper_frint32_s(tcg_res, tcg_op, tcg_fpstatus);
+ break;
+ case 0x1f: /* FRINT64Z */
+ case 0x5f: /* FRINT64X */
+ gen_helper_frint64_s(tcg_res, tcg_op, tcg_fpstatus);
+ break;
default:
g_assert_not_reached();
}
@@ -12739,6 +13011,17 @@
}
is_fp = 2;
break;
+ case 0x00: /* FMLAL */
+ case 0x04: /* FMLSL */
+ case 0x18: /* FMLAL2 */
+ case 0x1c: /* FMLSL2 */
+ if (is_scalar || size != MO_32 || !dc_isar_feature(aa64_fhm, s)) {
+ unallocated_encoding(s);
+ return;
+ }
+ size = MO_16;
+ /* is_fp, but we pass cpu_env not fp_status. */
+ break;
default:
unallocated_encoding(s);
return;
@@ -12849,6 +13132,22 @@
tcg_temp_free_ptr(fpst);
}
return;
+
+ case 0x00: /* FMLAL */
+ case 0x04: /* FMLSL */
+ case 0x18: /* FMLAL2 */
+ case 0x1c: /* FMLSL2 */
+ {
+ int is_s = extract32(opcode, 2, 1);
+ int is_2 = u;
+ int data = (index << 2) | (is_2 << 1) | is_s;
+ tcg_gen_gvec_3_ptr(vec_full_reg_offset(s, rd),
+ vec_full_reg_offset(s, rn),
+ vec_full_reg_offset(s, rm), cpu_env,
+ is_q ? 16 : 8, vec_full_reg_size(s),
+ data, gen_helper_gvec_fmlal_idx_a64);
+ }
+ return;
}
if (size == 3) {
diff --git a/target/arm/translate.c b/target/arm/translate.c
index c117579..d408e4d 100644
--- a/target/arm/translate.c
+++ b/target/arm/translate.c
@@ -298,17 +298,6 @@
tcg_temp_free_i32(tcg_excp);
}
-static void gen_ss_advance(DisasContext *s)
-{
- /* If the singlestep state is Active-not-pending, advance to
- * Active-pending.
- */
- if (s->ss_active) {
- s->pstate_ss = 0;
- gen_helper_clear_pstate_ss(cpu_env);
- }
-}
-
static void gen_step_complete_exception(DisasContext *s)
{
/* We just completed step of an insn. Move from Active-not-pending
@@ -3357,14 +3346,10 @@
FPROUNDING_NEGINF,
};
-static int disas_vfp_v8_insn(DisasContext *s, uint32_t insn)
+static int disas_vfp_misc_insn(DisasContext *s, uint32_t insn)
{
uint32_t rd, rn, rm, dp = extract32(insn, 8, 1);
- if (!arm_dc_feature(s, ARM_FEATURE_V8)) {
- return 1;
- }
-
if (dp) {
VFP_DREG_D(rd, insn);
VFP_DREG_N(rn, insn);
@@ -3375,15 +3360,18 @@
rm = VFP_SREG_M(insn);
}
- if ((insn & 0x0f800e50) == 0x0e000a00) {
+ if ((insn & 0x0f800e50) == 0x0e000a00 && dc_isar_feature(aa32_vsel, s)) {
return handle_vsel(insn, rd, rn, rm, dp);
- } else if ((insn & 0x0fb00e10) == 0x0e800a00) {
+ } else if ((insn & 0x0fb00e10) == 0x0e800a00 &&
+ dc_isar_feature(aa32_vminmaxnm, s)) {
return handle_vminmaxnm(insn, rd, rn, rm, dp);
- } else if ((insn & 0x0fbc0ed0) == 0x0eb80a40) {
+ } else if ((insn & 0x0fbc0ed0) == 0x0eb80a40 &&
+ dc_isar_feature(aa32_vrint, s)) {
/* VRINTA, VRINTN, VRINTP, VRINTM */
int rounding = fp_decode_rm[extract32(insn, 16, 2)];
return handle_vrint(insn, rd, rm, dp, rounding);
- } else if ((insn & 0x0fbc0e50) == 0x0ebc0a40) {
+ } else if ((insn & 0x0fbc0e50) == 0x0ebc0a40 &&
+ dc_isar_feature(aa32_vcvt_dr, s)) {
/* VCVTA, VCVTN, VCVTP, VCVTM */
int rounding = fp_decode_rm[extract32(insn, 16, 2)];
return handle_vcvt(insn, rd, rm, dp, rounding);
@@ -3427,10 +3415,12 @@
}
if (extract32(insn, 28, 4) == 0xf) {
- /* Encodings with T=1 (Thumb) or unconditional (ARM):
- * only used in v8 and above.
+ /*
+ * Encodings with T=1 (Thumb) or unconditional (ARM):
+ * only used for the "miscellaneous VFP features" added in v8A
+ * and v7M (and gated on the MVFR2.FPMisc field).
*/
- return disas_vfp_v8_insn(s, insn);
+ return disas_vfp_misc_insn(s, insn);
}
dp = ((insn & 0xf00) == 0xb00);
@@ -3663,17 +3653,27 @@
* UNPREDICTABLE if bit 8 is set prior to ARMv8
* (we choose to UNDEF)
*/
- if ((dp && !arm_dc_feature(s, ARM_FEATURE_V8)) ||
- !arm_dc_feature(s, ARM_FEATURE_VFP_FP16)) {
- return 1;
+ if (dp) {
+ if (!dc_isar_feature(aa32_fp16_dpconv, s)) {
+ return 1;
+ }
+ } else {
+ if (!dc_isar_feature(aa32_fp16_spconv, s)) {
+ return 1;
+ }
}
rm_is_dp = false;
break;
case 0x06: /* vcvtb.f16.f32, vcvtb.f16.f64 */
case 0x07: /* vcvtt.f16.f32, vcvtt.f16.f64 */
- if ((dp && !arm_dc_feature(s, ARM_FEATURE_V8)) ||
- !arm_dc_feature(s, ARM_FEATURE_VFP_FP16)) {
- return 1;
+ if (dp) {
+ if (!dc_isar_feature(aa32_fp16_dpconv, s)) {
+ return 1;
+ }
+ } else {
+ if (!dc_isar_feature(aa32_fp16_spconv, s)) {
+ return 1;
+ }
}
rd_is_dp = false;
break;
@@ -7876,7 +7876,7 @@
TCGv_ptr fpst;
TCGv_i32 ahp;
- if (!arm_dc_feature(s, ARM_FEATURE_VFP_FP16) ||
+ if (!dc_isar_feature(aa32_fp16_spconv, s) ||
q || (rm & 1)) {
return 1;
}
@@ -7908,7 +7908,7 @@
{
TCGv_ptr fpst;
TCGv_i32 ahp;
- if (!arm_dc_feature(s, ARM_FEATURE_VFP_FP16) ||
+ if (!dc_isar_feature(aa32_fp16_spconv, s) ||
q || (rd & 1)) {
return 1;
}
@@ -8372,15 +8372,9 @@
gen_helper_gvec_3_ptr *fn_gvec_ptr = NULL;
int rd, rn, rm, opr_sz;
int data = 0;
- bool q;
-
- q = extract32(insn, 6, 1);
- VFP_DREG_D(rd, insn);
- VFP_DREG_N(rn, insn);
- VFP_DREG_M(rm, insn);
- if ((rd | rn | rm) & q) {
- return 1;
- }
+ int off_rn, off_rm;
+ bool is_long = false, q = extract32(insn, 6, 1);
+ bool ptr_is_env = false;
if ((insn & 0xfe200f10) == 0xfc200800) {
/* VCMLA -- 1111 110R R.1S .... .... 1000 ...0 .... */
@@ -8407,10 +8401,39 @@
return 1;
}
fn_gvec = u ? gen_helper_gvec_udot_b : gen_helper_gvec_sdot_b;
+ } else if ((insn & 0xff300f10) == 0xfc200810) {
+ /* VFM[AS]L -- 1111 1100 S.10 .... .... 1000 .Q.1 .... */
+ int is_s = extract32(insn, 23, 1);
+ if (!dc_isar_feature(aa32_fhm, s)) {
+ return 1;
+ }
+ is_long = true;
+ data = is_s; /* is_2 == 0 */
+ fn_gvec_ptr = gen_helper_gvec_fmlal_a32;
+ ptr_is_env = true;
} else {
return 1;
}
+ VFP_DREG_D(rd, insn);
+ if (rd & q) {
+ return 1;
+ }
+ if (q || !is_long) {
+ VFP_DREG_N(rn, insn);
+ VFP_DREG_M(rm, insn);
+ if ((rn | rm) & q & !is_long) {
+ return 1;
+ }
+ off_rn = vfp_reg_offset(1, rn);
+ off_rm = vfp_reg_offset(1, rm);
+ } else {
+ rn = VFP_SREG_N(insn);
+ rm = VFP_SREG_M(insn);
+ off_rn = vfp_reg_offset(0, rn);
+ off_rm = vfp_reg_offset(0, rm);
+ }
+
if (s->fp_excp_el) {
gen_exception_insn(s, 4, EXCP_UDEF,
syn_simd_access_trap(1, 0xe, false), s->fp_excp_el);
@@ -8422,16 +8445,19 @@
opr_sz = (1 + q) * 8;
if (fn_gvec_ptr) {
- TCGv_ptr fpst = get_fpstatus_ptr(1);
- tcg_gen_gvec_3_ptr(vfp_reg_offset(1, rd),
- vfp_reg_offset(1, rn),
- vfp_reg_offset(1, rm), fpst,
+ TCGv_ptr ptr;
+ if (ptr_is_env) {
+ ptr = cpu_env;
+ } else {
+ ptr = get_fpstatus_ptr(1);
+ }
+ tcg_gen_gvec_3_ptr(vfp_reg_offset(1, rd), off_rn, off_rm, ptr,
opr_sz, opr_sz, data, fn_gvec_ptr);
- tcg_temp_free_ptr(fpst);
+ if (!ptr_is_env) {
+ tcg_temp_free_ptr(ptr);
+ }
} else {
- tcg_gen_gvec_3_ool(vfp_reg_offset(1, rd),
- vfp_reg_offset(1, rn),
- vfp_reg_offset(1, rm),
+ tcg_gen_gvec_3_ool(vfp_reg_offset(1, rd), off_rn, off_rm,
opr_sz, opr_sz, data, fn_gvec);
}
return 0;
@@ -8450,14 +8476,9 @@
gen_helper_gvec_3 *fn_gvec = NULL;
gen_helper_gvec_3_ptr *fn_gvec_ptr = NULL;
int rd, rn, rm, opr_sz, data;
- bool q;
-
- q = extract32(insn, 6, 1);
- VFP_DREG_D(rd, insn);
- VFP_DREG_N(rn, insn);
- if ((rd | rn) & q) {
- return 1;
- }
+ int off_rn, off_rm;
+ bool is_long = false, q = extract32(insn, 6, 1);
+ bool ptr_is_env = false;
if ((insn & 0xff000f10) == 0xfe000800) {
/* VCMLA (indexed) -- 1111 1110 S.RR .... .... 1000 ...0 .... */
@@ -8486,6 +8507,7 @@
} else if ((insn & 0xffb00f00) == 0xfe200d00) {
/* V[US]DOT -- 1111 1110 0.10 .... .... 1101 .Q.U .... */
int u = extract32(insn, 4, 1);
+
if (!dc_isar_feature(aa32_dp, s)) {
return 1;
}
@@ -8493,10 +8515,48 @@
/* rm is just Vm, and index is M. */
data = extract32(insn, 5, 1); /* index */
rm = extract32(insn, 0, 4);
+ } else if ((insn & 0xffa00f10) == 0xfe000810) {
+ /* VFM[AS]L -- 1111 1110 0.0S .... .... 1000 .Q.1 .... */
+ int is_s = extract32(insn, 20, 1);
+ int vm20 = extract32(insn, 0, 3);
+ int vm3 = extract32(insn, 3, 1);
+ int m = extract32(insn, 5, 1);
+ int index;
+
+ if (!dc_isar_feature(aa32_fhm, s)) {
+ return 1;
+ }
+ if (q) {
+ rm = vm20;
+ index = m * 2 + vm3;
+ } else {
+ rm = vm20 * 2 + m;
+ index = vm3;
+ }
+ is_long = true;
+ data = (index << 2) | is_s; /* is_2 == 0 */
+ fn_gvec_ptr = gen_helper_gvec_fmlal_idx_a32;
+ ptr_is_env = true;
} else {
return 1;
}
+ VFP_DREG_D(rd, insn);
+ if (rd & q) {
+ return 1;
+ }
+ if (q || !is_long) {
+ VFP_DREG_N(rn, insn);
+ if (rn & q & !is_long) {
+ return 1;
+ }
+ off_rn = vfp_reg_offset(1, rn);
+ off_rm = vfp_reg_offset(1, rm);
+ } else {
+ rn = VFP_SREG_N(insn);
+ off_rn = vfp_reg_offset(0, rn);
+ off_rm = vfp_reg_offset(0, rm);
+ }
if (s->fp_excp_el) {
gen_exception_insn(s, 4, EXCP_UDEF,
syn_simd_access_trap(1, 0xe, false), s->fp_excp_el);
@@ -8508,16 +8568,19 @@
opr_sz = (1 + q) * 8;
if (fn_gvec_ptr) {
- TCGv_ptr fpst = get_fpstatus_ptr(1);
- tcg_gen_gvec_3_ptr(vfp_reg_offset(1, rd),
- vfp_reg_offset(1, rn),
- vfp_reg_offset(1, rm), fpst,
+ TCGv_ptr ptr;
+ if (ptr_is_env) {
+ ptr = cpu_env;
+ } else {
+ ptr = get_fpstatus_ptr(1);
+ }
+ tcg_gen_gvec_3_ptr(vfp_reg_offset(1, rd), off_rn, off_rm, ptr,
opr_sz, opr_sz, data, fn_gvec_ptr);
- tcg_temp_free_ptr(fpst);
+ if (!ptr_is_env) {
+ tcg_temp_free_ptr(ptr);
+ }
} else {
- tcg_gen_gvec_3_ool(vfp_reg_offset(1, rd),
- vfp_reg_offset(1, rn),
- vfp_reg_offset(1, rm),
+ tcg_gen_gvec_3_ool(vfp_reg_offset(1, rd), off_rn, off_rm,
opr_sz, opr_sz, data, fn_gvec);
}
return 0;
@@ -9208,6 +9271,17 @@
*/
gen_goto_tb(s, 0, s->pc & ~1);
return;
+ case 7: /* sb */
+ if ((insn & 0xf) || !dc_isar_feature(aa32_sb, s)) {
+ goto illegal_op;
+ }
+ /*
+ * TODO: There is no speculation barrier opcode
+ * for TCG; MB and end the TB instead.
+ */
+ tcg_gen_mb(TCG_MO_ALL | TCG_BAR_SC);
+ gen_goto_tb(s, 0, s->pc & ~1);
+ return;
default:
goto illegal_op;
}
@@ -10538,7 +10612,7 @@
} else if (i == rn) {
loaded_var = tmp;
loaded_base = 1;
- } else if (rn == 15 && exc_return) {
+ } else if (i == 15 && exc_return) {
store_pc_exc_ret(s, tmp);
} else {
store_reg_from_load(s, i, tmp);
@@ -11826,6 +11900,17 @@
*/
gen_goto_tb(s, 0, s->pc & ~1);
break;
+ case 7: /* sb */
+ if ((insn & 0xf) || !dc_isar_feature(aa32_sb, s)) {
+ goto illegal_op;
+ }
+ /*
+ * TODO: There is no speculation barrier opcode
+ * for TCG; MB and end the TB instead.
+ */
+ tcg_gen_mb(TCG_MO_ALL | TCG_BAR_SC);
+ gen_goto_tb(s, 0, s->pc & ~1);
+ break;
default:
goto illegal_op;
}
diff --git a/target/arm/translate.h b/target/arm/translate.h
index f25fe75..912cc2a 100644
--- a/target/arm/translate.h
+++ b/target/arm/translate.h
@@ -202,6 +202,40 @@
return ret;
}
+/* Set bits within PSTATE. */
+static inline void set_pstate_bits(uint32_t bits)
+{
+ TCGv_i32 p = tcg_temp_new_i32();
+
+ tcg_debug_assert(!(bits & CACHED_PSTATE_BITS));
+
+ tcg_gen_ld_i32(p, cpu_env, offsetof(CPUARMState, pstate));
+ tcg_gen_ori_i32(p, p, bits);
+ tcg_gen_st_i32(p, cpu_env, offsetof(CPUARMState, pstate));
+ tcg_temp_free_i32(p);
+}
+
+/* Clear bits within PSTATE. */
+static inline void clear_pstate_bits(uint32_t bits)
+{
+ TCGv_i32 p = tcg_temp_new_i32();
+
+ tcg_debug_assert(!(bits & CACHED_PSTATE_BITS));
+
+ tcg_gen_ld_i32(p, cpu_env, offsetof(CPUARMState, pstate));
+ tcg_gen_andi_i32(p, p, ~bits);
+ tcg_gen_st_i32(p, cpu_env, offsetof(CPUARMState, pstate));
+ tcg_temp_free_i32(p);
+}
+
+/* If the singlestep state is Active-not-pending, advance to Active-pending. */
+static inline void gen_ss_advance(DisasContext *s)
+{
+ if (s->ss_active) {
+ s->pstate_ss = 0;
+ clear_pstate_bits(PSTATE_SS);
+ }
+}
/* Vector operations shared between ARM and AArch64. */
extern const GVecGen3 bsl_op;
diff --git a/target/arm/vec_helper.c b/target/arm/vec_helper.c
index dfc635c..dedef62 100644
--- a/target/arm/vec_helper.c
+++ b/target/arm/vec_helper.c
@@ -898,3 +898,151 @@
}
clear_tail(d, oprsz, simd_maxsz(desc));
}
+
+/*
+ * Convert float16 to float32, raising no exceptions and
+ * preserving exceptional values, including SNaN.
+ * This is effectively an unpack+repack operation.
+ */
+static float32 float16_to_float32_by_bits(uint32_t f16, bool fz16)
+{
+ const int f16_bias = 15;
+ const int f32_bias = 127;
+ uint32_t sign = extract32(f16, 15, 1);
+ uint32_t exp = extract32(f16, 10, 5);
+ uint32_t frac = extract32(f16, 0, 10);
+
+ if (exp == 0x1f) {
+ /* Inf or NaN */
+ exp = 0xff;
+ } else if (exp == 0) {
+ /* Zero or denormal. */
+ if (frac != 0) {
+ if (fz16) {
+ frac = 0;
+ } else {
+ /*
+ * Denormal; these are all normal float32.
+ * Shift the fraction so that the msb is at bit 11,
+ * then remove bit 11 as the implicit bit of the
+ * normalized float32. Note that we still go through
+ * the shift for normal numbers below, to put the
+ * float32 fraction at the right place.
+ */
+ int shift = clz32(frac) - 21;
+ frac = (frac << shift) & 0x3ff;
+ exp = f32_bias - f16_bias - shift + 1;
+ }
+ }
+ } else {
+ /* Normal number; adjust the bias. */
+ exp += f32_bias - f16_bias;
+ }
+ sign <<= 31;
+ exp <<= 23;
+ frac <<= 23 - 10;
+
+ return sign | exp | frac;
+}
+
+static uint64_t load4_f16(uint64_t *ptr, int is_q, int is_2)
+{
+ /*
+ * Branchless load of u32[0], u64[0], u32[1], or u64[1].
+ * Load the 2nd qword iff is_q & is_2.
+ * Shift to the 2nd dword iff !is_q & is_2.
+ * For !is_q & !is_2, the upper bits of the result are garbage.
+ */
+ return ptr[is_q & is_2] >> ((is_2 & ~is_q) << 5);
+}
+
+/*
+ * Note that FMLAL requires oprsz == 8 or oprsz == 16,
+ * as there is not yet SVE versions that might use blocking.
+ */
+
+static void do_fmlal(float32 *d, void *vn, void *vm, float_status *fpst,
+ uint32_t desc, bool fz16)
+{
+ intptr_t i, oprsz = simd_oprsz(desc);
+ int is_s = extract32(desc, SIMD_DATA_SHIFT, 1);
+ int is_2 = extract32(desc, SIMD_DATA_SHIFT + 1, 1);
+ int is_q = oprsz == 16;
+ uint64_t n_4, m_4;
+
+ /* Pre-load all of the f16 data, avoiding overlap issues. */
+ n_4 = load4_f16(vn, is_q, is_2);
+ m_4 = load4_f16(vm, is_q, is_2);
+
+ /* Negate all inputs for FMLSL at once. */
+ if (is_s) {
+ n_4 ^= 0x8000800080008000ull;
+ }
+
+ for (i = 0; i < oprsz / 4; i++) {
+ float32 n_1 = float16_to_float32_by_bits(n_4 >> (i * 16), fz16);
+ float32 m_1 = float16_to_float32_by_bits(m_4 >> (i * 16), fz16);
+ d[H4(i)] = float32_muladd(n_1, m_1, d[H4(i)], 0, fpst);
+ }
+ clear_tail(d, oprsz, simd_maxsz(desc));
+}
+
+void HELPER(gvec_fmlal_a32)(void *vd, void *vn, void *vm,
+ void *venv, uint32_t desc)
+{
+ CPUARMState *env = venv;
+ do_fmlal(vd, vn, vm, &env->vfp.standard_fp_status, desc,
+ get_flush_inputs_to_zero(&env->vfp.fp_status_f16));
+}
+
+void HELPER(gvec_fmlal_a64)(void *vd, void *vn, void *vm,
+ void *venv, uint32_t desc)
+{
+ CPUARMState *env = venv;
+ do_fmlal(vd, vn, vm, &env->vfp.fp_status, desc,
+ get_flush_inputs_to_zero(&env->vfp.fp_status_f16));
+}
+
+static void do_fmlal_idx(float32 *d, void *vn, void *vm, float_status *fpst,
+ uint32_t desc, bool fz16)
+{
+ intptr_t i, oprsz = simd_oprsz(desc);
+ int is_s = extract32(desc, SIMD_DATA_SHIFT, 1);
+ int is_2 = extract32(desc, SIMD_DATA_SHIFT + 1, 1);
+ int index = extract32(desc, SIMD_DATA_SHIFT + 2, 3);
+ int is_q = oprsz == 16;
+ uint64_t n_4;
+ float32 m_1;
+
+ /* Pre-load all of the f16 data, avoiding overlap issues. */
+ n_4 = load4_f16(vn, is_q, is_2);
+
+ /* Negate all inputs for FMLSL at once. */
+ if (is_s) {
+ n_4 ^= 0x8000800080008000ull;
+ }
+
+ m_1 = float16_to_float32_by_bits(((float16 *)vm)[H2(index)], fz16);
+
+ for (i = 0; i < oprsz / 4; i++) {
+ float32 n_1 = float16_to_float32_by_bits(n_4 >> (i * 16), fz16);
+ d[H4(i)] = float32_muladd(n_1, m_1, d[H4(i)], 0, fpst);
+ }
+ clear_tail(d, oprsz, simd_maxsz(desc));
+}
+
+void HELPER(gvec_fmlal_idx_a32)(void *vd, void *vn, void *vm,
+ void *venv, uint32_t desc)
+{
+ CPUARMState *env = venv;
+ do_fmlal_idx(vd, vn, vm, &env->vfp.standard_fp_status, desc,
+ get_flush_inputs_to_zero(&env->vfp.fp_status_f16));
+}
+
+void HELPER(gvec_fmlal_idx_a64)(void *vd, void *vn, void *vm,
+ void *venv, uint32_t desc)
+{
+ CPUARMState *env = venv;
+ do_fmlal_idx(vd, vn, vm, &env->vfp.fp_status, desc,
+ get_flush_inputs_to_zero(&env->vfp.fp_status_f16));
+}
diff --git a/target/arm/vfp_helper.c b/target/arm/vfp_helper.c
index cc7f9f5..2468fc1 100644
--- a/target/arm/vfp_helper.c
+++ b/target/arm/vfp_helper.c
@@ -1174,3 +1174,99 @@
return result;
}
+
+/* Round a float32 to an integer that fits in int32_t or int64_t. */
+static float32 frint_s(float32 f, float_status *fpst, int intsize)
+{
+ int old_flags = get_float_exception_flags(fpst);
+ uint32_t exp = extract32(f, 23, 8);
+
+ if (unlikely(exp == 0xff)) {
+ /* NaN or Inf. */
+ goto overflow;
+ }
+
+ /* Round and re-extract the exponent. */
+ f = float32_round_to_int(f, fpst);
+ exp = extract32(f, 23, 8);
+
+ /* Validate the range of the result. */
+ if (exp < 126 + intsize) {
+ /* abs(F) <= INT{N}_MAX */
+ return f;
+ }
+ if (exp == 126 + intsize) {
+ uint32_t sign = extract32(f, 31, 1);
+ uint32_t frac = extract32(f, 0, 23);
+ if (sign && frac == 0) {
+ /* F == INT{N}_MIN */
+ return f;
+ }
+ }
+
+ overflow:
+ /*
+ * Raise Invalid and return INT{N}_MIN as a float. Revert any
+ * inexact exception float32_round_to_int may have raised.
+ */
+ set_float_exception_flags(old_flags | float_flag_invalid, fpst);
+ return (0x100u + 126u + intsize) << 23;
+}
+
+float32 HELPER(frint32_s)(float32 f, void *fpst)
+{
+ return frint_s(f, fpst, 32);
+}
+
+float32 HELPER(frint64_s)(float32 f, void *fpst)
+{
+ return frint_s(f, fpst, 64);
+}
+
+/* Round a float64 to an integer that fits in int32_t or int64_t. */
+static float64 frint_d(float64 f, float_status *fpst, int intsize)
+{
+ int old_flags = get_float_exception_flags(fpst);
+ uint32_t exp = extract64(f, 52, 11);
+
+ if (unlikely(exp == 0x7ff)) {
+ /* NaN or Inf. */
+ goto overflow;
+ }
+
+ /* Round and re-extract the exponent. */
+ f = float64_round_to_int(f, fpst);
+ exp = extract64(f, 52, 11);
+
+ /* Validate the range of the result. */
+ if (exp < 1022 + intsize) {
+ /* abs(F) <= INT{N}_MAX */
+ return f;
+ }
+ if (exp == 1022 + intsize) {
+ uint64_t sign = extract64(f, 63, 1);
+ uint64_t frac = extract64(f, 0, 52);
+ if (sign && frac == 0) {
+ /* F == INT{N}_MIN */
+ return f;
+ }
+ }
+
+ overflow:
+ /*
+ * Raise Invalid and return INT{N}_MIN as a float. Revert any
+ * inexact exception float64_round_to_int may have raised.
+ */
+ set_float_exception_flags(old_flags | float_flag_invalid, fpst);
+ return (uint64_t)(0x800 + 1022 + intsize) << 52;
+}
+
+float64 HELPER(frint32_d)(float64 f, void *fpst)
+{
+ return frint_d(f, fpst, 32);
+}
+
+float64 HELPER(frint64_d)(float64 f, void *fpst)
+{
+ return frint_d(f, fpst, 64);
+}
diff --git a/target/mips/translate.c b/target/mips/translate.c
index 3b17020..364bd6d 100644
--- a/target/mips/translate.c
+++ b/target/mips/translate.c
@@ -4362,6 +4362,7 @@
tcg_temp_free(t1);
}
+#if defined(TARGET_MIPS64)
/* Copy GPR to and from TX79 HI1/LO1 register. */
static void gen_HILO1_tx79(DisasContext *ctx, uint32_t opc, int reg)
{
@@ -4397,6 +4398,7 @@
break;
}
}
+#endif
/* Arithmetic on HI/LO registers */
static void gen_HILO(DisasContext *ctx, uint32_t opc, int acc, int reg)
@@ -4746,6 +4748,7 @@
tcg_temp_free(t1);
}
+#if defined(TARGET_MIPS64)
static void gen_div1_tx79(DisasContext *ctx, uint32_t opc, int rs, int rt)
{
TCGv t0, t1;
@@ -4802,6 +4805,7 @@
tcg_temp_free(t0);
tcg_temp_free(t1);
}
+#endif
static void gen_muldiv(DisasContext *ctx, uint32_t opc,
int acc, int rs, int rt)
@@ -24324,6 +24328,29 @@
}
+#if defined(TARGET_MIPS64)
+
+/*
+ *
+ * MMI (MultiMedia Interface) ASE instructions
+ * ===========================================
+ */
+
+/*
+ * MMI instructions category: data communication
+ * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ *
+ * PCPYH PEXCH PEXTLB PINTH PPACB PEXT5 PREVH
+ * PCPYLD PEXCW PEXTLH PINTEH PPACH PPAC5 PROT3W
+ * PCPYUD PEXEH PEXTLW PPACW
+ * PEXEW PEXTUB
+ * PEXTUH
+ * PEXTUW
+ */
+
+#endif
+
+
#if !defined(TARGET_MIPS64)
/* MXU accumulate add/subtract 1-bit pattern 'aptn1' */
@@ -27247,6 +27274,9 @@
}
}
+
+#if defined(TARGET_MIPS64)
+
static void decode_mmi0(CPUMIPSState *env, DisasContext *ctx)
{
uint32_t opc = MASK_MMI0(ctx->opcode);
@@ -27491,6 +27521,8 @@
gen_mmi_sq(ctx, base, rt, offset);
}
+#endif
+
static void decode_opc_special3(CPUMIPSState *env, DisasContext *ctx)
{
int rs, rt, rd, sa;
@@ -28796,10 +28828,11 @@
decode_opc_special(env, ctx);
break;
case OPC_SPECIAL2:
+#if defined(TARGET_MIPS64)
if ((ctx->insn_flags & INSN_R5900) && (ctx->insn_flags & ASE_MMI)) {
decode_mmi(env, ctx);
-#if !defined(TARGET_MIPS64)
- } else if (ctx->insn_flags & ASE_MXU) {
+#else
+ if (ctx->insn_flags & ASE_MXU) {
decode_opc_mxu(env, ctx);
#endif
} else {
@@ -28807,11 +28840,15 @@
}
break;
case OPC_SPECIAL3:
+#if defined(TARGET_MIPS64)
if (ctx->insn_flags & INSN_R5900) {
decode_mmi_sq(env, ctx); /* MMI_OPC_SQ */
} else {
decode_opc_special3(env, ctx);
}
+#else
+ decode_opc_special3(env, ctx);
+#endif
break;
case OPC_REGIMM:
op1 = MASK_REGIMM(ctx->opcode);
@@ -29483,7 +29520,9 @@
break;
case OPC_MSA: /* OPC_MDMX */
if (ctx->insn_flags & INSN_R5900) {
+#if defined(TARGET_MIPS64)
gen_mmi_lq(env, ctx); /* MMI_OPC_LQ */
+#endif
} else {
/* MDMX: Not implemented. */
gen_msa(env, ctx);
diff --git a/target/ppc/cpu-qom.h b/target/ppc/cpu-qom.h
index 3130802..ae51fe7 100644
--- a/target/ppc/cpu-qom.h
+++ b/target/ppc/cpu-qom.h
@@ -113,6 +113,8 @@
POWERPC_EXCP_POWER7,
/* POWER8 exception model */
POWERPC_EXCP_POWER8,
+ /* POWER9 exception model */
+ POWERPC_EXCP_POWER9,
};
/*****************************************************************************/
@@ -122,6 +124,7 @@
PPC_PM_NAP,
PPC_PM_SLEEP,
PPC_PM_RVWINKLE,
+ PPC_PM_STOP,
} powerpc_pm_insn_t;
/*****************************************************************************/
@@ -139,6 +142,8 @@
PPC_FLAGS_INPUT_970,
/* PowerPC POWER7 bus */
PPC_FLAGS_INPUT_POWER7,
+ /* PowerPC POWER9 bus */
+ PPC_FLAGS_INPUT_POWER9,
/* PowerPC 401 bus */
PPC_FLAGS_INPUT_401,
/* Freescale RCPU bus */
diff --git a/target/ppc/cpu.h b/target/ppc/cpu.h
index 325ebbe..26604dd 100644
--- a/target/ppc/cpu.h
+++ b/target/ppc/cpu.h
@@ -160,8 +160,10 @@
/* Server doorbell variants */
POWERPC_EXCP_SDOOR = 99,
POWERPC_EXCP_SDOOR_HV = 100,
+ /* ISA 3.00 additions */
+ POWERPC_EXCP_HVIRT = 101,
/* EOL */
- POWERPC_EXCP_NB = 101,
+ POWERPC_EXCP_NB = 102,
/* QEMU exceptions: used internally during code translation */
POWERPC_EXCP_STOP = 0x200, /* stop translation */
POWERPC_EXCP_BRANCH = 0x201, /* branch instruction */
@@ -318,6 +320,10 @@
#define SEGMENT_SHIFT_1T 40
#define SEGMENT_MASK_1T (~((1ULL << SEGMENT_SHIFT_1T) - 1))
+typedef struct ppc_v3_pate_t {
+ uint64_t dw0;
+ uint64_t dw1;
+} ppc_v3_pate_t;
/*****************************************************************************/
/* Machine state register bits definition */
@@ -386,6 +392,7 @@
#define LPCR_AIL (3ull << LPCR_AIL_SHIFT)
#define LPCR_UPRT PPC_BIT(41) /* Use Process Table */
#define LPCR_EVIRT PPC_BIT(42) /* Enhanced Virtualisation */
+#define LPCR_HR PPC_BIT(43) /* Host Radix */
#define LPCR_ONL PPC_BIT(45)
#define LPCR_LD PPC_BIT(46) /* Large Decrementer */
#define LPCR_P7_PECE0 PPC_BIT(49)
@@ -414,6 +421,10 @@
#define LPCR_HVICE PPC_BIT(62) /* HV Virtualisation Int Enable */
#define LPCR_HDICE PPC_BIT(63)
+/* PSSCR bits */
+#define PSSCR_ESL PPC_BIT(42) /* Enable State Loss */
+#define PSSCR_EC PPC_BIT(43) /* Exit Criterion */
+
#define msr_sf ((env->msr >> MSR_SF) & 1)
#define msr_isf ((env->msr >> MSR_ISF) & 1)
#define msr_shv ((env->msr >> MSR_SHV) & 1)
@@ -1110,11 +1121,13 @@
* instructions and SPRs are diallowed if MSR:HV is 0
*/
bool has_hv_mode;
- /* On P7/P8, set when in PM state, we need to handle resume
- * in a special way (such as routing some resume causes to
- * 0x100), so flag this here.
+
+ /*
+ * On P7/P8/P9, set when in PM state, we need to handle resume in
+ * a special way (such as routing some resume causes to 0x100, ie,
+ * sreset), so flag this here.
*/
- bool in_pm_state;
+ bool resume_as_sreset;
#endif
/* Those resources are used only during code translation */
@@ -1239,7 +1252,7 @@
hwaddr ptex, int n);
void (*store_hpte)(PPCVirtualHypervisor *vhyp, hwaddr ptex,
uint64_t pte0, uint64_t pte1);
- uint64_t (*get_patbe)(PPCVirtualHypervisor *vhyp);
+ void (*get_pate)(PPCVirtualHypervisor *vhyp, ppc_v3_pate_t *entry);
target_ulong (*encode_hpt_for_kvm_pr)(PPCVirtualHypervisor *vhyp);
};
@@ -2319,6 +2332,13 @@
* them */
POWER7_INPUT_NB,
};
+
+enum {
+ /* POWER9 input pins */
+ POWER9_INPUT_INT = 0,
+ POWER9_INPUT_HINT = 1,
+ POWER9_INPUT_NB,
+};
#endif
/* Hardware exceptions definitions */
@@ -2343,6 +2363,7 @@
PPC_INTERRUPT_PERFM, /* Performance monitor interrupt */
PPC_INTERRUPT_HMI, /* Hypervisor Maintainance interrupt */
PPC_INTERRUPT_HDOORBELL, /* Hypervisor Doorbell interrupt */
+ PPC_INTERRUPT_HVIRT, /* Hypervisor virtualization interrupt */
};
/* Processor Compatibility mask (PCR) */
diff --git a/target/ppc/excp_helper.c b/target/ppc/excp_helper.c
index 751d759..39bedbb 100644
--- a/target/ppc/excp_helper.c
+++ b/target/ppc/excp_helper.c
@@ -65,6 +65,49 @@
ppc_dump_gpr(env, 6), env->nip);
}
+static int powerpc_reset_wakeup(CPUState *cs, CPUPPCState *env, int excp,
+ target_ulong *msr)
+{
+ /* We no longer are in a PM state */
+ env->resume_as_sreset = false;
+
+ /* Pretend to be returning from doze always as we don't lose state */
+ *msr |= (0x1ull << (63 - 47));
+
+ /* Machine checks are sent normally */
+ if (excp == POWERPC_EXCP_MCHECK) {
+ return excp;
+ }
+ switch (excp) {
+ case POWERPC_EXCP_RESET:
+ *msr |= 0x4ull << (63 - 45);
+ break;
+ case POWERPC_EXCP_EXTERNAL:
+ *msr |= 0x8ull << (63 - 45);
+ break;
+ case POWERPC_EXCP_DECR:
+ *msr |= 0x6ull << (63 - 45);
+ break;
+ case POWERPC_EXCP_SDOOR:
+ *msr |= 0x5ull << (63 - 45);
+ break;
+ case POWERPC_EXCP_SDOOR_HV:
+ *msr |= 0x3ull << (63 - 45);
+ break;
+ case POWERPC_EXCP_HV_MAINT:
+ *msr |= 0xaull << (63 - 45);
+ break;
+ case POWERPC_EXCP_HVIRT:
+ *msr |= 0x9ull << (63 - 45);
+ break;
+ default:
+ cpu_abort(cs, "Unsupported exception %d in Power Save mode\n",
+ excp);
+ }
+ return POWERPC_EXCP_RESET;
+}
+
+
/* Note that this function should be greatly optimized
* when called with a constant excp, from ppc_hw_interrupt
*/
@@ -97,47 +140,17 @@
asrr0 = -1;
asrr1 = -1;
- /* check for special resume at 0x100 from doze/nap/sleep/winkle on P7/P8 */
- if (env->in_pm_state) {
- env->in_pm_state = false;
-
- /* Pretend to be returning from doze always as we don't lose state */
- msr |= (0x1ull << (63 - 47));
-
- /* Non-machine check are routed to 0x100 with a wakeup cause
- * encoded in SRR1
- */
- if (excp != POWERPC_EXCP_MCHECK) {
- switch (excp) {
- case POWERPC_EXCP_RESET:
- msr |= 0x4ull << (63 - 45);
- break;
- case POWERPC_EXCP_EXTERNAL:
- msr |= 0x8ull << (63 - 45);
- break;
- case POWERPC_EXCP_DECR:
- msr |= 0x6ull << (63 - 45);
- break;
- case POWERPC_EXCP_SDOOR:
- msr |= 0x5ull << (63 - 45);
- break;
- case POWERPC_EXCP_SDOOR_HV:
- msr |= 0x3ull << (63 - 45);
- break;
- case POWERPC_EXCP_HV_MAINT:
- msr |= 0xaull << (63 - 45);
- break;
- default:
- cpu_abort(cs, "Unsupported exception %d in Power Save mode\n",
- excp);
- }
- excp = POWERPC_EXCP_RESET;
- }
+ /*
+ * check for special resume at 0x100 from doze/nap/sleep/winkle on
+ * P7/P8/P9
+ */
+ if (env->resume_as_sreset) {
+ excp = powerpc_reset_wakeup(cs, env, excp, &msr);
}
/* Exception targetting modifiers
*
- * LPES0 is supported on POWER7/8
+ * LPES0 is supported on POWER7/8/9
* LPES1 is not supported (old iSeries mode)
*
* On anything else, we behave as if LPES0 is 1
@@ -148,9 +161,10 @@
*/
#if defined(TARGET_PPC64)
if (excp_model == POWERPC_EXCP_POWER7 ||
- excp_model == POWERPC_EXCP_POWER8) {
+ excp_model == POWERPC_EXCP_POWER8 ||
+ excp_model == POWERPC_EXCP_POWER9) {
lpes0 = !!(env->spr[SPR_LPCR] & LPCR_LPES0);
- if (excp_model == POWERPC_EXCP_POWER8) {
+ if (excp_model != POWERPC_EXCP_POWER7) {
ail = (env->spr[SPR_LPCR] & LPCR_AIL) >> LPCR_AIL_SHIFT;
} else {
ail = 0;
@@ -416,6 +430,7 @@
case POWERPC_EXCP_HISEG: /* Hypervisor instruction segment exception */
case POWERPC_EXCP_SDOOR_HV: /* Hypervisor Doorbell interrupt */
case POWERPC_EXCP_HV_EMU:
+ case POWERPC_EXCP_HVIRT: /* Hypervisor virtualization */
srr0 = SPR_HSRR0;
srr1 = SPR_HSRR1;
new_msr |= (target_ulong)MSR_HVB;
@@ -652,7 +667,15 @@
}
} else if (excp_model == POWERPC_EXCP_POWER8) {
if (new_msr & MSR_HVB) {
- if (env->spr[SPR_HID0] & (HID0_HILE | HID0_POWER9_HILE)) {
+ if (env->spr[SPR_HID0] & HID0_HILE) {
+ new_msr |= (target_ulong)1 << MSR_LE;
+ }
+ } else if (env->spr[SPR_LPCR] & LPCR_ILE) {
+ new_msr |= (target_ulong)1 << MSR_LE;
+ }
+ } else if (excp_model == POWERPC_EXCP_POWER9) {
+ if (new_msr & MSR_HVB) {
+ if (env->spr[SPR_HID0] & HID0_POWER9_HILE) {
new_msr |= (target_ulong)1 << MSR_LE;
}
} else if (env->spr[SPR_LPCR] & LPCR_ILE) {
@@ -748,6 +771,7 @@
static void ppc_hw_interrupt(CPUPPCState *env)
{
PowerPCCPU *cpu = ppc_env_get_cpu(env);
+ bool async_deliver;
/* External reset */
if (env->pending_interrupts & (1 << PPC_INTERRUPT_RESET)) {
@@ -769,21 +793,44 @@
return;
}
#endif
+
+ /*
+ * For interrupts that gate on MSR:EE, we need to do something a
+ * bit more subtle, as we need to let them through even when EE is
+ * clear when coming out of some power management states (in order
+ * for them to become a 0x100).
+ */
+ async_deliver = (msr_ee != 0) || env->resume_as_sreset;
+
/* Hypervisor decrementer exception */
if (env->pending_interrupts & (1 << PPC_INTERRUPT_HDECR)) {
/* LPCR will be clear when not supported so this will work */
bool hdice = !!(env->spr[SPR_LPCR] & LPCR_HDICE);
- if ((msr_ee != 0 || msr_hv == 0) && hdice) {
+ if ((async_deliver || msr_hv == 0) && hdice) {
/* HDEC clears on delivery */
env->pending_interrupts &= ~(1 << PPC_INTERRUPT_HDECR);
powerpc_excp(cpu, env->excp_model, POWERPC_EXCP_HDECR);
return;
}
}
- /* Extermal interrupt can ignore MSR:EE under some circumstances */
+
+ /* Hypervisor virtualization interrupt */
+ if (env->pending_interrupts & (1 << PPC_INTERRUPT_HVIRT)) {
+ /* LPCR will be clear when not supported so this will work */
+ bool hvice = !!(env->spr[SPR_LPCR] & LPCR_HVICE);
+ if ((async_deliver || msr_hv == 0) && hvice) {
+ powerpc_excp(cpu, env->excp_model, POWERPC_EXCP_HVIRT);
+ return;
+ }
+ }
+
+ /* External interrupt can ignore MSR:EE under some circumstances */
if (env->pending_interrupts & (1 << PPC_INTERRUPT_EXT)) {
bool lpes0 = !!(env->spr[SPR_LPCR] & LPCR_LPES0);
- if (msr_ee != 0 || (env->has_hv_mode && msr_hv == 0 && !lpes0)) {
+ bool heic = !!(env->spr[SPR_LPCR] & LPCR_HEIC);
+ /* HEIC blocks delivery to the hypervisor */
+ if ((async_deliver && !(heic && msr_hv && !msr_pr)) ||
+ (env->has_hv_mode && msr_hv == 0 && !lpes0)) {
powerpc_excp(cpu, env->excp_model, POWERPC_EXCP_EXTERNAL);
return;
}
@@ -795,7 +842,7 @@
return;
}
}
- if (msr_ee != 0) {
+ if (async_deliver != 0) {
/* Watchdog timer on embedded PowerPC */
if (env->pending_interrupts & (1 << PPC_INTERRUPT_WDT)) {
env->pending_interrupts &= ~(1 << PPC_INTERRUPT_WDT);
@@ -849,6 +896,22 @@
return;
}
}
+
+ if (env->resume_as_sreset) {
+ /*
+ * This is a bug ! It means that has_work took us out of halt without
+ * anything to deliver while in a PM state that requires getting
+ * out via a 0x100
+ *
+ * This means we will incorrectly execute past the power management
+ * instruction instead of triggering a reset.
+ *
+ * It generally means a discrepancy between the wakup conditions in the
+ * processor has_work implementation and the logic in this function.
+ */
+ cpu_abort(CPU(ppc_env_get_cpu(env)),
+ "Wakeup from PM state but interrupt Undelivered");
+ }
}
void ppc_cpu_do_system_reset(CPUState *cs)
@@ -943,22 +1006,15 @@
cs = CPU(ppc_env_get_cpu(env));
cs->halted = 1;
- env->in_pm_state = true;
/* The architecture specifies that HDEC interrupts are
* discarded in PM states
*/
env->pending_interrupts &= ~(1 << PPC_INTERRUPT_HDECR);
- /* Technically, nap doesn't set EE, but if we don't set it
- * then ppc_hw_interrupt() won't deliver. We could add some
- * other tests there based on LPCR but it's simpler to just
- * whack EE in. It will be cleared by the 0x100 at wakeup
- * anyway. It will still be observable by the guest in SRR1
- * but this doesn't seem to be a problem.
- */
- env->msr |= (1ull << MSR_EE);
- raise_exception(env, EXCP_HLT);
+ /* Condition for waking up at 0x100 */
+ env->resume_as_sreset = (insn != PPC_PM_STOP) ||
+ (env->spr[SPR_PSSCR] & PSSCR_EC);
}
#endif /* defined(TARGET_PPC64) */
diff --git a/target/ppc/helper.h b/target/ppc/helper.h
index 18910d1..638a6e9 100644
--- a/target/ppc/helper.h
+++ b/target/ppc/helper.h
@@ -689,6 +689,7 @@
#endif
DEF_HELPER_2(store_sdr1, void, env, tl)
DEF_HELPER_2(store_pidr, void, env, tl)
+DEF_HELPER_2(store_lpidr, void, env, tl)
DEF_HELPER_FLAGS_2(store_tbl, TCG_CALL_NO_RWG, void, env, tl)
DEF_HELPER_FLAGS_2(store_tbu, TCG_CALL_NO_RWG, void, env, tl)
DEF_HELPER_FLAGS_2(store_atbl, TCG_CALL_NO_RWG, void, env, tl)
diff --git a/target/ppc/helper_regs.h b/target/ppc/helper_regs.h
index 5efd180..a2205e1 100644
--- a/target/ppc/helper_regs.h
+++ b/target/ppc/helper_regs.h
@@ -174,26 +174,19 @@
static inline void check_tlb_flush(CPUPPCState *env, bool global)
{
CPUState *cs = CPU(ppc_env_get_cpu(env));
- if (env->tlb_need_flush & TLB_NEED_LOCAL_FLUSH) {
- tlb_flush(cs);
+
+ /* Handle global flushes first */
+ if (global && (env->tlb_need_flush & TLB_NEED_GLOBAL_FLUSH)) {
+ env->tlb_need_flush &= ~TLB_NEED_GLOBAL_FLUSH;
env->tlb_need_flush &= ~TLB_NEED_LOCAL_FLUSH;
+ tlb_flush_all_cpus_synced(cs);
+ return;
}
- /* Propagate TLB invalidations to other CPUs when the guest uses broadcast
- * TLB invalidation instructions.
- */
- if (global && (env->tlb_need_flush & TLB_NEED_GLOBAL_FLUSH)) {
- CPUState *other_cs;
- CPU_FOREACH(other_cs) {
- if (other_cs != cs) {
- PowerPCCPU *cpu = POWERPC_CPU(other_cs);
- CPUPPCState *other_env = &cpu->env;
-
- other_env->tlb_need_flush &= ~TLB_NEED_LOCAL_FLUSH;
- tlb_flush(other_cs);
- }
- }
- env->tlb_need_flush &= ~TLB_NEED_GLOBAL_FLUSH;
+ /* Then handle local ones */
+ if (env->tlb_need_flush & TLB_NEED_LOCAL_FLUSH) {
+ env->tlb_need_flush &= ~TLB_NEED_LOCAL_FLUSH;
+ tlb_flush(cs);
}
}
#else
diff --git a/target/ppc/misc_helper.c b/target/ppc/misc_helper.c
index b884930..c65d1ad 100644
--- a/target/ppc/misc_helper.c
+++ b/target/ppc/misc_helper.c
@@ -117,6 +117,21 @@
tlb_flush(CPU(cpu));
}
+void helper_store_lpidr(CPUPPCState *env, target_ulong val)
+{
+ PowerPCCPU *cpu = ppc_env_get_cpu(env);
+
+ env->spr[SPR_LPIDR] = val;
+
+ /*
+ * We need to flush the TLB on LPID changes as we only tag HV vs
+ * guest in TCG TLB. Also the quadrants means the HV will
+ * potentially access and cache entries for the current LPID as
+ * well.
+ */
+ tlb_flush(CPU(cpu));
+}
+
void helper_store_hid0_601(CPUPPCState *env, target_ulong val)
{
target_ulong hid0;
diff --git a/target/ppc/mmu-book3s-v3.c b/target/ppc/mmu-book3s-v3.c
index b60df44..32b8c16 100644
--- a/target/ppc/mmu-book3s-v3.c
+++ b/target/ppc/mmu-book3s-v3.c
@@ -26,9 +26,36 @@
int ppc64_v3_handle_mmu_fault(PowerPCCPU *cpu, vaddr eaddr, int rwx,
int mmu_idx)
{
- if (ppc64_radix_guest(cpu)) { /* Guest uses radix */
+ if (ppc64_v3_radix(cpu)) { /* Guest uses radix */
return ppc_radix64_handle_mmu_fault(cpu, eaddr, rwx, mmu_idx);
} else { /* Guest uses hash */
return ppc_hash64_handle_mmu_fault(cpu, eaddr, rwx, mmu_idx);
}
}
+
+hwaddr ppc64_v3_get_phys_page_debug(PowerPCCPU *cpu, vaddr eaddr)
+{
+ if (ppc64_v3_radix(cpu)) {
+ return ppc_radix64_get_phys_page_debug(cpu, eaddr);
+ } else {
+ return ppc_hash64_get_phys_page_debug(cpu, eaddr);
+ }
+}
+
+bool ppc64_v3_get_pate(PowerPCCPU *cpu, target_ulong lpid, ppc_v3_pate_t *entry)
+{
+ uint64_t patb = cpu->env.spr[SPR_PTCR] & PTCR_PATB;
+ uint64_t pats = cpu->env.spr[SPR_PTCR] & PTCR_PATS;
+
+ /* Calculate number of entries */
+ pats = 1ull << (pats + 12 - 4);
+ if (pats <= lpid) {
+ return false;
+ }
+
+ /* Grab entry */
+ patb += 16 * lpid;
+ entry->dw0 = ldq_phys(CPU(cpu)->as, patb);
+ entry->dw1 = ldq_phys(CPU(cpu)->as, patb + 8);
+ return true;
+}
diff --git a/target/ppc/mmu-book3s-v3.h b/target/ppc/mmu-book3s-v3.h
index fdf8098..ee8288e 100644
--- a/target/ppc/mmu-book3s-v3.h
+++ b/target/ppc/mmu-book3s-v3.h
@@ -17,8 +17,10 @@
* License along with this library; if not, see <http://www.gnu.org/licenses/>.
*/
-#ifndef MMU_H
-#define MMU_H
+#ifndef MMU_BOOOK3S_V3_H
+#define MMU_BOOOK3S_V3_H
+
+#include "mmu-hash64.h"
#ifndef CONFIG_USER_ONLY
@@ -29,7 +31,16 @@
#define PTCR_PATS 0x000000000000001FULL /* Partition Table Size */
/* Partition Table Entry Fields */
-#define PATBE1_GR 0x8000000000000000
+#define PATE0_HR 0x8000000000000000
+
+/*
+ * WARNING: This field doesn't actually exist in the final version of
+ * the architecture and is unused by hardware. However, qemu uses it
+ * as an indication of a radix guest in the pseudo-PATB entry that it
+ * maintains for SPAPR guests and in the migration stream, so we need
+ * to keep it around
+ */
+#define PATE1_GR 0x8000000000000000
/* Process Table Entry */
struct prtb_entry {
@@ -43,19 +54,68 @@
return !!(cpu->env.spr[SPR_LPCR] & LPCR_UPRT);
}
-static inline bool ppc64_radix_guest(PowerPCCPU *cpu)
-{
- PPCVirtualHypervisorClass *vhc =
- PPC_VIRTUAL_HYPERVISOR_GET_CLASS(cpu->vhyp);
+bool ppc64_v3_get_pate(PowerPCCPU *cpu, target_ulong lpid,
+ ppc_v3_pate_t *entry);
- return !!(vhc->get_patbe(cpu->vhyp) & PATBE1_GR);
+/*
+ * The LPCR:HR bit is a shortcut that avoids having to
+ * dig out the partition table in the fast path. This is
+ * also how the HW uses it.
+ */
+static inline bool ppc64_v3_radix(PowerPCCPU *cpu)
+{
+ return !!(cpu->env.spr[SPR_LPCR] & LPCR_HR);
}
+hwaddr ppc64_v3_get_phys_page_debug(PowerPCCPU *cpu, vaddr eaddr);
+
int ppc64_v3_handle_mmu_fault(PowerPCCPU *cpu, vaddr eaddr, int rwx,
int mmu_idx);
+static inline hwaddr ppc_hash64_hpt_base(PowerPCCPU *cpu)
+{
+ uint64_t base;
+
+ if (cpu->vhyp) {
+ return 0;
+ }
+ if (cpu->env.mmu_model == POWERPC_MMU_3_00) {
+ ppc_v3_pate_t pate;
+
+ if (!ppc64_v3_get_pate(cpu, cpu->env.spr[SPR_LPIDR], &pate)) {
+ return 0;
+ }
+ base = pate.dw0;
+ } else {
+ base = cpu->env.spr[SPR_SDR1];
+ }
+ return base & SDR_64_HTABORG;
+}
+
+static inline hwaddr ppc_hash64_hpt_mask(PowerPCCPU *cpu)
+{
+ uint64_t base;
+
+ if (cpu->vhyp) {
+ PPCVirtualHypervisorClass *vhc =
+ PPC_VIRTUAL_HYPERVISOR_GET_CLASS(cpu->vhyp);
+ return vhc->hpt_mask(cpu->vhyp);
+ }
+ if (cpu->env.mmu_model == POWERPC_MMU_3_00) {
+ ppc_v3_pate_t pate;
+
+ if (!ppc64_v3_get_pate(cpu, cpu->env.spr[SPR_LPIDR], &pate)) {
+ return 0;
+ }
+ base = pate.dw0;
+ } else {
+ base = cpu->env.spr[SPR_SDR1];
+ }
+ return (1ULL << ((base & SDR_64_HTABSIZE) + 18 - 7)) - 1;
+}
+
#endif /* TARGET_PPC64 */
#endif /* CONFIG_USER_ONLY */
-#endif /* MMU_H */
+#endif /* MMU_BOOOK3S_V3_H */
diff --git a/target/ppc/mmu-hash32.c b/target/ppc/mmu-hash32.c
index 03ae3c1..e8562a7 100644
--- a/target/ppc/mmu-hash32.c
+++ b/target/ppc/mmu-hash32.c
@@ -319,6 +319,12 @@
for (i = 0; i < HPTES_PER_GROUP; i++) {
pte0 = ppc_hash32_load_hpte0(cpu, pte_offset);
+ /*
+ * pte0 contains the valid bit and must be read before pte1,
+ * otherwise we might see an old pte1 with a new valid bit and
+ * thus an inconsistent hpte value
+ */
+ smp_rmb();
pte1 = ppc_hash32_load_hpte1(cpu, pte_offset);
if ((pte0 & HPTE32_V_VALID)
diff --git a/target/ppc/mmu-hash64.c b/target/ppc/mmu-hash64.c
index 276d901..c431303 100644
--- a/target/ppc/mmu-hash64.c
+++ b/target/ppc/mmu-hash64.c
@@ -417,7 +417,7 @@
hwaddr ptex, int n)
{
hwaddr pte_offset = ptex * HASH_PTE_SIZE_64;
- hwaddr base = ppc_hash64_hpt_base(cpu);
+ hwaddr base;
hwaddr plen = n * HASH_PTE_SIZE_64;
const ppc_hash_pte64_t *hptes;
@@ -426,6 +426,7 @@
PPC_VIRTUAL_HYPERVISOR_GET_CLASS(cpu->vhyp);
return vhc->map_hptes(cpu->vhyp, ptex, n);
}
+ base = ppc_hash64_hpt_base(cpu);
if (!base) {
return NULL;
@@ -490,6 +491,18 @@
return 0; /* Bad page size encoding */
}
+static void ppc64_v3_new_to_old_hpte(target_ulong *pte0, target_ulong *pte1)
+{
+ /* Insert B into pte0 */
+ *pte0 = (*pte0 & HPTE64_V_COMMON_BITS) |
+ ((*pte1 & HPTE64_R_3_0_SSIZE_MASK) <<
+ (HPTE64_V_SSIZE_SHIFT - HPTE64_R_3_0_SSIZE_SHIFT));
+
+ /* Remove B from pte1 */
+ *pte1 = *pte1 & ~HPTE64_R_3_0_SSIZE_MASK;
+}
+
+
static hwaddr ppc_hash64_pteg_search(PowerPCCPU *cpu, hwaddr hash,
const PPCHash64SegmentPageSizes *sps,
target_ulong ptem,
@@ -507,8 +520,19 @@
}
for (i = 0; i < HPTES_PER_GROUP; i++) {
pte0 = ppc_hash64_hpte0(cpu, pteg, i);
+ /*
+ * pte0 contains the valid bit and must be read before pte1,
+ * otherwise we might see an old pte1 with a new valid bit and
+ * thus an inconsistent hpte value
+ */
+ smp_rmb();
pte1 = ppc_hash64_hpte1(cpu, pteg, i);
+ /* Convert format if necessary */
+ if (cpu->env.mmu_model == POWERPC_MMU_3_00 && !cpu->vhyp) {
+ ppc64_v3_new_to_old_hpte(&pte0, &pte1);
+ }
+
/* This compares V, B, H (secondary) and the AVPN */
if (HPTE64_V_COMPARE(pte0, ptem)) {
*pshift = hpte_page_shift(sps, pte0, pte1);
@@ -918,7 +942,7 @@
void ppc_hash64_store_hpte(PowerPCCPU *cpu, hwaddr ptex,
uint64_t pte0, uint64_t pte1)
{
- hwaddr base = ppc_hash64_hpt_base(cpu);
+ hwaddr base;
hwaddr offset = ptex * HASH_PTE_SIZE_64;
if (cpu->vhyp) {
@@ -927,6 +951,7 @@
vhc->store_hpte(cpu->vhyp, ptex, pte0, pte1);
return;
}
+ base = ppc_hash64_hpt_base(cpu);
stq_phys(CPU(cpu)->as, base + offset, pte0);
stq_phys(CPU(cpu)->as, base + offset + HASH_PTE_SIZE_64 / 2, pte1);
@@ -1084,10 +1109,18 @@
case POWERPC_MMU_3_00: /* P9 */
lpcr = val & (LPCR_VPM1 | LPCR_ISL | LPCR_KBV | LPCR_DPFD |
(LPCR_PECE_U_MASK & LPCR_HVEE) | LPCR_ILE | LPCR_AIL |
- LPCR_UPRT | LPCR_EVIRT | LPCR_ONL |
+ LPCR_UPRT | LPCR_EVIRT | LPCR_ONL | LPCR_HR |
(LPCR_PECE_L_MASK & (LPCR_PDEE | LPCR_HDEE | LPCR_EEE |
LPCR_DEE | LPCR_OEE)) | LPCR_MER | LPCR_GTSE | LPCR_TC |
LPCR_HEIC | LPCR_LPES0 | LPCR_HVICE | LPCR_HDICE);
+ /*
+ * If we have a virtual hypervisor, we need to bring back RMLS. It
+ * doesn't exist on an actual P9 but that's all we know how to
+ * configure with softmmu at the moment
+ */
+ if (cpu->vhyp) {
+ lpcr |= (val & LPCR_RMLS);
+ }
break;
default:
;
diff --git a/target/ppc/mmu-hash64.h b/target/ppc/mmu-hash64.h
index f11efc9..6b555b7 100644
--- a/target/ppc/mmu-hash64.h
+++ b/target/ppc/mmu-hash64.h
@@ -63,6 +63,7 @@
#define SDR_64_HTABORG 0x0FFFFFFFFFFC0000ULL
#define SDR_64_HTABSIZE 0x000000000000001FULL
+#define PATE0_HTABORG 0x0FFFFFFFFFFC0000ULL
#define HPTES_PER_GROUP 8
#define HASH_PTE_SIZE_64 16
#define HASH_PTEG_SIZE_64 (HASH_PTE_SIZE_64 * HPTES_PER_GROUP)
@@ -102,23 +103,10 @@
#define HPTE64_V_1TB_SEG 0x4000000000000000ULL
#define HPTE64_V_VRMA_MASK 0x4001ffffff000000ULL
-static inline hwaddr ppc_hash64_hpt_base(PowerPCCPU *cpu)
-{
- if (cpu->vhyp) {
- return 0;
- }
- return cpu->env.spr[SPR_SDR1] & SDR_64_HTABORG;
-}
-
-static inline hwaddr ppc_hash64_hpt_mask(PowerPCCPU *cpu)
-{
- if (cpu->vhyp) {
- PPCVirtualHypervisorClass *vhc =
- PPC_VIRTUAL_HYPERVISOR_GET_CLASS(cpu->vhyp);
- return vhc->hpt_mask(cpu->vhyp);
- }
- return (1ULL << ((cpu->env.spr[SPR_SDR1] & SDR_64_HTABSIZE) + 18 - 7)) - 1;
-}
+/* Format changes for ARCH v3 */
+#define HPTE64_V_COMMON_BITS 0x000fffffffffffffULL
+#define HPTE64_R_3_0_SSIZE_SHIFT 58
+#define HPTE64_R_3_0_SSIZE_MASK (3ULL << HPTE64_R_3_0_SSIZE_SHIFT)
struct ppc_hash_pte64 {
uint64_t pte0, pte1;
diff --git a/target/ppc/mmu-radix64.c b/target/ppc/mmu-radix64.c
index ab76cbc..ca1fb26 100644
--- a/target/ppc/mmu-radix64.c
+++ b/target/ppc/mmu-radix64.c
@@ -31,10 +31,26 @@
static bool ppc_radix64_get_fully_qualified_addr(CPUPPCState *env, vaddr eaddr,
uint64_t *lpid, uint64_t *pid)
{
- /* We don't have HV support yet and shouldn't get here with it set anyway */
- assert(!msr_hv);
-
- if (!msr_hv) { /* !MSR[HV] -> Guest */
+ if (msr_hv) { /* MSR[HV] -> Hypervisor/bare metal */
+ switch (eaddr & R_EADDR_QUADRANT) {
+ case R_EADDR_QUADRANT0:
+ *lpid = 0;
+ *pid = env->spr[SPR_BOOKS_PID];
+ break;
+ case R_EADDR_QUADRANT1:
+ *lpid = env->spr[SPR_LPIDR];
+ *pid = env->spr[SPR_BOOKS_PID];
+ break;
+ case R_EADDR_QUADRANT2:
+ *lpid = env->spr[SPR_LPIDR];
+ *pid = 0;
+ break;
+ case R_EADDR_QUADRANT3:
+ *lpid = 0;
+ *pid = 0;
+ break;
+ }
+ } else { /* !MSR[HV] -> Guest */
switch (eaddr & R_EADDR_QUADRANT) {
case R_EADDR_QUADRANT0: /* Guest application */
*lpid = env->spr[SPR_LPIDR];
@@ -186,20 +202,32 @@
raddr, psize, fault_cause, pte_addr);
}
+static bool validate_pate(PowerPCCPU *cpu, uint64_t lpid, ppc_v3_pate_t *pate)
+{
+ CPUPPCState *env = &cpu->env;
+
+ if (!(pate->dw0 & PATE0_HR)) {
+ return false;
+ }
+ if (lpid == 0 && !msr_hv) {
+ return false;
+ }
+ /* More checks ... */
+ return true;
+}
+
int ppc_radix64_handle_mmu_fault(PowerPCCPU *cpu, vaddr eaddr, int rwx,
int mmu_idx)
{
CPUState *cs = CPU(cpu);
CPUPPCState *env = &cpu->env;
- PPCVirtualHypervisorClass *vhc =
- PPC_VIRTUAL_HYPERVISOR_GET_CLASS(cpu->vhyp);
+ PPCVirtualHypervisorClass *vhc;
hwaddr raddr, pte_addr;
- uint64_t lpid = 0, pid = 0, offset, size, patbe, prtbe0, pte;
+ uint64_t lpid = 0, pid = 0, offset, size, prtbe0, pte;
int page_size, prot, fault_cause = 0;
+ ppc_v3_pate_t pate;
assert((rwx == 0) || (rwx == 1) || (rwx == 2));
- assert(!msr_hv); /* For now there is no Radix PowerNV Support */
- assert(cpu->vhyp);
assert(ppc64_use_proc_tbl(cpu));
/* Real Mode Access */
@@ -220,17 +248,33 @@
}
/* Get Process Table */
- patbe = vhc->get_patbe(cpu->vhyp);
+ if (cpu->vhyp) {
+ vhc = PPC_VIRTUAL_HYPERVISOR_GET_CLASS(cpu->vhyp);
+ vhc->get_pate(cpu->vhyp, &pate);
+ } else {
+ if (!ppc64_v3_get_pate(cpu, lpid, &pate)) {
+ ppc_radix64_raise_si(cpu, rwx, eaddr, DSISR_NOPTE);
+ return 1;
+ }
+ if (!validate_pate(cpu, lpid, &pate)) {
+ ppc_radix64_raise_si(cpu, rwx, eaddr, DSISR_R_BADCONFIG);
+ }
+ /* We don't support guest mode yet */
+ if (lpid != 0) {
+ error_report("PowerNV guest support Unimplemented");
+ exit(1);
+ }
+ }
/* Index Process Table by PID to Find Corresponding Process Table Entry */
offset = pid * sizeof(struct prtb_entry);
- size = 1ULL << ((patbe & PATBE1_R_PRTS) + 12);
+ size = 1ULL << ((pate.dw1 & PATE1_R_PRTS) + 12);
if (offset >= size) {
/* offset exceeds size of the process table */
ppc_radix64_raise_si(cpu, rwx, eaddr, DSISR_NOPTE);
return 1;
}
- prtbe0 = ldq_phys(cs->as, (patbe & PATBE1_R_PRTB) + offset);
+ prtbe0 = ldq_phys(cs->as, (pate.dw1 & PATE1_R_PRTB) + offset);
/* Walk Radix Tree from Process Table Entry to Convert EA to RA */
page_size = PRTBE_R_GET_RTS(prtbe0);
@@ -255,11 +299,11 @@
{
CPUState *cs = CPU(cpu);
CPUPPCState *env = &cpu->env;
- PPCVirtualHypervisorClass *vhc =
- PPC_VIRTUAL_HYPERVISOR_GET_CLASS(cpu->vhyp);
+ PPCVirtualHypervisorClass *vhc;
hwaddr raddr, pte_addr;
- uint64_t lpid = 0, pid = 0, offset, size, patbe, prtbe0, pte;
+ uint64_t lpid = 0, pid = 0, offset, size, prtbe0, pte;
int page_size, fault_cause = 0;
+ ppc_v3_pate_t pate;
/* Handle Real Mode */
if (msr_dr == 0) {
@@ -273,16 +317,31 @@
}
/* Get Process Table */
- patbe = vhc->get_patbe(cpu->vhyp);
+ if (cpu->vhyp) {
+ vhc = PPC_VIRTUAL_HYPERVISOR_GET_CLASS(cpu->vhyp);
+ vhc->get_pate(cpu->vhyp, &pate);
+ } else {
+ if (!ppc64_v3_get_pate(cpu, lpid, &pate)) {
+ return -1;
+ }
+ if (!validate_pate(cpu, lpid, &pate)) {
+ return -1;
+ }
+ /* We don't support guest mode yet */
+ if (lpid != 0) {
+ error_report("PowerNV guest support Unimplemented");
+ exit(1);
+ }
+ }
/* Index Process Table by PID to Find Corresponding Process Table Entry */
offset = pid * sizeof(struct prtb_entry);
- size = 1ULL << ((patbe & PATBE1_R_PRTS) + 12);
+ size = 1ULL << ((pate.dw1 & PATE1_R_PRTS) + 12);
if (offset >= size) {
/* offset exceeds size of the process table */
return -1;
}
- prtbe0 = ldq_phys(cs->as, (patbe & PATBE1_R_PRTB) + offset);
+ prtbe0 = ldq_phys(cs->as, (pate.dw1 & PATE1_R_PRTB) + offset);
/* Walk Radix Tree from Process Table Entry to Convert EA to RA */
page_size = PRTBE_R_GET_RTS(prtbe0);
diff --git a/target/ppc/mmu-radix64.h b/target/ppc/mmu-radix64.h
index 0ecf063..9622854 100644
--- a/target/ppc/mmu-radix64.h
+++ b/target/ppc/mmu-radix64.h
@@ -12,8 +12,8 @@
#define R_EADDR_QUADRANT3 0xC000000000000000
/* Radix Partition Table Entry Fields */
-#define PATBE1_R_PRTB 0x0FFFFFFFFFFFF000
-#define PATBE1_R_PRTS 0x000000000000001F
+#define PATE1_R_PRTB 0x0FFFFFFFFFFFF000
+#define PATE1_R_PRTS 0x000000000000001F
/* Radix Process Table Entry Fields */
#define PRTBE_R_GET_RTS(rts) \
diff --git a/target/ppc/mmu_helper.c b/target/ppc/mmu_helper.c
index bcf19da..4a6be4d 100644
--- a/target/ppc/mmu_helper.c
+++ b/target/ppc/mmu_helper.c
@@ -1342,7 +1342,7 @@
dump_slb(f, cpu_fprintf, ppc_env_get_cpu(env));
break;
case POWERPC_MMU_3_00:
- if (ppc64_radix_guest(ppc_env_get_cpu(env))) {
+ if (ppc64_v3_radix(ppc_env_get_cpu(env))) {
/* TODO - Unsupported */
} else {
dump_slb(f, cpu_fprintf, ppc_env_get_cpu(env));
@@ -1489,12 +1489,7 @@
case POWERPC_MMU_2_07:
return ppc_hash64_get_phys_page_debug(cpu, addr);
case POWERPC_MMU_3_00:
- if (ppc64_radix_guest(ppc_env_get_cpu(env))) {
- return ppc_radix64_get_phys_page_debug(cpu, addr);
- } else {
- return ppc_hash64_get_phys_page_debug(cpu, addr);
- }
- break;
+ return ppc64_v3_get_phys_page_debug(cpu, addr);
#endif
case POWERPC_MMU_32B:
diff --git a/target/ppc/translate.c b/target/ppc/translate.c
index f4d70e7..819221f 100644
--- a/target/ppc/translate.c
+++ b/target/ppc/translate.c
@@ -3566,7 +3566,8 @@
t = tcg_const_i32(PPC_PM_DOZE);
gen_helper_pminsn(cpu_env, t);
tcg_temp_free_i32(t);
- gen_stop_exception(ctx);
+ /* Stop translation, as the CPU is supposed to sleep from now */
+ gen_exception_nip(ctx, EXCP_HLT, ctx->base.pc_next);
#endif /* defined(CONFIG_USER_ONLY) */
}
@@ -3581,13 +3582,25 @@
t = tcg_const_i32(PPC_PM_NAP);
gen_helper_pminsn(cpu_env, t);
tcg_temp_free_i32(t);
- gen_stop_exception(ctx);
+ /* Stop translation, as the CPU is supposed to sleep from now */
+ gen_exception_nip(ctx, EXCP_HLT, ctx->base.pc_next);
#endif /* defined(CONFIG_USER_ONLY) */
}
static void gen_stop(DisasContext *ctx)
{
- gen_nap(ctx);
+#if defined(CONFIG_USER_ONLY)
+ GEN_PRIV;
+#else
+ TCGv_i32 t;
+
+ CHK_HV;
+ t = tcg_const_i32(PPC_PM_STOP);
+ gen_helper_pminsn(cpu_env, t);
+ tcg_temp_free_i32(t);
+ /* Stop translation, as the CPU is supposed to sleep from now */
+ gen_exception_nip(ctx, EXCP_HLT, ctx->base.pc_next);
+#endif /* defined(CONFIG_USER_ONLY) */
}
static void gen_sleep(DisasContext *ctx)
@@ -3601,7 +3614,8 @@
t = tcg_const_i32(PPC_PM_SLEEP);
gen_helper_pminsn(cpu_env, t);
tcg_temp_free_i32(t);
- gen_stop_exception(ctx);
+ /* Stop translation, as the CPU is supposed to sleep from now */
+ gen_exception_nip(ctx, EXCP_HLT, ctx->base.pc_next);
#endif /* defined(CONFIG_USER_ONLY) */
}
@@ -3616,7 +3630,8 @@
t = tcg_const_i32(PPC_PM_RVWINKLE);
gen_helper_pminsn(cpu_env, t);
tcg_temp_free_i32(t);
- gen_stop_exception(ctx);
+ /* Stop translation, as the CPU is supposed to sleep from now */
+ gen_exception_nip(ctx, EXCP_HLT, ctx->base.pc_next);
#endif /* defined(CONFIG_USER_ONLY) */
}
#endif /* #if defined(TARGET_PPC64) */
@@ -7466,7 +7481,8 @@
#if defined(TARGET_PPC64)
if (env->excp_model == POWERPC_EXCP_POWER7 ||
- env->excp_model == POWERPC_EXCP_POWER8) {
+ env->excp_model == POWERPC_EXCP_POWER8 ||
+ env->excp_model == POWERPC_EXCP_POWER9) {
cpu_fprintf(f, "HSRR0 " TARGET_FMT_lx " HSRR1 " TARGET_FMT_lx "\n",
env->spr[SPR_HSRR0], env->spr[SPR_HSRR1]);
}
diff --git a/target/ppc/translate_init.inc.c b/target/ppc/translate_init.inc.c
index d884906..58542c0 100644
--- a/target/ppc/translate_init.inc.c
+++ b/target/ppc/translate_init.inc.c
@@ -408,6 +408,11 @@
gen_helper_store_pidr(cpu_env, cpu_gpr[gprn]);
}
+static void spr_write_lpidr(DisasContext *ctx, int sprn, int gprn)
+{
+ gen_helper_store_lpidr(cpu_env, cpu_gpr[gprn]);
+}
+
static void spr_read_hior(DisasContext *ctx, int gprn, int sprn)
{
tcg_gen_ld_tl(cpu_gpr[gprn], cpu_env, offsetof(CPUPPCState, excp_prefix));
@@ -3313,6 +3318,15 @@
#endif
}
+static void init_excp_POWER9(CPUPPCState *env)
+{
+ init_excp_POWER8(env);
+
+#if !defined(CONFIG_USER_ONLY)
+ env->excp_vectors[POWERPC_EXCP_HVIRT] = 0x00000EA0;
+#endif
+}
+
#endif
/*****************************************************************************/
@@ -7876,7 +7890,7 @@
spr_register_hv(env, SPR_LPIDR, "LPIDR",
SPR_NOACCESS, SPR_NOACCESS,
SPR_NOACCESS, SPR_NOACCESS,
- &spr_read_generic, &spr_write_generic,
+ &spr_read_generic, &spr_write_lpidr,
0x00000000);
spr_register_hv(env, SPR_HFSCR, "HFSCR",
SPR_NOACCESS, SPR_NOACCESS,
@@ -8783,8 +8797,8 @@
env->icache_line_size = 128;
/* Allocate hardware IRQ controller */
- init_excp_POWER8(env);
- ppcPOWER7_irq_init(ppc_env_get_cpu(env));
+ init_excp_POWER9(env);
+ ppcPOWER9_irq_init(ppc_env_get_cpu(env));
}
static bool ppc_pvr_match_power9(PowerPCCPUClass *pcc, uint32_t pvr)
@@ -8801,13 +8815,23 @@
CPUPPCState *env = &cpu->env;
if (cs->halted) {
+ uint64_t psscr = env->spr[SPR_PSSCR];
+
if (!(cs->interrupt_request & CPU_INTERRUPT_HARD)) {
return false;
}
+
+ /* If EC is clear, just return true on any pending interrupt */
+ if (!(psscr & PSSCR_EC)) {
+ return true;
+ }
/* External Exception */
if ((env->pending_interrupts & (1u << PPC_INTERRUPT_EXT)) &&
(env->spr[SPR_LPCR] & LPCR_EEE)) {
- return true;
+ bool heic = !!(env->spr[SPR_LPCR] & LPCR_HEIC);
+ if (heic == 0 || !msr_hv || msr_pr) {
+ return true;
+ }
}
/* Decrementer Exception */
if ((env->pending_interrupts & (1u << PPC_INTERRUPT_DECR)) &&
@@ -8829,6 +8853,11 @@
(env->spr[SPR_LPCR] & LPCR_HDEE)) {
return true;
}
+ /* Hypervisor virtualization exception */
+ if ((env->pending_interrupts & (1u << PPC_INTERRUPT_HVIRT)) &&
+ (env->spr[SPR_LPCR] & LPCR_HVEE)) {
+ return true;
+ }
if (env->pending_interrupts & (1u << PPC_INTERRUPT_RESET)) {
return true;
}
@@ -8898,8 +8927,8 @@
pcc->hash64_opts = &ppc_hash64_opts_POWER7;
pcc->radix_page_info = &POWER9_radix_page_info;
#endif
- pcc->excp_model = POWERPC_EXCP_POWER8;
- pcc->bus_model = PPC_FLAGS_INPUT_POWER7;
+ pcc->excp_model = POWERPC_EXCP_POWER9;
+ pcc->bus_model = PPC_FLAGS_INPUT_POWER9;
pcc->bfd_mach = bfd_mach_ppc64;
pcc->flags = POWERPC_FLAG_VRE | POWERPC_FLAG_SE |
POWERPC_FLAG_BE | POWERPC_FLAG_PMM |
diff --git a/target/s390x/cc_helper.c b/target/s390x/cc_helper.c
index 307ad61..0e467bf 100644
--- a/target/s390x/cc_helper.c
+++ b/target/s390x/cc_helper.c
@@ -397,6 +397,11 @@
return dst ? 2 : 0;
}
+static uint32_t cc_calc_lcbb(uint64_t dst)
+{
+ return dst == 16 ? 0 : 3;
+}
+
static uint32_t do_calc_cc(CPUS390XState *env, uint32_t cc_op,
uint64_t src, uint64_t dst, uint64_t vr)
{
@@ -506,6 +511,9 @@
case CC_OP_FLOGR:
r = cc_calc_flogr(dst);
break;
+ case CC_OP_LCBB:
+ r = cc_calc_lcbb(dst);
+ break;
case CC_OP_NZ_F32:
r = set_cc_nz_f32(dst);
diff --git a/target/s390x/excp_helper.c b/target/s390x/excp_helper.c
index a758649..f84bfb1 100644
--- a/target/s390x/excp_helper.c
+++ b/target/s390x/excp_helper.c
@@ -347,10 +347,41 @@
load_psw(env, mask, addr);
}
+typedef struct MchkExtSaveArea {
+ uint64_t vregs[32][2]; /* 0x0000 */
+ uint8_t pad_0x0200[0x0400 - 0x0200]; /* 0x0200 */
+} MchkExtSaveArea;
+QEMU_BUILD_BUG_ON(sizeof(MchkExtSaveArea) != 1024);
+
+static int mchk_store_vregs(CPUS390XState *env, uint64_t mcesao)
+{
+ hwaddr len = sizeof(MchkExtSaveArea);
+ MchkExtSaveArea *sa;
+ int i;
+
+ sa = cpu_physical_memory_map(mcesao, &len, 1);
+ if (!sa) {
+ return -EFAULT;
+ }
+ if (len != sizeof(MchkExtSaveArea)) {
+ cpu_physical_memory_unmap(sa, len, 1, 0);
+ return -EFAULT;
+ }
+
+ 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);
+ }
+
+ cpu_physical_memory_unmap(sa, len, 1, len);
+ return 0;
+}
+
static void do_mchk_interrupt(CPUS390XState *env)
{
QEMUS390FLICState *flic = QEMU_S390_FLIC(s390_get_flic());
- uint64_t mask, addr;
+ uint64_t mcic = s390_build_validity_mcic() | MCIC_SC_CP;
+ uint64_t mask, addr, mcesao = 0;
LowCore *lowcore;
int i;
@@ -362,6 +393,17 @@
lowcore = cpu_map_lowcore(env);
+ /* extended save area */
+ if (mcic & MCIC_VB_VR) {
+ /* length and alignment is 1024 bytes */
+ mcesao = be64_to_cpu(lowcore->mcesad) & ~0x3ffull;
+ }
+
+ /* try to store vector registers */
+ if (!mcesao || mchk_store_vregs(env, mcesao)) {
+ mcic &= ~MCIC_VB_VR;
+ }
+
/* we are always in z/Architecture mode */
lowcore->ar_access_id = 1;
@@ -377,7 +419,7 @@
lowcore->cpu_timer_save_area = cpu_to_be64(env->cputm);
lowcore->clock_comp_save_area = cpu_to_be64(env->ckc >> 8);
- lowcore->mcic = cpu_to_be64(s390_build_validity_mcic() | MCIC_SC_CP);
+ lowcore->mcic = cpu_to_be64(mcic);
lowcore->mcck_old_psw.mask = cpu_to_be64(get_psw_mask(env));
lowcore->mcck_old_psw.addr = cpu_to_be64(env->psw.addr);
mask = be64_to_cpu(lowcore->mcck_new_psw.mask);
diff --git a/target/s390x/fpu_helper.c b/target/s390x/fpu_helper.c
index e921172..1be68ba 100644
--- a/target/s390x/fpu_helper.c
+++ b/target/s390x/fpu_helper.c
@@ -36,13 +36,21 @@
#define RET128(F) (env->retxl = F.low, F.high)
-#define convert_bit(mask, from, to) \
- (to < from \
- ? (mask / (from / to)) & to \
- : (mask & from) * (to / from))
+uint8_t s390_softfloat_exc_to_ieee(unsigned int exc)
+{
+ uint8_t s390_exc = 0;
+
+ s390_exc |= (exc & float_flag_invalid) ? S390_IEEE_MASK_INVALID : 0;
+ s390_exc |= (exc & float_flag_divbyzero) ? S390_IEEE_MASK_DIVBYZERO : 0;
+ s390_exc |= (exc & float_flag_overflow) ? S390_IEEE_MASK_OVERFLOW : 0;
+ s390_exc |= (exc & float_flag_underflow) ? S390_IEEE_MASK_UNDERFLOW : 0;
+ s390_exc |= (exc & float_flag_inexact) ? S390_IEEE_MASK_INEXACT : 0;
+
+ return s390_exc;
+}
/* Should be called after any operation that may raise IEEE exceptions. */
-static void handle_exceptions(CPUS390XState *env, uintptr_t retaddr)
+static void handle_exceptions(CPUS390XState *env, bool XxC, uintptr_t retaddr)
{
unsigned s390_exc, qemu_exc;
@@ -53,22 +61,54 @@
return;
}
env->fpu_status.float_exception_flags = 0;
+ s390_exc = s390_softfloat_exc_to_ieee(qemu_exc);
- /* Convert softfloat exception bits to s390 exception bits. */
- s390_exc = 0;
- s390_exc |= convert_bit(qemu_exc, float_flag_invalid, 0x80);
- s390_exc |= convert_bit(qemu_exc, float_flag_divbyzero, 0x40);
- s390_exc |= convert_bit(qemu_exc, float_flag_overflow, 0x20);
- s390_exc |= convert_bit(qemu_exc, float_flag_underflow, 0x10);
- s390_exc |= convert_bit(qemu_exc, float_flag_inexact, 0x08);
+ /*
+ * IEEE-Underflow exception recognition exists if a tininess condition
+ * (underflow) exists and
+ * - The mask bit in the FPC is zero and the result is inexact
+ * - The mask bit in the FPC is one
+ * So tininess conditions that are not inexact don't trigger any
+ * underflow action in case the mask bit is not one.
+ */
+ if (!(s390_exc & S390_IEEE_MASK_INEXACT) &&
+ !((env->fpc >> 24) & S390_IEEE_MASK_UNDERFLOW)) {
+ s390_exc &= ~S390_IEEE_MASK_UNDERFLOW;
+ }
- /* Install the exceptions that we raised. */
- env->fpc |= s390_exc << 16;
+ /*
+ * FIXME:
+ * 1. Right now, all inexact conditions are inidicated as
+ * "truncated" (0) and never as "incremented" (1) in the DXC.
+ * 2. Only traps due to invalid/divbyzero are suppressing. Other traps
+ * are completing, meaning the target register has to be written!
+ * This, however will mean that we have to write the register before
+ * triggering the trap - impossible right now.
+ */
- /* Send signals for enabled exceptions. */
- s390_exc &= env->fpc >> 24;
- if (s390_exc) {
- tcg_s390_data_exception(env, s390_exc, retaddr);
+ /*
+ * invalid/divbyzero cannot coexist with other conditions.
+ * overflow/underflow however can coexist with inexact, we have to
+ * handle it separatly.
+ */
+ if (s390_exc & ~S390_IEEE_MASK_INEXACT) {
+ if (s390_exc & ~S390_IEEE_MASK_INEXACT & env->fpc >> 24) {
+ /* trap condition - inexact reported along */
+ tcg_s390_data_exception(env, s390_exc, retaddr);
+ }
+ /* nontrap condition - inexact handled differently */
+ env->fpc |= (s390_exc & ~S390_IEEE_MASK_INEXACT) << 16;
+ }
+
+ /* inexact handling */
+ if (s390_exc & S390_IEEE_MASK_INEXACT && !XxC) {
+ /* trap condition - overflow/underflow _not_ reported along */
+ if (s390_exc & S390_IEEE_MASK_INEXACT & env->fpc >> 24) {
+ tcg_s390_data_exception(env, s390_exc & S390_IEEE_MASK_INEXACT,
+ retaddr);
+ }
+ /* nontrap condition */
+ env->fpc |= (s390_exc & S390_IEEE_MASK_INEXACT) << 16;
}
}
@@ -130,11 +170,22 @@
}
}
+static inline uint8_t round_from_m34(uint32_t m34)
+{
+ return extract32(m34, 0, 4);
+}
+
+static inline bool xxc_from_m34(uint32_t m34)
+{
+ /* XxC is bit 1 of m4 */
+ return extract32(m34, 4 + 3 - 1, 1);
+}
+
/* 32-bit FP addition */
uint64_t HELPER(aeb)(CPUS390XState *env, uint64_t f1, uint64_t f2)
{
float32 ret = float32_add(f1, f2, &env->fpu_status);
- handle_exceptions(env, GETPC());
+ handle_exceptions(env, false, GETPC());
return ret;
}
@@ -142,7 +193,7 @@
uint64_t HELPER(adb)(CPUS390XState *env, uint64_t f1, uint64_t f2)
{
float64 ret = float64_add(f1, f2, &env->fpu_status);
- handle_exceptions(env, GETPC());
+ handle_exceptions(env, false, GETPC());
return ret;
}
@@ -153,7 +204,7 @@
float128 ret = float128_add(make_float128(ah, al),
make_float128(bh, bl),
&env->fpu_status);
- handle_exceptions(env, GETPC());
+ handle_exceptions(env, false, GETPC());
return RET128(ret);
}
@@ -161,7 +212,7 @@
uint64_t HELPER(seb)(CPUS390XState *env, uint64_t f1, uint64_t f2)
{
float32 ret = float32_sub(f1, f2, &env->fpu_status);
- handle_exceptions(env, GETPC());
+ handle_exceptions(env, false, GETPC());
return ret;
}
@@ -169,7 +220,7 @@
uint64_t HELPER(sdb)(CPUS390XState *env, uint64_t f1, uint64_t f2)
{
float64 ret = float64_sub(f1, f2, &env->fpu_status);
- handle_exceptions(env, GETPC());
+ handle_exceptions(env, false, GETPC());
return ret;
}
@@ -180,7 +231,7 @@
float128 ret = float128_sub(make_float128(ah, al),
make_float128(bh, bl),
&env->fpu_status);
- handle_exceptions(env, GETPC());
+ handle_exceptions(env, false, GETPC());
return RET128(ret);
}
@@ -188,7 +239,7 @@
uint64_t HELPER(deb)(CPUS390XState *env, uint64_t f1, uint64_t f2)
{
float32 ret = float32_div(f1, f2, &env->fpu_status);
- handle_exceptions(env, GETPC());
+ handle_exceptions(env, false, GETPC());
return ret;
}
@@ -196,7 +247,7 @@
uint64_t HELPER(ddb)(CPUS390XState *env, uint64_t f1, uint64_t f2)
{
float64 ret = float64_div(f1, f2, &env->fpu_status);
- handle_exceptions(env, GETPC());
+ handle_exceptions(env, false, GETPC());
return ret;
}
@@ -207,7 +258,7 @@
float128 ret = float128_div(make_float128(ah, al),
make_float128(bh, bl),
&env->fpu_status);
- handle_exceptions(env, GETPC());
+ handle_exceptions(env, false, GETPC());
return RET128(ret);
}
@@ -215,7 +266,7 @@
uint64_t HELPER(meeb)(CPUS390XState *env, uint64_t f1, uint64_t f2)
{
float32 ret = float32_mul(f1, f2, &env->fpu_status);
- handle_exceptions(env, GETPC());
+ handle_exceptions(env, false, GETPC());
return ret;
}
@@ -223,7 +274,7 @@
uint64_t HELPER(mdb)(CPUS390XState *env, uint64_t f1, uint64_t f2)
{
float64 ret = float64_mul(f1, f2, &env->fpu_status);
- handle_exceptions(env, GETPC());
+ handle_exceptions(env, false, GETPC());
return ret;
}
@@ -232,7 +283,7 @@
{
float64 ret = float32_to_float64(f2, &env->fpu_status);
ret = float64_mul(f1, ret, &env->fpu_status);
- handle_exceptions(env, GETPC());
+ handle_exceptions(env, false, GETPC());
return ret;
}
@@ -243,7 +294,7 @@
float128 ret = float128_mul(make_float128(ah, al),
make_float128(bh, bl),
&env->fpu_status);
- handle_exceptions(env, GETPC());
+ handle_exceptions(env, false, GETPC());
return RET128(ret);
}
@@ -253,7 +304,7 @@
{
float128 ret = float64_to_float128(f2, &env->fpu_status);
ret = float128_mul(make_float128(ah, al), ret, &env->fpu_status);
- handle_exceptions(env, GETPC());
+ handle_exceptions(env, false, GETPC());
return RET128(ret);
}
@@ -261,15 +312,19 @@
uint64_t HELPER(ldeb)(CPUS390XState *env, uint64_t f2)
{
float64 ret = float32_to_float64(f2, &env->fpu_status);
- handle_exceptions(env, GETPC());
+ handle_exceptions(env, false, GETPC());
return ret;
}
/* convert 128-bit float to 64-bit float */
-uint64_t HELPER(ldxb)(CPUS390XState *env, uint64_t ah, uint64_t al)
+uint64_t HELPER(ldxb)(CPUS390XState *env, uint64_t ah, uint64_t al,
+ uint32_t m34)
{
+ int old_mode = s390_swap_bfp_rounding_mode(env, round_from_m34(m34));
float64 ret = float128_to_float64(make_float128(ah, al), &env->fpu_status);
- handle_exceptions(env, GETPC());
+
+ s390_restore_bfp_rounding_mode(env, old_mode);
+ handle_exceptions(env, xxc_from_m34(m34), GETPC());
return ret;
}
@@ -277,7 +332,7 @@
uint64_t HELPER(lxdb)(CPUS390XState *env, uint64_t f2)
{
float128 ret = float64_to_float128(f2, &env->fpu_status);
- handle_exceptions(env, GETPC());
+ handle_exceptions(env, false, GETPC());
return RET128(ret);
}
@@ -285,23 +340,30 @@
uint64_t HELPER(lxeb)(CPUS390XState *env, uint64_t f2)
{
float128 ret = float32_to_float128(f2, &env->fpu_status);
- handle_exceptions(env, GETPC());
+ handle_exceptions(env, false, GETPC());
return RET128(ret);
}
/* convert 64-bit float to 32-bit float */
-uint64_t HELPER(ledb)(CPUS390XState *env, uint64_t f2)
+uint64_t HELPER(ledb)(CPUS390XState *env, uint64_t f2, uint32_t m34)
{
+ int old_mode = s390_swap_bfp_rounding_mode(env, round_from_m34(m34));
float32 ret = float64_to_float32(f2, &env->fpu_status);
- handle_exceptions(env, GETPC());
+
+ s390_restore_bfp_rounding_mode(env, old_mode);
+ handle_exceptions(env, xxc_from_m34(m34), GETPC());
return ret;
}
/* convert 128-bit float to 32-bit float */
-uint64_t HELPER(lexb)(CPUS390XState *env, uint64_t ah, uint64_t al)
+uint64_t HELPER(lexb)(CPUS390XState *env, uint64_t ah, uint64_t al,
+ uint32_t m34)
{
+ int old_mode = s390_swap_bfp_rounding_mode(env, round_from_m34(m34));
float32 ret = float128_to_float32(make_float128(ah, al), &env->fpu_status);
- handle_exceptions(env, GETPC());
+
+ s390_restore_bfp_rounding_mode(env, old_mode);
+ handle_exceptions(env, xxc_from_m34(m34), GETPC());
return ret;
}
@@ -309,7 +371,7 @@
uint32_t HELPER(ceb)(CPUS390XState *env, uint64_t f1, uint64_t f2)
{
int cmp = float32_compare_quiet(f1, f2, &env->fpu_status);
- handle_exceptions(env, GETPC());
+ handle_exceptions(env, false, GETPC());
return float_comp_to_cc(env, cmp);
}
@@ -317,7 +379,7 @@
uint32_t HELPER(cdb)(CPUS390XState *env, uint64_t f1, uint64_t f2)
{
int cmp = float64_compare_quiet(f1, f2, &env->fpu_status);
- handle_exceptions(env, GETPC());
+ handle_exceptions(env, false, GETPC());
return float_comp_to_cc(env, cmp);
}
@@ -328,21 +390,28 @@
int cmp = float128_compare_quiet(make_float128(ah, al),
make_float128(bh, bl),
&env->fpu_status);
- handle_exceptions(env, GETPC());
+ handle_exceptions(env, false, GETPC());
return float_comp_to_cc(env, cmp);
}
-static int swap_round_mode(CPUS390XState *env, int m3)
+int s390_swap_bfp_rounding_mode(CPUS390XState *env, int m3)
{
int ret = env->fpu_status.float_rounding_mode;
+
switch (m3) {
case 0:
/* current mode */
break;
case 1:
- /* biased round no nearest */
+ /* round to nearest with ties away from 0 */
+ set_float_rounding_mode(float_round_ties_away, &env->fpu_status);
+ break;
+ case 3:
+ /* round to prepare for shorter precision */
+ set_float_rounding_mode(float_round_to_odd, &env->fpu_status);
+ break;
case 4:
- /* round to nearest */
+ /* round to nearest with ties to even */
set_float_rounding_mode(float_round_nearest_even, &env->fpu_status);
break;
case 5:
@@ -357,226 +426,251 @@
/* round to -inf */
set_float_rounding_mode(float_round_down, &env->fpu_status);
break;
+ default:
+ g_assert_not_reached();
}
return ret;
}
-/* convert 64-bit int to 32-bit float */
-uint64_t HELPER(cegb)(CPUS390XState *env, int64_t v2, uint32_t m3)
+void s390_restore_bfp_rounding_mode(CPUS390XState *env, int old_mode)
{
- int hold = swap_round_mode(env, m3);
+ set_float_rounding_mode(old_mode, &env->fpu_status);
+}
+
+/* convert 64-bit int to 32-bit float */
+uint64_t HELPER(cegb)(CPUS390XState *env, int64_t v2, uint32_t m34)
+{
+ int old_mode = s390_swap_bfp_rounding_mode(env, round_from_m34(m34));
float32 ret = int64_to_float32(v2, &env->fpu_status);
- set_float_rounding_mode(hold, &env->fpu_status);
- handle_exceptions(env, GETPC());
+
+ s390_restore_bfp_rounding_mode(env, old_mode);
+ handle_exceptions(env, xxc_from_m34(m34), GETPC());
return ret;
}
/* convert 64-bit int to 64-bit float */
-uint64_t HELPER(cdgb)(CPUS390XState *env, int64_t v2, uint32_t m3)
+uint64_t HELPER(cdgb)(CPUS390XState *env, int64_t v2, uint32_t m34)
{
- int hold = swap_round_mode(env, m3);
+ int old_mode = s390_swap_bfp_rounding_mode(env, round_from_m34(m34));
float64 ret = int64_to_float64(v2, &env->fpu_status);
- set_float_rounding_mode(hold, &env->fpu_status);
- handle_exceptions(env, GETPC());
+
+ s390_restore_bfp_rounding_mode(env, old_mode);
+ handle_exceptions(env, xxc_from_m34(m34), GETPC());
return ret;
}
/* convert 64-bit int to 128-bit float */
-uint64_t HELPER(cxgb)(CPUS390XState *env, int64_t v2, uint32_t m3)
+uint64_t HELPER(cxgb)(CPUS390XState *env, int64_t v2, uint32_t m34)
{
- int hold = swap_round_mode(env, m3);
+ int old_mode = s390_swap_bfp_rounding_mode(env, round_from_m34(m34));
float128 ret = int64_to_float128(v2, &env->fpu_status);
- set_float_rounding_mode(hold, &env->fpu_status);
- handle_exceptions(env, GETPC());
+
+ s390_restore_bfp_rounding_mode(env, old_mode);
+ handle_exceptions(env, xxc_from_m34(m34), GETPC());
return RET128(ret);
}
/* convert 64-bit uint to 32-bit float */
-uint64_t HELPER(celgb)(CPUS390XState *env, uint64_t v2, uint32_t m3)
+uint64_t HELPER(celgb)(CPUS390XState *env, uint64_t v2, uint32_t m34)
{
- int hold = swap_round_mode(env, m3);
+ int old_mode = s390_swap_bfp_rounding_mode(env, round_from_m34(m34));
float32 ret = uint64_to_float32(v2, &env->fpu_status);
- set_float_rounding_mode(hold, &env->fpu_status);
- handle_exceptions(env, GETPC());
+
+ s390_restore_bfp_rounding_mode(env, old_mode);
+ handle_exceptions(env, xxc_from_m34(m34), GETPC());
return ret;
}
/* convert 64-bit uint to 64-bit float */
-uint64_t HELPER(cdlgb)(CPUS390XState *env, uint64_t v2, uint32_t m3)
+uint64_t HELPER(cdlgb)(CPUS390XState *env, uint64_t v2, uint32_t m34)
{
- int hold = swap_round_mode(env, m3);
+ int old_mode = s390_swap_bfp_rounding_mode(env, round_from_m34(m34));
float64 ret = uint64_to_float64(v2, &env->fpu_status);
- set_float_rounding_mode(hold, &env->fpu_status);
- handle_exceptions(env, GETPC());
+
+ s390_restore_bfp_rounding_mode(env, old_mode);
+ handle_exceptions(env, xxc_from_m34(m34), GETPC());
return ret;
}
/* convert 64-bit uint to 128-bit float */
-uint64_t HELPER(cxlgb)(CPUS390XState *env, uint64_t v2, uint32_t m3)
+uint64_t HELPER(cxlgb)(CPUS390XState *env, uint64_t v2, uint32_t m34)
{
- int hold = swap_round_mode(env, m3);
+ int old_mode = s390_swap_bfp_rounding_mode(env, round_from_m34(m34));
float128 ret = uint64_to_float128(v2, &env->fpu_status);
- set_float_rounding_mode(hold, &env->fpu_status);
- handle_exceptions(env, GETPC());
+
+ s390_restore_bfp_rounding_mode(env, old_mode);
+ handle_exceptions(env, xxc_from_m34(m34), GETPC());
return RET128(ret);
}
/* convert 32-bit float to 64-bit int */
-uint64_t HELPER(cgeb)(CPUS390XState *env, uint64_t v2, uint32_t m3)
+uint64_t HELPER(cgeb)(CPUS390XState *env, uint64_t v2, uint32_t m34)
{
- int hold = swap_round_mode(env, m3);
+ int old_mode = s390_swap_bfp_rounding_mode(env, round_from_m34(m34));
int64_t ret = float32_to_int64(v2, &env->fpu_status);
- set_float_rounding_mode(hold, &env->fpu_status);
- handle_exceptions(env, GETPC());
+
+ s390_restore_bfp_rounding_mode(env, old_mode);
+ handle_exceptions(env, xxc_from_m34(m34), GETPC());
return ret;
}
/* convert 64-bit float to 64-bit int */
-uint64_t HELPER(cgdb)(CPUS390XState *env, uint64_t v2, uint32_t m3)
+uint64_t HELPER(cgdb)(CPUS390XState *env, uint64_t v2, uint32_t m34)
{
- int hold = swap_round_mode(env, m3);
+ int old_mode = s390_swap_bfp_rounding_mode(env, round_from_m34(m34));
int64_t ret = float64_to_int64(v2, &env->fpu_status);
- set_float_rounding_mode(hold, &env->fpu_status);
- handle_exceptions(env, GETPC());
+
+ s390_restore_bfp_rounding_mode(env, old_mode);
+ handle_exceptions(env, xxc_from_m34(m34), GETPC());
return ret;
}
/* convert 128-bit float to 64-bit int */
-uint64_t HELPER(cgxb)(CPUS390XState *env, uint64_t h, uint64_t l, uint32_t m3)
+uint64_t HELPER(cgxb)(CPUS390XState *env, uint64_t h, uint64_t l, uint32_t m34)
{
- int hold = swap_round_mode(env, m3);
+ int old_mode = s390_swap_bfp_rounding_mode(env, round_from_m34(m34));
float128 v2 = make_float128(h, l);
int64_t ret = float128_to_int64(v2, &env->fpu_status);
- set_float_rounding_mode(hold, &env->fpu_status);
- handle_exceptions(env, GETPC());
+
+ s390_restore_bfp_rounding_mode(env, old_mode);
+ handle_exceptions(env, xxc_from_m34(m34), GETPC());
return ret;
}
/* convert 32-bit float to 32-bit int */
-uint64_t HELPER(cfeb)(CPUS390XState *env, uint64_t v2, uint32_t m3)
+uint64_t HELPER(cfeb)(CPUS390XState *env, uint64_t v2, uint32_t m34)
{
- int hold = swap_round_mode(env, m3);
+ int old_mode = s390_swap_bfp_rounding_mode(env, round_from_m34(m34));
int32_t ret = float32_to_int32(v2, &env->fpu_status);
- set_float_rounding_mode(hold, &env->fpu_status);
- handle_exceptions(env, GETPC());
+
+ s390_restore_bfp_rounding_mode(env, old_mode);
+ handle_exceptions(env, xxc_from_m34(m34), GETPC());
return ret;
}
/* convert 64-bit float to 32-bit int */
-uint64_t HELPER(cfdb)(CPUS390XState *env, uint64_t v2, uint32_t m3)
+uint64_t HELPER(cfdb)(CPUS390XState *env, uint64_t v2, uint32_t m34)
{
- int hold = swap_round_mode(env, m3);
+ int old_mode = s390_swap_bfp_rounding_mode(env, round_from_m34(m34));
int32_t ret = float64_to_int32(v2, &env->fpu_status);
- set_float_rounding_mode(hold, &env->fpu_status);
- handle_exceptions(env, GETPC());
+
+ s390_restore_bfp_rounding_mode(env, old_mode);
+ handle_exceptions(env, xxc_from_m34(m34), GETPC());
return ret;
}
/* convert 128-bit float to 32-bit int */
-uint64_t HELPER(cfxb)(CPUS390XState *env, uint64_t h, uint64_t l, uint32_t m3)
+uint64_t HELPER(cfxb)(CPUS390XState *env, uint64_t h, uint64_t l, uint32_t m34)
{
- int hold = swap_round_mode(env, m3);
+ int old_mode = s390_swap_bfp_rounding_mode(env, round_from_m34(m34));
float128 v2 = make_float128(h, l);
int32_t ret = float128_to_int32(v2, &env->fpu_status);
- set_float_rounding_mode(hold, &env->fpu_status);
- handle_exceptions(env, GETPC());
+
+ s390_restore_bfp_rounding_mode(env, old_mode);
+ handle_exceptions(env, xxc_from_m34(m34), GETPC());
return ret;
}
/* convert 32-bit float to 64-bit uint */
-uint64_t HELPER(clgeb)(CPUS390XState *env, uint64_t v2, uint32_t m3)
+uint64_t HELPER(clgeb)(CPUS390XState *env, uint64_t v2, uint32_t m34)
{
- int hold = swap_round_mode(env, m3);
+ int old_mode = s390_swap_bfp_rounding_mode(env, round_from_m34(m34));
uint64_t ret;
+
v2 = float32_to_float64(v2, &env->fpu_status);
ret = float64_to_uint64(v2, &env->fpu_status);
- set_float_rounding_mode(hold, &env->fpu_status);
- handle_exceptions(env, GETPC());
+ s390_restore_bfp_rounding_mode(env, old_mode);
+ handle_exceptions(env, xxc_from_m34(m34), GETPC());
return ret;
}
/* convert 64-bit float to 64-bit uint */
-uint64_t HELPER(clgdb)(CPUS390XState *env, uint64_t v2, uint32_t m3)
+uint64_t HELPER(clgdb)(CPUS390XState *env, uint64_t v2, uint32_t m34)
{
- int hold = swap_round_mode(env, m3);
+ int old_mode = s390_swap_bfp_rounding_mode(env, round_from_m34(m34));
uint64_t ret = float64_to_uint64(v2, &env->fpu_status);
- set_float_rounding_mode(hold, &env->fpu_status);
- handle_exceptions(env, GETPC());
+
+ s390_restore_bfp_rounding_mode(env, old_mode);
+ handle_exceptions(env, xxc_from_m34(m34), GETPC());
return ret;
}
/* convert 128-bit float to 64-bit uint */
-uint64_t HELPER(clgxb)(CPUS390XState *env, uint64_t h, uint64_t l, uint32_t m3)
+uint64_t HELPER(clgxb)(CPUS390XState *env, uint64_t h, uint64_t l, uint32_t m34)
{
- int hold = swap_round_mode(env, m3);
- float128 v2 = make_float128(h, l);
- /* ??? Not 100% correct. */
- uint64_t ret = float128_to_int64(v2, &env->fpu_status);
- set_float_rounding_mode(hold, &env->fpu_status);
- handle_exceptions(env, GETPC());
+ int old_mode = s390_swap_bfp_rounding_mode(env, round_from_m34(m34));
+ uint64_t ret = float128_to_uint64(make_float128(h, l), &env->fpu_status);
+
+ s390_restore_bfp_rounding_mode(env, old_mode);
+ handle_exceptions(env, xxc_from_m34(m34), GETPC());
return ret;
}
/* convert 32-bit float to 32-bit uint */
-uint64_t HELPER(clfeb)(CPUS390XState *env, uint64_t v2, uint32_t m3)
+uint64_t HELPER(clfeb)(CPUS390XState *env, uint64_t v2, uint32_t m34)
{
- int hold = swap_round_mode(env, m3);
+ int old_mode = s390_swap_bfp_rounding_mode(env, round_from_m34(m34));
uint32_t ret = float32_to_uint32(v2, &env->fpu_status);
- set_float_rounding_mode(hold, &env->fpu_status);
- handle_exceptions(env, GETPC());
+
+ s390_restore_bfp_rounding_mode(env, old_mode);
+ handle_exceptions(env, xxc_from_m34(m34), GETPC());
return ret;
}
/* convert 64-bit float to 32-bit uint */
-uint64_t HELPER(clfdb)(CPUS390XState *env, uint64_t v2, uint32_t m3)
+uint64_t HELPER(clfdb)(CPUS390XState *env, uint64_t v2, uint32_t m34)
{
- int hold = swap_round_mode(env, m3);
+ int old_mode = s390_swap_bfp_rounding_mode(env, round_from_m34(m34));
uint32_t ret = float64_to_uint32(v2, &env->fpu_status);
- set_float_rounding_mode(hold, &env->fpu_status);
- handle_exceptions(env, GETPC());
+
+ s390_restore_bfp_rounding_mode(env, old_mode);
+ handle_exceptions(env, xxc_from_m34(m34), GETPC());
return ret;
}
/* convert 128-bit float to 32-bit uint */
-uint64_t HELPER(clfxb)(CPUS390XState *env, uint64_t h, uint64_t l, uint32_t m3)
+uint64_t HELPER(clfxb)(CPUS390XState *env, uint64_t h, uint64_t l, uint32_t m34)
{
- int hold = swap_round_mode(env, m3);
- float128 v2 = make_float128(h, l);
- /* Not 100% correct. */
- uint32_t ret = float128_to_int64(v2, &env->fpu_status);
- set_float_rounding_mode(hold, &env->fpu_status);
- handle_exceptions(env, GETPC());
+ int old_mode = s390_swap_bfp_rounding_mode(env, round_from_m34(m34));
+ uint32_t ret = float128_to_uint32(make_float128(h, l), &env->fpu_status);
+
+ s390_restore_bfp_rounding_mode(env, old_mode);
+ handle_exceptions(env, xxc_from_m34(m34), GETPC());
return ret;
}
/* round to integer 32-bit */
-uint64_t HELPER(fieb)(CPUS390XState *env, uint64_t f2, uint32_t m3)
+uint64_t HELPER(fieb)(CPUS390XState *env, uint64_t f2, uint32_t m34)
{
- int hold = swap_round_mode(env, m3);
+ int old_mode = s390_swap_bfp_rounding_mode(env, round_from_m34(m34));
float32 ret = float32_round_to_int(f2, &env->fpu_status);
- set_float_rounding_mode(hold, &env->fpu_status);
- handle_exceptions(env, GETPC());
+
+ s390_restore_bfp_rounding_mode(env, old_mode);
+ handle_exceptions(env, xxc_from_m34(m34), GETPC());
return ret;
}
/* round to integer 64-bit */
-uint64_t HELPER(fidb)(CPUS390XState *env, uint64_t f2, uint32_t m3)
+uint64_t HELPER(fidb)(CPUS390XState *env, uint64_t f2, uint32_t m34)
{
- int hold = swap_round_mode(env, m3);
+ int old_mode = s390_swap_bfp_rounding_mode(env, round_from_m34(m34));
float64 ret = float64_round_to_int(f2, &env->fpu_status);
- set_float_rounding_mode(hold, &env->fpu_status);
- handle_exceptions(env, GETPC());
+
+ s390_restore_bfp_rounding_mode(env, old_mode);
+ handle_exceptions(env, xxc_from_m34(m34), GETPC());
return ret;
}
/* round to integer 128-bit */
-uint64_t HELPER(fixb)(CPUS390XState *env, uint64_t ah, uint64_t al, uint32_t m3)
+uint64_t HELPER(fixb)(CPUS390XState *env, uint64_t ah, uint64_t al,
+ uint32_t m34)
{
- int hold = swap_round_mode(env, m3);
+ int old_mode = s390_swap_bfp_rounding_mode(env, round_from_m34(m34));
float128 ret = float128_round_to_int(make_float128(ah, al),
&env->fpu_status);
- set_float_rounding_mode(hold, &env->fpu_status);
- handle_exceptions(env, GETPC());
+
+ s390_restore_bfp_rounding_mode(env, old_mode);
+ handle_exceptions(env, xxc_from_m34(m34), GETPC());
return RET128(ret);
}
@@ -584,7 +678,7 @@
uint32_t HELPER(keb)(CPUS390XState *env, uint64_t f1, uint64_t f2)
{
int cmp = float32_compare(f1, f2, &env->fpu_status);
- handle_exceptions(env, GETPC());
+ handle_exceptions(env, false, GETPC());
return float_comp_to_cc(env, cmp);
}
@@ -592,7 +686,7 @@
uint32_t HELPER(kdb)(CPUS390XState *env, uint64_t f1, uint64_t f2)
{
int cmp = float64_compare(f1, f2, &env->fpu_status);
- handle_exceptions(env, GETPC());
+ handle_exceptions(env, false, GETPC());
return float_comp_to_cc(env, cmp);
}
@@ -603,7 +697,7 @@
int cmp = float128_compare(make_float128(ah, al),
make_float128(bh, bl),
&env->fpu_status);
- handle_exceptions(env, GETPC());
+ handle_exceptions(env, false, GETPC());
return float_comp_to_cc(env, cmp);
}
@@ -612,7 +706,7 @@
uint64_t f2, uint64_t f3)
{
float32 ret = float32_muladd(f2, f3, f1, 0, &env->fpu_status);
- handle_exceptions(env, GETPC());
+ handle_exceptions(env, false, GETPC());
return ret;
}
@@ -621,7 +715,7 @@
uint64_t f2, uint64_t f3)
{
float64 ret = float64_muladd(f2, f3, f1, 0, &env->fpu_status);
- handle_exceptions(env, GETPC());
+ handle_exceptions(env, false, GETPC());
return ret;
}
@@ -631,7 +725,7 @@
{
float32 ret = float32_muladd(f2, f3, f1, float_muladd_negate_c,
&env->fpu_status);
- handle_exceptions(env, GETPC());
+ handle_exceptions(env, false, GETPC());
return ret;
}
@@ -641,78 +735,63 @@
{
float64 ret = float64_muladd(f2, f3, f1, float_muladd_negate_c,
&env->fpu_status);
- handle_exceptions(env, GETPC());
+ handle_exceptions(env, false, GETPC());
return ret;
}
+/* The rightmost bit has the number 11. */
+static inline uint16_t dcmask(int bit, bool neg)
+{
+ return 1 << (11 - bit - neg);
+}
+
+#define DEF_FLOAT_DCMASK(_TYPE) \
+static uint16_t _TYPE##_dcmask(CPUS390XState *env, _TYPE f1) \
+{ \
+ const bool neg = _TYPE##_is_neg(f1); \
+ \
+ /* Sorted by most common cases - only one class is possible */ \
+ if (_TYPE##_is_normal(f1)) { \
+ return dcmask(2, neg); \
+ } else if (_TYPE##_is_zero(f1)) { \
+ return dcmask(0, neg); \
+ } else if (_TYPE##_is_denormal(f1)) { \
+ return dcmask(4, neg); \
+ } else if (_TYPE##_is_infinity(f1)) { \
+ return dcmask(6, neg); \
+ } else if (_TYPE##_is_quiet_nan(f1, &env->fpu_status)) { \
+ return dcmask(8, neg); \
+ } \
+ /* signaling nan, as last remaining case */ \
+ return dcmask(10, neg); \
+}
+DEF_FLOAT_DCMASK(float32)
+DEF_FLOAT_DCMASK(float64)
+DEF_FLOAT_DCMASK(float128)
+
/* test data class 32-bit */
uint32_t HELPER(tceb)(CPUS390XState *env, uint64_t f1, uint64_t m2)
{
- float32 v1 = f1;
- int neg = float32_is_neg(v1);
- uint32_t cc = 0;
-
- if ((float32_is_zero(v1) && (m2 & (1 << (11-neg)))) ||
- (float32_is_infinity(v1) && (m2 & (1 << (5-neg)))) ||
- (float32_is_any_nan(v1) && (m2 & (1 << (3-neg)))) ||
- (float32_is_signaling_nan(v1, &env->fpu_status) &&
- (m2 & (1 << (1-neg))))) {
- cc = 1;
- } else if (m2 & (1 << (9-neg))) {
- /* assume normalized number */
- cc = 1;
- }
- /* FIXME: denormalized? */
- return cc;
+ return (m2 & float32_dcmask(env, f1)) != 0;
}
/* test data class 64-bit */
uint32_t HELPER(tcdb)(CPUS390XState *env, uint64_t v1, uint64_t m2)
{
- int neg = float64_is_neg(v1);
- uint32_t cc = 0;
-
- if ((float64_is_zero(v1) && (m2 & (1 << (11-neg)))) ||
- (float64_is_infinity(v1) && (m2 & (1 << (5-neg)))) ||
- (float64_is_any_nan(v1) && (m2 & (1 << (3-neg)))) ||
- (float64_is_signaling_nan(v1, &env->fpu_status) &&
- (m2 & (1 << (1-neg))))) {
- cc = 1;
- } else if (m2 & (1 << (9-neg))) {
- /* assume normalized number */
- cc = 1;
- }
- /* FIXME: denormalized? */
- return cc;
+ return (m2 & float64_dcmask(env, v1)) != 0;
}
/* test data class 128-bit */
-uint32_t HELPER(tcxb)(CPUS390XState *env, uint64_t ah,
- uint64_t al, uint64_t m2)
+uint32_t HELPER(tcxb)(CPUS390XState *env, uint64_t ah, uint64_t al, uint64_t m2)
{
- float128 v1 = make_float128(ah, al);
- int neg = float128_is_neg(v1);
- uint32_t cc = 0;
-
- if ((float128_is_zero(v1) && (m2 & (1 << (11-neg)))) ||
- (float128_is_infinity(v1) && (m2 & (1 << (5-neg)))) ||
- (float128_is_any_nan(v1) && (m2 & (1 << (3-neg)))) ||
- (float128_is_signaling_nan(v1, &env->fpu_status) &&
- (m2 & (1 << (1-neg))))) {
- cc = 1;
- } else if (m2 & (1 << (9-neg))) {
- /* assume normalized number */
- cc = 1;
- }
- /* FIXME: denormalized? */
- return cc;
+ return (m2 & float128_dcmask(env, make_float128(ah, al))) != 0;
}
/* square root 32-bit */
uint64_t HELPER(sqeb)(CPUS390XState *env, uint64_t f2)
{
float32 ret = float32_sqrt(f2, &env->fpu_status);
- handle_exceptions(env, GETPC());
+ handle_exceptions(env, false, GETPC());
return ret;
}
@@ -720,7 +799,7 @@
uint64_t HELPER(sqdb)(CPUS390XState *env, uint64_t f2)
{
float64 ret = float64_sqrt(f2, &env->fpu_status);
- handle_exceptions(env, GETPC());
+ handle_exceptions(env, false, GETPC());
return ret;
}
@@ -728,44 +807,84 @@
uint64_t HELPER(sqxb)(CPUS390XState *env, uint64_t ah, uint64_t al)
{
float128 ret = float128_sqrt(make_float128(ah, al), &env->fpu_status);
- handle_exceptions(env, GETPC());
+ handle_exceptions(env, false, GETPC());
return RET128(ret);
}
-static const int fpc_to_rnd[4] = {
+static const int fpc_to_rnd[8] = {
float_round_nearest_even,
float_round_to_zero,
float_round_up,
- float_round_down
+ float_round_down,
+ -1,
+ -1,
+ -1,
+ float_round_to_odd,
};
/* set fpc */
void HELPER(sfpc)(CPUS390XState *env, uint64_t fpc)
{
+ if (fpc_to_rnd[fpc & 0x7] == -1 || fpc & 0x03030088u ||
+ (!s390_has_feat(S390_FEAT_FLOATING_POINT_EXT) && fpc & 0x4)) {
+ s390_program_interrupt(env, PGM_SPECIFICATION, ILEN_AUTO, GETPC());
+ }
+
/* Install everything in the main FPC. */
env->fpc = fpc;
/* Install the rounding mode in the shadow fpu_status. */
- set_float_rounding_mode(fpc_to_rnd[fpc & 3], &env->fpu_status);
+ set_float_rounding_mode(fpc_to_rnd[fpc & 0x7], &env->fpu_status);
}
/* set fpc and signal */
-void HELPER(sfas)(CPUS390XState *env, uint64_t val)
+void HELPER(sfas)(CPUS390XState *env, uint64_t fpc)
{
uint32_t signalling = env->fpc;
- uint32_t source = val;
uint32_t s390_exc;
- /* The contents of the source operand are placed in the FPC register;
- then the flags in the FPC register are set to the logical OR of the
- signalling flags and the source flags. */
- env->fpc = source | (signalling & 0x00ff0000);
- set_float_rounding_mode(fpc_to_rnd[source & 3], &env->fpu_status);
+ if (fpc_to_rnd[fpc & 0x7] == -1 || fpc & 0x03030088u ||
+ (!s390_has_feat(S390_FEAT_FLOATING_POINT_EXT) && fpc & 0x4)) {
+ s390_program_interrupt(env, PGM_SPECIFICATION, ILEN_AUTO, GETPC());
+ }
- /* If any signalling flag is 1 and the corresponding source mask
- is also 1, a simulated-iee-exception trap occurs. */
- s390_exc = (signalling >> 16) & (source >> 24);
+ /*
+ * FPC is set to the FPC operand with a bitwise OR of the signalling
+ * flags.
+ */
+ env->fpc = fpc | (signalling & 0x00ff0000);
+ set_float_rounding_mode(fpc_to_rnd[fpc & 0x7], &env->fpu_status);
+
+ /*
+ * If any signaling flag is enabled in the new FPC mask, a
+ * simulated-iee-exception exception occurs.
+ */
+ s390_exc = (signalling >> 16) & (fpc >> 24);
if (s390_exc) {
+ if (s390_exc & S390_IEEE_MASK_INVALID) {
+ s390_exc = S390_IEEE_MASK_INVALID;
+ } else if (s390_exc & S390_IEEE_MASK_DIVBYZERO) {
+ s390_exc = S390_IEEE_MASK_DIVBYZERO;
+ } else if (s390_exc & S390_IEEE_MASK_OVERFLOW) {
+ s390_exc &= (S390_IEEE_MASK_OVERFLOW | S390_IEEE_MASK_INEXACT);
+ } else if (s390_exc & S390_IEEE_MASK_UNDERFLOW) {
+ s390_exc &= (S390_IEEE_MASK_UNDERFLOW | S390_IEEE_MASK_INEXACT);
+ } else if (s390_exc & S390_IEEE_MASK_INEXACT) {
+ s390_exc = S390_IEEE_MASK_INEXACT;
+ } else if (s390_exc & S390_IEEE_MASK_QUANTUM) {
+ s390_exc = S390_IEEE_MASK_QUANTUM;
+ }
tcg_s390_data_exception(env, s390_exc | 3, GETPC());
}
}
+
+/* set bfp rounding mode */
+void HELPER(srnm)(CPUS390XState *env, uint64_t rnd)
+{
+ if (rnd > 0x7 || fpc_to_rnd[rnd & 0x7] == -1) {
+ s390_program_interrupt(env, PGM_SPECIFICATION, ILEN_AUTO, GETPC());
+ }
+
+ env->fpc = deposit32(env->fpc, 0, 3, rnd);
+ set_float_rounding_mode(fpc_to_rnd[rnd & 0x7], &env->fpu_status);
+}
diff --git a/target/s390x/gen-features.c b/target/s390x/gen-features.c
index 44eca45..e4739a6 100644
--- a/target/s390x/gen-features.c
+++ b/target/s390x/gen-features.c
@@ -601,6 +601,11 @@
};
static uint16_t qemu_LATEST[] = {
+ /*
+ * Only BFP bits are implemented (HFP, DFP, PFPO and DIVIDE TO INTEGER not
+ * implemented yet).
+ */
+ S390_FEAT_FLOATING_POINT_EXT,
S390_FEAT_ZPCI,
};
diff --git a/target/s390x/helper.c b/target/s390x/helper.c
index 3d74836..8e95732 100644
--- a/target/s390x/helper.c
+++ b/target/s390x/helper.c
@@ -211,7 +211,7 @@
}
}
-struct sigp_save_area {
+typedef struct SigpSaveArea {
uint64_t fprs[16]; /* 0x0000 */
uint64_t grs[16]; /* 0x0080 */
PSW psw; /* 0x0100 */
@@ -225,13 +225,13 @@
uint8_t pad_0x0138[0x0140 - 0x0138]; /* 0x0138 */
uint32_t ars[16]; /* 0x0140 */
uint64_t crs[16]; /* 0x0384 */
-};
-QEMU_BUILD_BUG_ON(sizeof(struct sigp_save_area) != 512);
+} SigpSaveArea;
+QEMU_BUILD_BUG_ON(sizeof(SigpSaveArea) != 512);
int s390_store_status(S390CPU *cpu, hwaddr addr, bool store_arch)
{
static const uint8_t ar_id = 1;
- struct sigp_save_area *sa;
+ SigpSaveArea *sa;
hwaddr len = sizeof(*sa);
int i;
@@ -272,32 +272,43 @@
return 0;
}
-#define ADTL_GS_OFFSET 1024 /* offset of GS data in adtl save area */
+typedef struct SigpAdtlSaveArea {
+ uint64_t vregs[32][2]; /* 0x0000 */
+ uint8_t pad_0x0200[0x0400 - 0x0200]; /* 0x0200 */
+ uint64_t gscb[4]; /* 0x0400 */
+ uint8_t pad_0x0420[0x1000 - 0x0420]; /* 0x0420 */
+} SigpAdtlSaveArea;
+QEMU_BUILD_BUG_ON(sizeof(SigpAdtlSaveArea) != 4096);
+
#define ADTL_GS_MIN_SIZE 2048 /* minimal size of adtl save area for GS */
int s390_store_adtl_status(S390CPU *cpu, hwaddr addr, hwaddr len)
{
+ SigpAdtlSaveArea *sa;
hwaddr save = len;
- void *mem;
+ int i;
- mem = cpu_physical_memory_map(addr, &save, 1);
- if (!mem) {
+ sa = cpu_physical_memory_map(addr, &save, 1);
+ if (!sa) {
return -EFAULT;
}
if (save != len) {
- cpu_physical_memory_unmap(mem, len, 1, 0);
+ cpu_physical_memory_unmap(sa, len, 1, 0);
return -EFAULT;
}
- /* FIXME: as soon as TCG supports these features, convert cpu->be */
if (s390_has_feat(S390_FEAT_VECTOR)) {
- memcpy(mem, &cpu->env.vregs, 512);
+ 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);
+ }
}
if (s390_has_feat(S390_FEAT_GUARDED_STORAGE) && len >= ADTL_GS_MIN_SIZE) {
- memcpy(mem + ADTL_GS_OFFSET, &cpu->env.gscb, 32);
+ for (i = 0; i < 4; i++) {
+ sa->gscb[i] = cpu_to_be64(cpu->env.gscb[i]);
+ }
}
- cpu_physical_memory_unmap(mem, len, 1, len);
-
+ cpu_physical_memory_unmap(sa, len, 1, len);
return 0;
}
#endif /* CONFIG_USER_ONLY */
@@ -406,6 +417,7 @@
[CC_OP_SLA_32] = "CC_OP_SLA_32",
[CC_OP_SLA_64] = "CC_OP_SLA_64",
[CC_OP_FLOGR] = "CC_OP_FLOGR",
+ [CC_OP_LCBB] = "CC_OP_LCBB",
};
return cc_names[cc_op];
diff --git a/target/s390x/helper.h b/target/s390x/helper.h
index 6260b50..bb65925 100644
--- a/target/s390x/helper.h
+++ b/target/s390x/helper.h
@@ -53,11 +53,11 @@
DEF_HELPER_FLAGS_5(mxb, TCG_CALL_NO_WG, i64, env, i64, i64, i64, i64)
DEF_HELPER_FLAGS_4(mxdb, TCG_CALL_NO_WG, i64, env, i64, i64, i64)
DEF_HELPER_FLAGS_2(ldeb, TCG_CALL_NO_WG, i64, env, i64)
-DEF_HELPER_FLAGS_3(ldxb, TCG_CALL_NO_WG, i64, env, i64, i64)
+DEF_HELPER_FLAGS_4(ldxb, TCG_CALL_NO_WG, i64, env, i64, i64, i32)
DEF_HELPER_FLAGS_2(lxdb, TCG_CALL_NO_WG, i64, env, i64)
DEF_HELPER_FLAGS_2(lxeb, TCG_CALL_NO_WG, i64, env, i64)
-DEF_HELPER_FLAGS_2(ledb, TCG_CALL_NO_WG, i64, env, i64)
-DEF_HELPER_FLAGS_3(lexb, TCG_CALL_NO_WG, i64, env, i64, i64)
+DEF_HELPER_FLAGS_3(ledb, TCG_CALL_NO_WG, i64, env, i64, i32)
+DEF_HELPER_FLAGS_4(lexb, TCG_CALL_NO_WG, i64, env, i64, i64, i32)
DEF_HELPER_FLAGS_3(ceb, TCG_CALL_NO_WG_SE, i32, env, i64, i64)
DEF_HELPER_FLAGS_3(cdb, TCG_CALL_NO_WG_SE, i32, env, i64, i64)
DEF_HELPER_FLAGS_5(cxb, TCG_CALL_NO_WG_SE, i32, env, i64, i64, i64, i64)
@@ -104,8 +104,9 @@
DEF_HELPER_5(trXX, i32, env, i32, i32, i32, i32)
DEF_HELPER_4(cksm, i64, env, i64, i64, i64)
DEF_HELPER_FLAGS_5(calc_cc, TCG_CALL_NO_RWG_SE, i32, env, i32, i64, i64, i64)
-DEF_HELPER_FLAGS_2(sfpc, TCG_CALL_NO_RWG, void, env, i64)
+DEF_HELPER_FLAGS_2(sfpc, TCG_CALL_NO_WG, void, env, i64)
DEF_HELPER_FLAGS_2(sfas, TCG_CALL_NO_WG, void, env, i64)
+DEF_HELPER_FLAGS_2(srnm, TCG_CALL_NO_WG, void, env, i64)
DEF_HELPER_FLAGS_1(popcnt, TCG_CALL_NO_RWG_SE, i64, i64)
DEF_HELPER_2(stfle, i32, env, i64)
DEF_HELPER_FLAGS_2(lpq, TCG_CALL_NO_WG, i64, env, i64)
diff --git a/target/s390x/insn-data.def b/target/s390x/insn-data.def
index 6158237..61b750a 100644
--- a/target/s390x/insn-data.def
+++ b/target/s390x/insn-data.def
@@ -479,6 +479,8 @@
F(0xb313, LCDBR, RRE, Z, 0, f2, new, f1, negf64, f64, IF_BFP)
F(0xb343, LCXBR, RRE, Z, x2h, x2l, new_P, x1, negf128, f128, IF_BFP)
F(0xb373, LCDFR, RRE, FPSSH, 0, f2, new, f1, negf64, 0, IF_AFP1 | IF_AFP2)
+/* LOAD COUNT TO BLOCK BOUNDARY */
+ C(0xe727, LCBB, RXE, V, la2, 0, r1, 0, lcbb, 0)
/* LOAD HALFWORD */
C(0xb927, LHR, RRE, EI, 0, r2_16s, 0, r1_32, mov2, 0)
C(0xb907, LGHR, RRE, EI, 0, r2_16s, 0, r1, mov2, 0)
@@ -598,10 +600,12 @@
F(0xed04, LDEB, RXE, Z, 0, m2_32u, new, f1, ldeb, 0, IF_BFP)
F(0xed05, LXDB, RXE, Z, 0, m2_64, new_P, x1, lxdb, 0, IF_BFP)
F(0xed06, LXEB, RXE, Z, 0, m2_32u, new_P, x1, lxeb, 0, IF_BFP)
+ F(0xb324, LDER, RXE, Z, 0, e2, new, f1, lde, 0, IF_AFP1)
+ F(0xed24, LDE, RXE, Z, 0, m2_32u, new, f1, lde, 0, IF_AFP1)
/* LOAD ROUNDED */
- F(0xb344, LEDBR, RRE, Z, 0, f2, new, e1, ledb, 0, IF_BFP)
- F(0xb345, LDXBR, RRE, Z, x2h, x2l, new, f1, ldxb, 0, IF_BFP)
- F(0xb346, LEXBR, RRE, Z, x2h, x2l, new, e1, lexb, 0, IF_BFP)
+ F(0xb344, LEDBR, RRF_e, Z, 0, f2, new, e1, ledb, 0, IF_BFP)
+ F(0xb345, LDXBR, RRF_e, Z, x2h, x2l, new, f1, ldxb, 0, IF_BFP)
+ F(0xb346, LEXBR, RRF_e, Z, x2h, x2l, new, e1, lexb, 0, IF_BFP)
/* LOAD MULTIPLE */
C(0x9800, LM, RS_a, Z, 0, a2, 0, 0, lm32, 0)
@@ -759,10 +763,10 @@
/* SET FPC AND SIGNAL */
F(0xb385, SFASR, RRE, IEEEE_SIM, 0, r1_o, 0, 0, sfas, 0, IF_DFP)
/* SET BFP ROUNDING MODE */
- F(0xb299, SRNM, S, Z, 0, 0, 0, 0, srnm, 0, IF_BFP)
- F(0xb2b8, SRNMB, S, FPE, 0, 0, 0, 0, srnm, 0, IF_BFP)
+ F(0xb299, SRNM, S, Z, la2, 0, 0, 0, srnm, 0, IF_BFP)
+ F(0xb2b8, SRNMB, S, FPE, la2, 0, 0, 0, srnmb, 0, IF_BFP)
/* SET DFP ROUNDING MODE */
- F(0xb2b9, SRNMT, S, DFPR, 0, 0, 0, 0, srnm, 0, IF_DFP)
+ F(0xb2b9, SRNMT, S, DFPR, la2, 0, 0, 0, srnmt, 0, IF_DFP)
/* SET PROGRAM MASK */
C(0x0400, SPM, RR_a, Z, r1, 0, 0, 0, spm, 0)
diff --git a/target/s390x/insn-format.def b/target/s390x/insn-format.def
index a412d90..4297ff4 100644
--- a/target/s390x/insn-format.def
+++ b/target/s390x/insn-format.def
@@ -36,7 +36,7 @@
F3(RSY_b, R(1, 8), BDL(2), M(3,12))
F2(RX_a, R(1, 8), BXD(2))
F2(RX_b, M(1, 8), BXD(2))
-F2(RXE, R(1, 8), BXD(2))
+F3(RXE, R(1, 8), BXD(2), M(3,32))
F3(RXF, R(1,32), BXD(2), R(3, 8))
F2(RXY_a, R(1, 8), BXDL(2))
F2(RXY_b, M(1, 8), BXDL(2))
diff --git a/target/s390x/internal.h b/target/s390x/internal.h
index f2a771e..7baf0e2 100644
--- a/target/s390x/internal.h
+++ b/target/s390x/internal.h
@@ -101,7 +101,9 @@
/* whether the kernel died with panic() or not */
uint32_t panic_magic; /* 0xe00 */
- uint8_t pad13[0x11b8 - 0xe04]; /* 0xe04 */
+ uint8_t pad13[0x11b0 - 0xe04]; /* 0xe04 */
+
+ uint64_t mcesad; /* 0x11B0 */
/* 64 bit extparam used for pfault, diag 250 etc */
uint64_t ext_params2; /* 0x11B8 */
@@ -234,6 +236,7 @@
CC_OP_SLA_32, /* Calculate shift left signed (32bit) */
CC_OP_SLA_64, /* Calculate shift left signed (64bit) */
CC_OP_FLOGR, /* find leftmost one */
+ CC_OP_LCBB, /* load count to block boundary */
CC_OP_MAX
};
@@ -308,6 +311,15 @@
uint32_t set_cc_nz_f32(float32 v);
uint32_t set_cc_nz_f64(float64 v);
uint32_t set_cc_nz_f128(float128 v);
+#define S390_IEEE_MASK_INVALID 0x80
+#define S390_IEEE_MASK_DIVBYZERO 0x40
+#define S390_IEEE_MASK_OVERFLOW 0x20
+#define S390_IEEE_MASK_UNDERFLOW 0x10
+#define S390_IEEE_MASK_INEXACT 0x08
+#define S390_IEEE_MASK_QUANTUM 0x04
+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);
/* gdbstub.c */
diff --git a/target/s390x/translate.c b/target/s390x/translate.c
index 19072ef..41fb466 100644
--- a/target/s390x/translate.c
+++ b/target/s390x/translate.c
@@ -145,12 +145,18 @@
}
}
-static inline int vec_reg_offset(uint8_t reg, uint8_t enr, TCGMemOp size)
+static inline int vec_full_reg_offset(uint8_t reg)
{
- const uint8_t es = 1 << size;
- int offs = enr * es;
-
g_assert(reg < 32);
+ return offsetof(CPUS390XState, vregs[reg][0].d);
+}
+
+static inline int vec_reg_offset(uint8_t reg, uint8_t enr, TCGMemOp es)
+{
+ /* Convert element size (es) - e.g. MO_8 - to bytes */
+ const uint8_t bytes = 1 << es;
+ int offs = enr * bytes;
+
/*
* vregs[n][0] is the lowest 8 byte and vregs[n][1] the highest 8 byte
* of the 16 byte vector, on both, little and big endian systems.
@@ -173,11 +179,11 @@
* the two 8 byte elements have to be loaded separately. Let's force all
* 16 byte operations to handle it in a special way.
*/
- g_assert(size <= MO_64);
+ g_assert(es <= MO_64);
#ifndef HOST_WORDS_BIGENDIAN
- offs ^= (8 - es);
+ offs ^= (8 - bytes);
#endif
- return offs + offsetof(CPUS390XState, vregs[reg][0].d);
+ return offs + vec_full_reg_offset(reg);
}
static inline int freg64_offset(uint8_t reg)
@@ -376,32 +382,43 @@
gen_data_exception(0xff);
}
+static void gen_addi_and_wrap_i64(DisasContext *s, TCGv_i64 dst, TCGv_i64 src,
+ int64_t imm)
+{
+ tcg_gen_addi_i64(dst, src, imm);
+ if (!(s->base.tb->flags & FLAG_MASK_64)) {
+ if (s->base.tb->flags & FLAG_MASK_32) {
+ tcg_gen_andi_i64(dst, dst, 0x7fffffff);
+ } else {
+ tcg_gen_andi_i64(dst, dst, 0x00ffffff);
+ }
+ }
+}
+
static TCGv_i64 get_address(DisasContext *s, int x2, int b2, int d2)
{
TCGv_i64 tmp = tcg_temp_new_i64();
- bool need_31 = !(s->base.tb->flags & FLAG_MASK_64);
- /* Note that d2 is limited to 20 bits, signed. If we crop negative
- displacements early we create larger immedate addends. */
-
- /* Note that addi optimizes the imm==0 case. */
+ /*
+ * Note that d2 is limited to 20 bits, signed. If we crop negative
+ * displacements early we create larger immedate addends.
+ */
if (b2 && x2) {
tcg_gen_add_i64(tmp, regs[b2], regs[x2]);
- tcg_gen_addi_i64(tmp, tmp, d2);
+ gen_addi_and_wrap_i64(s, tmp, tmp, d2);
} else if (b2) {
- tcg_gen_addi_i64(tmp, regs[b2], d2);
+ gen_addi_and_wrap_i64(s, tmp, regs[b2], d2);
} else if (x2) {
- tcg_gen_addi_i64(tmp, regs[x2], d2);
- } else {
- if (need_31) {
- d2 &= 0x7fffffff;
- need_31 = false;
+ gen_addi_and_wrap_i64(s, tmp, regs[x2], d2);
+ } else if (!(s->base.tb->flags & FLAG_MASK_64)) {
+ if (s->base.tb->flags & FLAG_MASK_32) {
+ tcg_gen_movi_i64(tmp, d2 & 0x7fffffff);
+ } else {
+ tcg_gen_movi_i64(tmp, d2 & 0x00ffffff);
}
+ } else {
tcg_gen_movi_i64(tmp, d2);
}
- if (need_31) {
- tcg_gen_andi_i64(tmp, tmp, 0x7fffffff);
- }
return tmp;
}
@@ -540,6 +557,7 @@
case CC_OP_NZ_F32:
case CC_OP_NZ_F64:
case CC_OP_FLOGR:
+ case CC_OP_LCBB:
/* 1 argument */
gen_helper_calc_cc(cc_op, cpu_env, local_cc_op, dummy, cc_dst, dummy);
break;
@@ -1758,160 +1776,257 @@
return DISAS_NEXT;
}
+static TCGv_i32 fpinst_extract_m34(DisasContext *s, bool m3_with_fpe,
+ bool m4_with_fpe)
+{
+ const bool fpe = s390_has_feat(S390_FEAT_FLOATING_POINT_EXT);
+ uint8_t m3 = get_field(s->fields, m3);
+ uint8_t m4 = get_field(s->fields, m4);
+
+ /* m3 field was introduced with FPE */
+ if (!fpe && m3_with_fpe) {
+ m3 = 0;
+ }
+ /* m4 field was introduced with FPE */
+ if (!fpe && m4_with_fpe) {
+ m4 = 0;
+ }
+
+ /* Check for valid rounding modes. Mode 3 was introduced later. */
+ if (m3 == 2 || m3 > 7 || (!fpe && m3 == 3)) {
+ gen_program_exception(s, PGM_SPECIFICATION);
+ return NULL;
+ }
+
+ return tcg_const_i32(deposit32(m3, 4, 4, m4));
+}
+
static DisasJumpType op_cfeb(DisasContext *s, DisasOps *o)
{
- TCGv_i32 m3 = tcg_const_i32(get_field(s->fields, m3));
- gen_helper_cfeb(o->out, cpu_env, o->in2, m3);
- tcg_temp_free_i32(m3);
+ TCGv_i32 m34 = fpinst_extract_m34(s, false, true);
+
+ if (!m34) {
+ return DISAS_NORETURN;
+ }
+ gen_helper_cfeb(o->out, cpu_env, o->in2, m34);
+ tcg_temp_free_i32(m34);
gen_set_cc_nz_f32(s, o->in2);
return DISAS_NEXT;
}
static DisasJumpType op_cfdb(DisasContext *s, DisasOps *o)
{
- TCGv_i32 m3 = tcg_const_i32(get_field(s->fields, m3));
- gen_helper_cfdb(o->out, cpu_env, o->in2, m3);
- tcg_temp_free_i32(m3);
+ TCGv_i32 m34 = fpinst_extract_m34(s, false, true);
+
+ if (!m34) {
+ return DISAS_NORETURN;
+ }
+ gen_helper_cfdb(o->out, cpu_env, o->in2, m34);
+ tcg_temp_free_i32(m34);
gen_set_cc_nz_f64(s, o->in2);
return DISAS_NEXT;
}
static DisasJumpType op_cfxb(DisasContext *s, DisasOps *o)
{
- TCGv_i32 m3 = tcg_const_i32(get_field(s->fields, m3));
- gen_helper_cfxb(o->out, cpu_env, o->in1, o->in2, m3);
- tcg_temp_free_i32(m3);
+ TCGv_i32 m34 = fpinst_extract_m34(s, false, true);
+
+ if (!m34) {
+ return DISAS_NORETURN;
+ }
+ gen_helper_cfxb(o->out, cpu_env, o->in1, o->in2, m34);
+ tcg_temp_free_i32(m34);
gen_set_cc_nz_f128(s, o->in1, o->in2);
return DISAS_NEXT;
}
static DisasJumpType op_cgeb(DisasContext *s, DisasOps *o)
{
- TCGv_i32 m3 = tcg_const_i32(get_field(s->fields, m3));
- gen_helper_cgeb(o->out, cpu_env, o->in2, m3);
- tcg_temp_free_i32(m3);
+ TCGv_i32 m34 = fpinst_extract_m34(s, false, true);
+
+ if (!m34) {
+ return DISAS_NORETURN;
+ }
+ gen_helper_cgeb(o->out, cpu_env, o->in2, m34);
+ tcg_temp_free_i32(m34);
gen_set_cc_nz_f32(s, o->in2);
return DISAS_NEXT;
}
static DisasJumpType op_cgdb(DisasContext *s, DisasOps *o)
{
- TCGv_i32 m3 = tcg_const_i32(get_field(s->fields, m3));
- gen_helper_cgdb(o->out, cpu_env, o->in2, m3);
- tcg_temp_free_i32(m3);
+ TCGv_i32 m34 = fpinst_extract_m34(s, false, true);
+
+ if (!m34) {
+ return DISAS_NORETURN;
+ }
+ gen_helper_cgdb(o->out, cpu_env, o->in2, m34);
+ tcg_temp_free_i32(m34);
gen_set_cc_nz_f64(s, o->in2);
return DISAS_NEXT;
}
static DisasJumpType op_cgxb(DisasContext *s, DisasOps *o)
{
- TCGv_i32 m3 = tcg_const_i32(get_field(s->fields, m3));
- gen_helper_cgxb(o->out, cpu_env, o->in1, o->in2, m3);
- tcg_temp_free_i32(m3);
+ TCGv_i32 m34 = fpinst_extract_m34(s, false, true);
+
+ if (!m34) {
+ return DISAS_NORETURN;
+ }
+ gen_helper_cgxb(o->out, cpu_env, o->in1, o->in2, m34);
+ tcg_temp_free_i32(m34);
gen_set_cc_nz_f128(s, o->in1, o->in2);
return DISAS_NEXT;
}
static DisasJumpType op_clfeb(DisasContext *s, DisasOps *o)
{
- TCGv_i32 m3 = tcg_const_i32(get_field(s->fields, m3));
- gen_helper_clfeb(o->out, cpu_env, o->in2, m3);
- tcg_temp_free_i32(m3);
+ TCGv_i32 m34 = fpinst_extract_m34(s, false, false);
+
+ if (!m34) {
+ return DISAS_NORETURN;
+ }
+ gen_helper_clfeb(o->out, cpu_env, o->in2, m34);
+ tcg_temp_free_i32(m34);
gen_set_cc_nz_f32(s, o->in2);
return DISAS_NEXT;
}
static DisasJumpType op_clfdb(DisasContext *s, DisasOps *o)
{
- TCGv_i32 m3 = tcg_const_i32(get_field(s->fields, m3));
- gen_helper_clfdb(o->out, cpu_env, o->in2, m3);
- tcg_temp_free_i32(m3);
+ TCGv_i32 m34 = fpinst_extract_m34(s, false, false);
+
+ if (!m34) {
+ return DISAS_NORETURN;
+ }
+ gen_helper_clfdb(o->out, cpu_env, o->in2, m34);
+ tcg_temp_free_i32(m34);
gen_set_cc_nz_f64(s, o->in2);
return DISAS_NEXT;
}
static DisasJumpType op_clfxb(DisasContext *s, DisasOps *o)
{
- TCGv_i32 m3 = tcg_const_i32(get_field(s->fields, m3));
- gen_helper_clfxb(o->out, cpu_env, o->in1, o->in2, m3);
- tcg_temp_free_i32(m3);
+ TCGv_i32 m34 = fpinst_extract_m34(s, false, false);
+
+ if (!m34) {
+ return DISAS_NORETURN;
+ }
+ gen_helper_clfxb(o->out, cpu_env, o->in1, o->in2, m34);
+ tcg_temp_free_i32(m34);
gen_set_cc_nz_f128(s, o->in1, o->in2);
return DISAS_NEXT;
}
static DisasJumpType op_clgeb(DisasContext *s, DisasOps *o)
{
- TCGv_i32 m3 = tcg_const_i32(get_field(s->fields, m3));
- gen_helper_clgeb(o->out, cpu_env, o->in2, m3);
- tcg_temp_free_i32(m3);
+ TCGv_i32 m34 = fpinst_extract_m34(s, false, false);
+
+ if (!m34) {
+ return DISAS_NORETURN;
+ }
+ gen_helper_clgeb(o->out, cpu_env, o->in2, m34);
+ tcg_temp_free_i32(m34);
gen_set_cc_nz_f32(s, o->in2);
return DISAS_NEXT;
}
static DisasJumpType op_clgdb(DisasContext *s, DisasOps *o)
{
- TCGv_i32 m3 = tcg_const_i32(get_field(s->fields, m3));
- gen_helper_clgdb(o->out, cpu_env, o->in2, m3);
- tcg_temp_free_i32(m3);
+ TCGv_i32 m34 = fpinst_extract_m34(s, false, false);
+
+ if (!m34) {
+ return DISAS_NORETURN;
+ }
+ gen_helper_clgdb(o->out, cpu_env, o->in2, m34);
+ tcg_temp_free_i32(m34);
gen_set_cc_nz_f64(s, o->in2);
return DISAS_NEXT;
}
static DisasJumpType op_clgxb(DisasContext *s, DisasOps *o)
{
- TCGv_i32 m3 = tcg_const_i32(get_field(s->fields, m3));
- gen_helper_clgxb(o->out, cpu_env, o->in1, o->in2, m3);
- tcg_temp_free_i32(m3);
+ TCGv_i32 m34 = fpinst_extract_m34(s, false, false);
+
+ if (!m34) {
+ return DISAS_NORETURN;
+ }
+ gen_helper_clgxb(o->out, cpu_env, o->in1, o->in2, m34);
+ tcg_temp_free_i32(m34);
gen_set_cc_nz_f128(s, o->in1, o->in2);
return DISAS_NEXT;
}
static DisasJumpType op_cegb(DisasContext *s, DisasOps *o)
{
- TCGv_i32 m3 = tcg_const_i32(get_field(s->fields, m3));
- gen_helper_cegb(o->out, cpu_env, o->in2, m3);
- tcg_temp_free_i32(m3);
+ TCGv_i32 m34 = fpinst_extract_m34(s, true, true);
+
+ if (!m34) {
+ return DISAS_NORETURN;
+ }
+ gen_helper_cegb(o->out, cpu_env, o->in2, m34);
+ tcg_temp_free_i32(m34);
return DISAS_NEXT;
}
static DisasJumpType op_cdgb(DisasContext *s, DisasOps *o)
{
- TCGv_i32 m3 = tcg_const_i32(get_field(s->fields, m3));
- gen_helper_cdgb(o->out, cpu_env, o->in2, m3);
- tcg_temp_free_i32(m3);
+ TCGv_i32 m34 = fpinst_extract_m34(s, true, true);
+
+ if (!m34) {
+ return DISAS_NORETURN;
+ }
+ gen_helper_cdgb(o->out, cpu_env, o->in2, m34);
+ tcg_temp_free_i32(m34);
return DISAS_NEXT;
}
static DisasJumpType op_cxgb(DisasContext *s, DisasOps *o)
{
- TCGv_i32 m3 = tcg_const_i32(get_field(s->fields, m3));
- gen_helper_cxgb(o->out, cpu_env, o->in2, m3);
- tcg_temp_free_i32(m3);
+ TCGv_i32 m34 = fpinst_extract_m34(s, true, true);
+
+ if (!m34) {
+ return DISAS_NORETURN;
+ }
+ gen_helper_cxgb(o->out, cpu_env, o->in2, m34);
+ tcg_temp_free_i32(m34);
return_low128(o->out2);
return DISAS_NEXT;
}
static DisasJumpType op_celgb(DisasContext *s, DisasOps *o)
{
- TCGv_i32 m3 = tcg_const_i32(get_field(s->fields, m3));
- gen_helper_celgb(o->out, cpu_env, o->in2, m3);
- tcg_temp_free_i32(m3);
+ TCGv_i32 m34 = fpinst_extract_m34(s, false, false);
+
+ if (!m34) {
+ return DISAS_NORETURN;
+ }
+ gen_helper_celgb(o->out, cpu_env, o->in2, m34);
+ tcg_temp_free_i32(m34);
return DISAS_NEXT;
}
static DisasJumpType op_cdlgb(DisasContext *s, DisasOps *o)
{
- TCGv_i32 m3 = tcg_const_i32(get_field(s->fields, m3));
- gen_helper_cdlgb(o->out, cpu_env, o->in2, m3);
- tcg_temp_free_i32(m3);
+ TCGv_i32 m34 = fpinst_extract_m34(s, false, false);
+
+ if (!m34) {
+ return DISAS_NORETURN;
+ }
+ gen_helper_cdlgb(o->out, cpu_env, o->in2, m34);
+ tcg_temp_free_i32(m34);
return DISAS_NEXT;
}
static DisasJumpType op_cxlgb(DisasContext *s, DisasOps *o)
{
- TCGv_i32 m3 = tcg_const_i32(get_field(s->fields, m3));
- gen_helper_cxlgb(o->out, cpu_env, o->in2, m3);
- tcg_temp_free_i32(m3);
+ TCGv_i32 m34 = fpinst_extract_m34(s, false, false);
+
+ if (!m34) {
+ return DISAS_NORETURN;
+ }
+ gen_helper_cxlgb(o->out, cpu_env, o->in2, m34);
+ tcg_temp_free_i32(m34);
return_low128(o->out2);
return DISAS_NEXT;
}
@@ -2390,26 +2505,38 @@
static DisasJumpType op_fieb(DisasContext *s, DisasOps *o)
{
- TCGv_i32 m3 = tcg_const_i32(get_field(s->fields, m3));
- gen_helper_fieb(o->out, cpu_env, o->in2, m3);
- tcg_temp_free_i32(m3);
+ TCGv_i32 m34 = fpinst_extract_m34(s, false, true);
+
+ if (!m34) {
+ return DISAS_NORETURN;
+ }
+ gen_helper_fieb(o->out, cpu_env, o->in2, m34);
+ tcg_temp_free_i32(m34);
return DISAS_NEXT;
}
static DisasJumpType op_fidb(DisasContext *s, DisasOps *o)
{
- TCGv_i32 m3 = tcg_const_i32(get_field(s->fields, m3));
- gen_helper_fidb(o->out, cpu_env, o->in2, m3);
- tcg_temp_free_i32(m3);
+ TCGv_i32 m34 = fpinst_extract_m34(s, false, true);
+
+ if (!m34) {
+ return DISAS_NORETURN;
+ }
+ gen_helper_fidb(o->out, cpu_env, o->in2, m34);
+ tcg_temp_free_i32(m34);
return DISAS_NEXT;
}
static DisasJumpType op_fixb(DisasContext *s, DisasOps *o)
{
- TCGv_i32 m3 = tcg_const_i32(get_field(s->fields, m3));
- gen_helper_fixb(o->out, cpu_env, o->in1, o->in2, m3);
+ TCGv_i32 m34 = fpinst_extract_m34(s, false, true);
+
+ if (!m34) {
+ return DISAS_NORETURN;
+ }
+ gen_helper_fixb(o->out, cpu_env, o->in1, o->in2, m34);
return_low128(o->out2);
- tcg_temp_free_i32(m3);
+ tcg_temp_free_i32(m34);
return DISAS_NEXT;
}
@@ -2678,19 +2805,37 @@
static DisasJumpType op_ledb(DisasContext *s, DisasOps *o)
{
- gen_helper_ledb(o->out, cpu_env, o->in2);
+ TCGv_i32 m34 = fpinst_extract_m34(s, true, true);
+
+ if (!m34) {
+ return DISAS_NORETURN;
+ }
+ gen_helper_ledb(o->out, cpu_env, o->in2, m34);
+ tcg_temp_free_i32(m34);
return DISAS_NEXT;
}
static DisasJumpType op_ldxb(DisasContext *s, DisasOps *o)
{
- gen_helper_ldxb(o->out, cpu_env, o->in1, o->in2);
+ TCGv_i32 m34 = fpinst_extract_m34(s, true, true);
+
+ if (!m34) {
+ return DISAS_NORETURN;
+ }
+ gen_helper_ldxb(o->out, cpu_env, o->in1, o->in2, m34);
+ tcg_temp_free_i32(m34);
return DISAS_NEXT;
}
static DisasJumpType op_lexb(DisasContext *s, DisasOps *o)
{
- gen_helper_lexb(o->out, cpu_env, o->in1, o->in2);
+ TCGv_i32 m34 = fpinst_extract_m34(s, true, true);
+
+ if (!m34) {
+ return DISAS_NORETURN;
+ }
+ gen_helper_lexb(o->out, cpu_env, o->in1, o->in2, m34);
+ tcg_temp_free_i32(m34);
return DISAS_NEXT;
}
@@ -2708,6 +2853,12 @@
return DISAS_NEXT;
}
+static DisasJumpType op_lde(DisasContext *s, DisasOps *o)
+{
+ tcg_gen_shli_i64(o->out, o->in2, 32);
+ return DISAS_NEXT;
+}
+
static DisasJumpType op_llgt(DisasContext *s, DisasOps *o)
{
tcg_gen_andi_i64(o->out, o->in2, 0x7fffffff);
@@ -3119,6 +3270,23 @@
return DISAS_NEXT;
}
+static DisasJumpType op_lcbb(DisasContext *s, DisasOps *o)
+{
+ const int64_t block_size = (1ull << (get_field(s->fields, m3) + 6));
+
+ if (get_field(s->fields, m3) > 6) {
+ gen_program_exception(s, PGM_SPECIFICATION);
+ return DISAS_NORETURN;
+ }
+
+ tcg_gen_ori_i64(o->addr1, o->addr1, -block_size);
+ tcg_gen_neg_i64(o->addr1, o->addr1);
+ tcg_gen_movi_i64(o->out, 16);
+ tcg_gen_umin_i64(o->out, o->out, o->addr1);
+ gen_op_update1_cc_i64(s, CC_OP_LCBB, o->out);
+ return DISAS_NEXT;
+}
+
static DisasJumpType op_mov2(DisasContext *s, DisasOps *o)
{
o->out = o->in2;
@@ -3955,41 +4123,33 @@
static DisasJumpType op_srnm(DisasContext *s, DisasOps *o)
{
- int b2 = get_field(s->fields, b2);
- int d2 = get_field(s->fields, d2);
- TCGv_i64 t1 = tcg_temp_new_i64();
- TCGv_i64 t2 = tcg_temp_new_i64();
- int mask, pos, len;
+ /* Bits other than 62 and 63 are ignored. Bit 29 is set to zero. */
+ tcg_gen_andi_i64(o->addr1, o->addr1, 0x3ull);
+ gen_helper_srnm(cpu_env, o->addr1);
+ return DISAS_NEXT;
+}
- switch (s->fields->op2) {
- case 0x99: /* SRNM */
- pos = 0, len = 2;
- break;
- case 0xb8: /* SRNMB */
- pos = 0, len = 3;
- break;
- case 0xb9: /* SRNMT */
- pos = 4, len = 3;
- break;
- default:
- tcg_abort();
- }
- mask = (1 << len) - 1;
+static DisasJumpType op_srnmb(DisasContext *s, DisasOps *o)
+{
+ /* Bits 0-55 are are ignored. */
+ tcg_gen_andi_i64(o->addr1, o->addr1, 0xffull);
+ gen_helper_srnm(cpu_env, o->addr1);
+ return DISAS_NEXT;
+}
- /* Insert the value into the appropriate field of the FPC. */
- if (b2 == 0) {
- tcg_gen_movi_i64(t1, d2 & mask);
- } else {
- tcg_gen_addi_i64(t1, regs[b2], d2);
- tcg_gen_andi_i64(t1, t1, mask);
- }
- tcg_gen_ld32u_i64(t2, cpu_env, offsetof(CPUS390XState, fpc));
- tcg_gen_deposit_i64(t2, t2, t1, pos, len);
- tcg_temp_free_i64(t1);
+static DisasJumpType op_srnmt(DisasContext *s, DisasOps *o)
+{
+ TCGv_i64 tmp = tcg_temp_new_i64();
- /* Then install the new FPC to set the rounding mode in fpu_status. */
- gen_helper_sfpc(cpu_env, t2);
- tcg_temp_free_i64(t2);
+ /* Bits other than 61-63 are ignored. */
+ tcg_gen_andi_i64(o->addr1, o->addr1, 0x7ull);
+
+ /* No need to call a helper, we don't implement dfp */
+ tcg_gen_ld32u_i64(tmp, cpu_env, offsetof(CPUS390XState, fpc));
+ tcg_gen_deposit_i64(tmp, tmp, o->addr1, 4, 3);
+ tcg_gen_st32_i64(tmp, cpu_env, offsetof(CPUS390XState, fpc));
+
+ tcg_temp_free_i64(tmp);
return DISAS_NEXT;
}
@@ -5908,6 +6068,7 @@
#define FAC_ECT S390_FEAT_EXTRACT_CPU_TIME
#define FAC_PCI S390_FEAT_ZPCI /* z/PCI facility */
#define FAC_AIS S390_FEAT_ADAPTER_INT_SUPPRESSION
+#define FAC_V S390_FEAT_VECTOR /* vector facility */
static const DisasInsn insn_info[] = {
#include "insn-data.def"
@@ -6091,7 +6252,7 @@
const DisasInsn *insn;
DisasJumpType ret = DISAS_NEXT;
DisasFields f;
- DisasOps o;
+ DisasOps o = {};
/* Search for the insn in the table. */
insn = extract_insn(env, s, &f);
@@ -6161,12 +6322,6 @@
/* Set up the strutures we use to communicate with the helpers. */
s->insn = insn;
s->fields = &f;
- o.g_out = o.g_out2 = o.g_in1 = o.g_in2 = false;
- o.out = NULL;
- o.out2 = NULL;
- o.in1 = NULL;
- o.in2 = NULL;
- o.addr1 = NULL;
/* Implement the instruction. */
if (insn->help_in1) {
diff --git a/target/xtensa/core-test_mmuhifi_c3/xtensa-modules.inc.c b/target/xtensa/core-test_mmuhifi_c3/xtensa-modules.inc.c
index ef70f80..687631b 100644
--- a/target/xtensa/core-test_mmuhifi_c3/xtensa-modules.inc.c
+++ b/target/xtensa/core-test_mmuhifi_c3/xtensa-modules.inc.c
@@ -24159,2627 +24159,2627 @@
slotbuf[0] = 0xe7d014;
}
-xtensa_opcode_encode_fn Opcode_excw_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_excw_encode_fns[] = {
Opcode_excw_Slot_inst_encode, 0, 0, 0, 0
};
-xtensa_opcode_encode_fn Opcode_rfe_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_rfe_encode_fns[] = {
Opcode_rfe_Slot_inst_encode, 0, 0, 0, 0
};
-xtensa_opcode_encode_fn Opcode_rfde_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_rfde_encode_fns[] = {
Opcode_rfde_Slot_inst_encode, 0, 0, 0, 0
};
-xtensa_opcode_encode_fn Opcode_syscall_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_syscall_encode_fns[] = {
Opcode_syscall_Slot_inst_encode, 0, 0, 0, 0
};
-xtensa_opcode_encode_fn Opcode_simcall_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_simcall_encode_fns[] = {
Opcode_simcall_Slot_inst_encode, 0, 0, 0, 0
};
-xtensa_opcode_encode_fn Opcode_call12_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_call12_encode_fns[] = {
Opcode_call12_Slot_inst_encode, 0, 0, 0, 0
};
-xtensa_opcode_encode_fn Opcode_call8_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_call8_encode_fns[] = {
Opcode_call8_Slot_inst_encode, 0, 0, 0, 0
};
-xtensa_opcode_encode_fn Opcode_call4_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_call4_encode_fns[] = {
Opcode_call4_Slot_inst_encode, 0, 0, 0, 0
};
-xtensa_opcode_encode_fn Opcode_callx12_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_callx12_encode_fns[] = {
Opcode_callx12_Slot_inst_encode, 0, 0, 0, 0
};
-xtensa_opcode_encode_fn Opcode_callx8_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_callx8_encode_fns[] = {
Opcode_callx8_Slot_inst_encode, 0, 0, 0, 0
};
-xtensa_opcode_encode_fn Opcode_callx4_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_callx4_encode_fns[] = {
Opcode_callx4_Slot_inst_encode, 0, 0, 0, 0
};
-xtensa_opcode_encode_fn Opcode_entry_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_entry_encode_fns[] = {
Opcode_entry_Slot_inst_encode, 0, 0, 0, 0
};
-xtensa_opcode_encode_fn Opcode_movsp_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_movsp_encode_fns[] = {
Opcode_movsp_Slot_inst_encode, 0, 0, 0, 0
};
-xtensa_opcode_encode_fn Opcode_rotw_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_rotw_encode_fns[] = {
Opcode_rotw_Slot_inst_encode, 0, 0, 0, 0
};
-xtensa_opcode_encode_fn Opcode_retw_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_retw_encode_fns[] = {
Opcode_retw_Slot_inst_encode, 0, 0, 0, 0
};
-xtensa_opcode_encode_fn Opcode_retw_n_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_retw_n_encode_fns[] = {
0, 0, Opcode_retw_n_Slot_inst16b_encode, 0, 0
};
-xtensa_opcode_encode_fn Opcode_rfwo_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_rfwo_encode_fns[] = {
Opcode_rfwo_Slot_inst_encode, 0, 0, 0, 0
};
-xtensa_opcode_encode_fn Opcode_rfwu_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_rfwu_encode_fns[] = {
Opcode_rfwu_Slot_inst_encode, 0, 0, 0, 0
};
-xtensa_opcode_encode_fn Opcode_l32e_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_l32e_encode_fns[] = {
Opcode_l32e_Slot_inst_encode, 0, 0, 0, 0
};
-xtensa_opcode_encode_fn Opcode_s32e_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_s32e_encode_fns[] = {
Opcode_s32e_Slot_inst_encode, 0, 0, 0, 0
};
-xtensa_opcode_encode_fn Opcode_rsr_windowbase_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_rsr_windowbase_encode_fns[] = {
Opcode_rsr_windowbase_Slot_inst_encode, 0, 0, 0, 0
};
-xtensa_opcode_encode_fn Opcode_wsr_windowbase_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_wsr_windowbase_encode_fns[] = {
Opcode_wsr_windowbase_Slot_inst_encode, 0, 0, 0, 0
};
-xtensa_opcode_encode_fn Opcode_xsr_windowbase_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_xsr_windowbase_encode_fns[] = {
Opcode_xsr_windowbase_Slot_inst_encode, 0, 0, 0, 0
};
-xtensa_opcode_encode_fn Opcode_rsr_windowstart_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_rsr_windowstart_encode_fns[] = {
Opcode_rsr_windowstart_Slot_inst_encode, 0, 0, 0, 0
};
-xtensa_opcode_encode_fn Opcode_wsr_windowstart_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_wsr_windowstart_encode_fns[] = {
Opcode_wsr_windowstart_Slot_inst_encode, 0, 0, 0, 0
};
-xtensa_opcode_encode_fn Opcode_xsr_windowstart_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_xsr_windowstart_encode_fns[] = {
Opcode_xsr_windowstart_Slot_inst_encode, 0, 0, 0, 0
};
-xtensa_opcode_encode_fn Opcode_add_n_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_add_n_encode_fns[] = {
0, Opcode_add_n_Slot_inst16a_encode, 0, 0, 0
};
-xtensa_opcode_encode_fn Opcode_addi_n_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_addi_n_encode_fns[] = {
0, Opcode_addi_n_Slot_inst16a_encode, 0, 0, 0
};
-xtensa_opcode_encode_fn Opcode_beqz_n_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_beqz_n_encode_fns[] = {
0, 0, Opcode_beqz_n_Slot_inst16b_encode, 0, 0
};
-xtensa_opcode_encode_fn Opcode_bnez_n_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_bnez_n_encode_fns[] = {
0, 0, Opcode_bnez_n_Slot_inst16b_encode, 0, 0
};
-xtensa_opcode_encode_fn Opcode_ill_n_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ill_n_encode_fns[] = {
0, 0, Opcode_ill_n_Slot_inst16b_encode, 0, 0
};
-xtensa_opcode_encode_fn Opcode_l32i_n_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_l32i_n_encode_fns[] = {
0, Opcode_l32i_n_Slot_inst16a_encode, 0, 0, 0
};
-xtensa_opcode_encode_fn Opcode_mov_n_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_mov_n_encode_fns[] = {
0, 0, Opcode_mov_n_Slot_inst16b_encode, 0, 0
};
-xtensa_opcode_encode_fn Opcode_movi_n_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_movi_n_encode_fns[] = {
0, 0, Opcode_movi_n_Slot_inst16b_encode, 0, 0
};
-xtensa_opcode_encode_fn Opcode_nop_n_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_nop_n_encode_fns[] = {
0, 0, Opcode_nop_n_Slot_inst16b_encode, 0, 0
};
-xtensa_opcode_encode_fn Opcode_ret_n_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ret_n_encode_fns[] = {
0, 0, Opcode_ret_n_Slot_inst16b_encode, 0, 0
};
-xtensa_opcode_encode_fn Opcode_s32i_n_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_s32i_n_encode_fns[] = {
0, Opcode_s32i_n_Slot_inst16a_encode, 0, 0, 0
};
-xtensa_opcode_encode_fn Opcode_rur_threadptr_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_rur_threadptr_encode_fns[] = {
Opcode_rur_threadptr_Slot_inst_encode, 0, 0, 0, 0
};
-xtensa_opcode_encode_fn Opcode_wur_threadptr_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_wur_threadptr_encode_fns[] = {
Opcode_wur_threadptr_Slot_inst_encode, 0, 0, 0, 0
};
-xtensa_opcode_encode_fn Opcode_addi_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_addi_encode_fns[] = {
Opcode_addi_Slot_inst_encode, 0, 0, 0, Opcode_addi_Slot_ae_slot0_encode
};
-xtensa_opcode_encode_fn Opcode_addmi_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_addmi_encode_fns[] = {
Opcode_addmi_Slot_inst_encode, 0, 0, 0, Opcode_addmi_Slot_ae_slot0_encode
};
-xtensa_opcode_encode_fn Opcode_add_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_add_encode_fns[] = {
Opcode_add_Slot_inst_encode, 0, 0, 0, Opcode_add_Slot_ae_slot0_encode
};
-xtensa_opcode_encode_fn Opcode_sub_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_sub_encode_fns[] = {
Opcode_sub_Slot_inst_encode, 0, 0, 0, Opcode_sub_Slot_ae_slot0_encode
};
-xtensa_opcode_encode_fn Opcode_addx2_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_addx2_encode_fns[] = {
Opcode_addx2_Slot_inst_encode, 0, 0, 0, Opcode_addx2_Slot_ae_slot0_encode
};
-xtensa_opcode_encode_fn Opcode_addx4_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_addx4_encode_fns[] = {
Opcode_addx4_Slot_inst_encode, 0, 0, 0, Opcode_addx4_Slot_ae_slot0_encode
};
-xtensa_opcode_encode_fn Opcode_addx8_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_addx8_encode_fns[] = {
Opcode_addx8_Slot_inst_encode, 0, 0, 0, Opcode_addx8_Slot_ae_slot0_encode
};
-xtensa_opcode_encode_fn Opcode_subx2_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_subx2_encode_fns[] = {
Opcode_subx2_Slot_inst_encode, 0, 0, 0, Opcode_subx2_Slot_ae_slot0_encode
};
-xtensa_opcode_encode_fn Opcode_subx4_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_subx4_encode_fns[] = {
Opcode_subx4_Slot_inst_encode, 0, 0, 0, Opcode_subx4_Slot_ae_slot0_encode
};
-xtensa_opcode_encode_fn Opcode_subx8_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_subx8_encode_fns[] = {
Opcode_subx8_Slot_inst_encode, 0, 0, 0, Opcode_subx8_Slot_ae_slot0_encode
};
-xtensa_opcode_encode_fn Opcode_and_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_and_encode_fns[] = {
Opcode_and_Slot_inst_encode, 0, 0, 0, Opcode_and_Slot_ae_slot0_encode
};
-xtensa_opcode_encode_fn Opcode_or_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_or_encode_fns[] = {
Opcode_or_Slot_inst_encode, 0, 0, 0, Opcode_or_Slot_ae_slot0_encode
};
-xtensa_opcode_encode_fn Opcode_xor_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_xor_encode_fns[] = {
Opcode_xor_Slot_inst_encode, 0, 0, 0, Opcode_xor_Slot_ae_slot0_encode
};
-xtensa_opcode_encode_fn Opcode_beqi_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_beqi_encode_fns[] = {
Opcode_beqi_Slot_inst_encode, 0, 0, 0, Opcode_beqi_Slot_ae_slot0_encode
};
-xtensa_opcode_encode_fn Opcode_bnei_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_bnei_encode_fns[] = {
Opcode_bnei_Slot_inst_encode, 0, 0, 0, Opcode_bnei_Slot_ae_slot0_encode
};
-xtensa_opcode_encode_fn Opcode_bgei_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_bgei_encode_fns[] = {
Opcode_bgei_Slot_inst_encode, 0, 0, 0, Opcode_bgei_Slot_ae_slot0_encode
};
-xtensa_opcode_encode_fn Opcode_blti_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_blti_encode_fns[] = {
Opcode_blti_Slot_inst_encode, 0, 0, 0, Opcode_blti_Slot_ae_slot0_encode
};
-xtensa_opcode_encode_fn Opcode_bbci_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_bbci_encode_fns[] = {
Opcode_bbci_Slot_inst_encode, 0, 0, 0, Opcode_bbci_Slot_ae_slot0_encode
};
-xtensa_opcode_encode_fn Opcode_bbsi_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_bbsi_encode_fns[] = {
Opcode_bbsi_Slot_inst_encode, 0, 0, 0, Opcode_bbsi_Slot_ae_slot0_encode
};
-xtensa_opcode_encode_fn Opcode_bgeui_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_bgeui_encode_fns[] = {
Opcode_bgeui_Slot_inst_encode, 0, 0, 0, Opcode_bgeui_Slot_ae_slot0_encode
};
-xtensa_opcode_encode_fn Opcode_bltui_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_bltui_encode_fns[] = {
Opcode_bltui_Slot_inst_encode, 0, 0, 0, Opcode_bltui_Slot_ae_slot0_encode
};
-xtensa_opcode_encode_fn Opcode_beq_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_beq_encode_fns[] = {
Opcode_beq_Slot_inst_encode, 0, 0, 0, Opcode_beq_Slot_ae_slot0_encode
};
-xtensa_opcode_encode_fn Opcode_bne_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_bne_encode_fns[] = {
Opcode_bne_Slot_inst_encode, 0, 0, 0, Opcode_bne_Slot_ae_slot0_encode
};
-xtensa_opcode_encode_fn Opcode_bge_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_bge_encode_fns[] = {
Opcode_bge_Slot_inst_encode, 0, 0, 0, Opcode_bge_Slot_ae_slot0_encode
};
-xtensa_opcode_encode_fn Opcode_blt_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_blt_encode_fns[] = {
Opcode_blt_Slot_inst_encode, 0, 0, 0, Opcode_blt_Slot_ae_slot0_encode
};
-xtensa_opcode_encode_fn Opcode_bgeu_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_bgeu_encode_fns[] = {
Opcode_bgeu_Slot_inst_encode, 0, 0, 0, Opcode_bgeu_Slot_ae_slot0_encode
};
-xtensa_opcode_encode_fn Opcode_bltu_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_bltu_encode_fns[] = {
Opcode_bltu_Slot_inst_encode, 0, 0, 0, Opcode_bltu_Slot_ae_slot0_encode
};
-xtensa_opcode_encode_fn Opcode_bany_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_bany_encode_fns[] = {
Opcode_bany_Slot_inst_encode, 0, 0, 0, Opcode_bany_Slot_ae_slot0_encode
};
-xtensa_opcode_encode_fn Opcode_bnone_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_bnone_encode_fns[] = {
Opcode_bnone_Slot_inst_encode, 0, 0, 0, Opcode_bnone_Slot_ae_slot0_encode
};
-xtensa_opcode_encode_fn Opcode_ball_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ball_encode_fns[] = {
Opcode_ball_Slot_inst_encode, 0, 0, 0, Opcode_ball_Slot_ae_slot0_encode
};
-xtensa_opcode_encode_fn Opcode_bnall_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_bnall_encode_fns[] = {
Opcode_bnall_Slot_inst_encode, 0, 0, 0, Opcode_bnall_Slot_ae_slot0_encode
};
-xtensa_opcode_encode_fn Opcode_bbc_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_bbc_encode_fns[] = {
Opcode_bbc_Slot_inst_encode, 0, 0, 0, Opcode_bbc_Slot_ae_slot0_encode
};
-xtensa_opcode_encode_fn Opcode_bbs_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_bbs_encode_fns[] = {
Opcode_bbs_Slot_inst_encode, 0, 0, 0, Opcode_bbs_Slot_ae_slot0_encode
};
-xtensa_opcode_encode_fn Opcode_beqz_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_beqz_encode_fns[] = {
Opcode_beqz_Slot_inst_encode, 0, 0, 0, Opcode_beqz_Slot_ae_slot0_encode
};
-xtensa_opcode_encode_fn Opcode_bnez_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_bnez_encode_fns[] = {
Opcode_bnez_Slot_inst_encode, 0, 0, 0, Opcode_bnez_Slot_ae_slot0_encode
};
-xtensa_opcode_encode_fn Opcode_bgez_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_bgez_encode_fns[] = {
Opcode_bgez_Slot_inst_encode, 0, 0, 0, Opcode_bgez_Slot_ae_slot0_encode
};
-xtensa_opcode_encode_fn Opcode_bltz_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_bltz_encode_fns[] = {
Opcode_bltz_Slot_inst_encode, 0, 0, 0, Opcode_bltz_Slot_ae_slot0_encode
};
-xtensa_opcode_encode_fn Opcode_call0_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_call0_encode_fns[] = {
Opcode_call0_Slot_inst_encode, 0, 0, 0, 0
};
-xtensa_opcode_encode_fn Opcode_callx0_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_callx0_encode_fns[] = {
Opcode_callx0_Slot_inst_encode, 0, 0, 0, 0
};
-xtensa_opcode_encode_fn Opcode_extui_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_extui_encode_fns[] = {
Opcode_extui_Slot_inst_encode, 0, 0, 0, Opcode_extui_Slot_ae_slot0_encode
};
-xtensa_opcode_encode_fn Opcode_ill_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ill_encode_fns[] = {
Opcode_ill_Slot_inst_encode, 0, 0, 0, 0
};
-xtensa_opcode_encode_fn Opcode_j_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_j_encode_fns[] = {
Opcode_j_Slot_inst_encode, 0, 0, 0, Opcode_j_Slot_ae_slot0_encode
};
-xtensa_opcode_encode_fn Opcode_jx_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_jx_encode_fns[] = {
Opcode_jx_Slot_inst_encode, 0, 0, 0, Opcode_jx_Slot_ae_slot0_encode
};
-xtensa_opcode_encode_fn Opcode_l16ui_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_l16ui_encode_fns[] = {
Opcode_l16ui_Slot_inst_encode, 0, 0, 0, Opcode_l16ui_Slot_ae_slot0_encode
};
-xtensa_opcode_encode_fn Opcode_l16si_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_l16si_encode_fns[] = {
Opcode_l16si_Slot_inst_encode, 0, 0, 0, Opcode_l16si_Slot_ae_slot0_encode
};
-xtensa_opcode_encode_fn Opcode_l32i_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_l32i_encode_fns[] = {
Opcode_l32i_Slot_inst_encode, 0, 0, 0, Opcode_l32i_Slot_ae_slot0_encode
};
-xtensa_opcode_encode_fn Opcode_l32r_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_l32r_encode_fns[] = {
Opcode_l32r_Slot_inst_encode, 0, 0, 0, Opcode_l32r_Slot_ae_slot0_encode
};
-xtensa_opcode_encode_fn Opcode_l8ui_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_l8ui_encode_fns[] = {
Opcode_l8ui_Slot_inst_encode, 0, 0, 0, Opcode_l8ui_Slot_ae_slot0_encode
};
-xtensa_opcode_encode_fn Opcode_loop_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_loop_encode_fns[] = {
Opcode_loop_Slot_inst_encode, 0, 0, 0, 0
};
-xtensa_opcode_encode_fn Opcode_loopnez_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_loopnez_encode_fns[] = {
Opcode_loopnez_Slot_inst_encode, 0, 0, 0, 0
};
-xtensa_opcode_encode_fn Opcode_loopgtz_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_loopgtz_encode_fns[] = {
Opcode_loopgtz_Slot_inst_encode, 0, 0, 0, 0
};
-xtensa_opcode_encode_fn Opcode_movi_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_movi_encode_fns[] = {
Opcode_movi_Slot_inst_encode, 0, 0, 0, Opcode_movi_Slot_ae_slot0_encode
};
-xtensa_opcode_encode_fn Opcode_moveqz_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_moveqz_encode_fns[] = {
Opcode_moveqz_Slot_inst_encode, 0, 0, 0, Opcode_moveqz_Slot_ae_slot0_encode
};
-xtensa_opcode_encode_fn Opcode_movnez_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_movnez_encode_fns[] = {
Opcode_movnez_Slot_inst_encode, 0, 0, 0, Opcode_movnez_Slot_ae_slot0_encode
};
-xtensa_opcode_encode_fn Opcode_movltz_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_movltz_encode_fns[] = {
Opcode_movltz_Slot_inst_encode, 0, 0, 0, Opcode_movltz_Slot_ae_slot0_encode
};
-xtensa_opcode_encode_fn Opcode_movgez_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_movgez_encode_fns[] = {
Opcode_movgez_Slot_inst_encode, 0, 0, 0, Opcode_movgez_Slot_ae_slot0_encode
};
-xtensa_opcode_encode_fn Opcode_neg_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_neg_encode_fns[] = {
Opcode_neg_Slot_inst_encode, 0, 0, 0, Opcode_neg_Slot_ae_slot0_encode
};
-xtensa_opcode_encode_fn Opcode_abs_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_abs_encode_fns[] = {
Opcode_abs_Slot_inst_encode, 0, 0, 0, Opcode_abs_Slot_ae_slot0_encode
};
-xtensa_opcode_encode_fn Opcode_nop_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_nop_encode_fns[] = {
Opcode_nop_Slot_inst_encode, 0, 0, Opcode_nop_Slot_ae_slot1_encode, Opcode_nop_Slot_ae_slot0_encode
};
-xtensa_opcode_encode_fn Opcode_ret_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ret_encode_fns[] = {
Opcode_ret_Slot_inst_encode, 0, 0, 0, 0
};
-xtensa_opcode_encode_fn Opcode_s16i_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_s16i_encode_fns[] = {
Opcode_s16i_Slot_inst_encode, 0, 0, 0, Opcode_s16i_Slot_ae_slot0_encode
};
-xtensa_opcode_encode_fn Opcode_s32i_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_s32i_encode_fns[] = {
Opcode_s32i_Slot_inst_encode, 0, 0, 0, Opcode_s32i_Slot_ae_slot0_encode
};
-xtensa_opcode_encode_fn Opcode_s8i_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_s8i_encode_fns[] = {
Opcode_s8i_Slot_inst_encode, 0, 0, 0, Opcode_s8i_Slot_ae_slot0_encode
};
-xtensa_opcode_encode_fn Opcode_ssr_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ssr_encode_fns[] = {
Opcode_ssr_Slot_inst_encode, 0, 0, 0, Opcode_ssr_Slot_ae_slot0_encode
};
-xtensa_opcode_encode_fn Opcode_ssl_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ssl_encode_fns[] = {
Opcode_ssl_Slot_inst_encode, 0, 0, 0, Opcode_ssl_Slot_ae_slot0_encode
};
-xtensa_opcode_encode_fn Opcode_ssa8l_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ssa8l_encode_fns[] = {
Opcode_ssa8l_Slot_inst_encode, 0, 0, 0, Opcode_ssa8l_Slot_ae_slot0_encode
};
-xtensa_opcode_encode_fn Opcode_ssa8b_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ssa8b_encode_fns[] = {
Opcode_ssa8b_Slot_inst_encode, 0, 0, 0, Opcode_ssa8b_Slot_ae_slot0_encode
};
-xtensa_opcode_encode_fn Opcode_ssai_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ssai_encode_fns[] = {
Opcode_ssai_Slot_inst_encode, 0, 0, 0, Opcode_ssai_Slot_ae_slot0_encode
};
-xtensa_opcode_encode_fn Opcode_sll_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_sll_encode_fns[] = {
Opcode_sll_Slot_inst_encode, 0, 0, 0, Opcode_sll_Slot_ae_slot0_encode
};
-xtensa_opcode_encode_fn Opcode_src_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_src_encode_fns[] = {
Opcode_src_Slot_inst_encode, 0, 0, 0, Opcode_src_Slot_ae_slot0_encode
};
-xtensa_opcode_encode_fn Opcode_srl_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_srl_encode_fns[] = {
Opcode_srl_Slot_inst_encode, 0, 0, 0, Opcode_srl_Slot_ae_slot0_encode
};
-xtensa_opcode_encode_fn Opcode_sra_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_sra_encode_fns[] = {
Opcode_sra_Slot_inst_encode, 0, 0, 0, Opcode_sra_Slot_ae_slot0_encode
};
-xtensa_opcode_encode_fn Opcode_slli_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_slli_encode_fns[] = {
Opcode_slli_Slot_inst_encode, 0, 0, 0, Opcode_slli_Slot_ae_slot0_encode
};
-xtensa_opcode_encode_fn Opcode_srai_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_srai_encode_fns[] = {
Opcode_srai_Slot_inst_encode, 0, 0, 0, Opcode_srai_Slot_ae_slot0_encode
};
-xtensa_opcode_encode_fn Opcode_srli_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_srli_encode_fns[] = {
Opcode_srli_Slot_inst_encode, 0, 0, 0, Opcode_srli_Slot_ae_slot0_encode
};
-xtensa_opcode_encode_fn Opcode_memw_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_memw_encode_fns[] = {
Opcode_memw_Slot_inst_encode, 0, 0, 0, 0
};
-xtensa_opcode_encode_fn Opcode_extw_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_extw_encode_fns[] = {
Opcode_extw_Slot_inst_encode, 0, 0, 0, 0
};
-xtensa_opcode_encode_fn Opcode_isync_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_isync_encode_fns[] = {
Opcode_isync_Slot_inst_encode, 0, 0, 0, 0
};
-xtensa_opcode_encode_fn Opcode_rsync_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_rsync_encode_fns[] = {
Opcode_rsync_Slot_inst_encode, 0, 0, 0, 0
};
-xtensa_opcode_encode_fn Opcode_esync_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_esync_encode_fns[] = {
Opcode_esync_Slot_inst_encode, 0, 0, 0, 0
};
-xtensa_opcode_encode_fn Opcode_dsync_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_dsync_encode_fns[] = {
Opcode_dsync_Slot_inst_encode, 0, 0, 0, 0
};
-xtensa_opcode_encode_fn Opcode_rsil_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_rsil_encode_fns[] = {
Opcode_rsil_Slot_inst_encode, 0, 0, 0, 0
};
-xtensa_opcode_encode_fn Opcode_rsr_lend_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_rsr_lend_encode_fns[] = {
Opcode_rsr_lend_Slot_inst_encode, 0, 0, 0, 0
};
-xtensa_opcode_encode_fn Opcode_wsr_lend_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_wsr_lend_encode_fns[] = {
Opcode_wsr_lend_Slot_inst_encode, 0, 0, 0, 0
};
-xtensa_opcode_encode_fn Opcode_xsr_lend_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_xsr_lend_encode_fns[] = {
Opcode_xsr_lend_Slot_inst_encode, 0, 0, 0, 0
};
-xtensa_opcode_encode_fn Opcode_rsr_lcount_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_rsr_lcount_encode_fns[] = {
Opcode_rsr_lcount_Slot_inst_encode, 0, 0, 0, 0
};
-xtensa_opcode_encode_fn Opcode_wsr_lcount_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_wsr_lcount_encode_fns[] = {
Opcode_wsr_lcount_Slot_inst_encode, 0, 0, 0, 0
};
-xtensa_opcode_encode_fn Opcode_xsr_lcount_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_xsr_lcount_encode_fns[] = {
Opcode_xsr_lcount_Slot_inst_encode, 0, 0, 0, 0
};
-xtensa_opcode_encode_fn Opcode_rsr_lbeg_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_rsr_lbeg_encode_fns[] = {
Opcode_rsr_lbeg_Slot_inst_encode, 0, 0, 0, 0
};
-xtensa_opcode_encode_fn Opcode_wsr_lbeg_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_wsr_lbeg_encode_fns[] = {
Opcode_wsr_lbeg_Slot_inst_encode, 0, 0, 0, 0
};
-xtensa_opcode_encode_fn Opcode_xsr_lbeg_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_xsr_lbeg_encode_fns[] = {
Opcode_xsr_lbeg_Slot_inst_encode, 0, 0, 0, 0
};
-xtensa_opcode_encode_fn Opcode_rsr_sar_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_rsr_sar_encode_fns[] = {
Opcode_rsr_sar_Slot_inst_encode, 0, 0, 0, 0
};
-xtensa_opcode_encode_fn Opcode_wsr_sar_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_wsr_sar_encode_fns[] = {
Opcode_wsr_sar_Slot_inst_encode, 0, 0, 0, 0
};
-xtensa_opcode_encode_fn Opcode_xsr_sar_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_xsr_sar_encode_fns[] = {
Opcode_xsr_sar_Slot_inst_encode, 0, 0, 0, 0
};
-xtensa_opcode_encode_fn Opcode_rsr_litbase_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_rsr_litbase_encode_fns[] = {
Opcode_rsr_litbase_Slot_inst_encode, 0, 0, 0, 0
};
-xtensa_opcode_encode_fn Opcode_wsr_litbase_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_wsr_litbase_encode_fns[] = {
Opcode_wsr_litbase_Slot_inst_encode, 0, 0, 0, 0
};
-xtensa_opcode_encode_fn Opcode_xsr_litbase_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_xsr_litbase_encode_fns[] = {
Opcode_xsr_litbase_Slot_inst_encode, 0, 0, 0, 0
};
-xtensa_opcode_encode_fn Opcode_rsr_176_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_rsr_176_encode_fns[] = {
Opcode_rsr_176_Slot_inst_encode, 0, 0, 0, 0
};
-xtensa_opcode_encode_fn Opcode_wsr_176_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_wsr_176_encode_fns[] = {
Opcode_wsr_176_Slot_inst_encode, 0, 0, 0, 0
};
-xtensa_opcode_encode_fn Opcode_rsr_208_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_rsr_208_encode_fns[] = {
Opcode_rsr_208_Slot_inst_encode, 0, 0, 0, 0
};
-xtensa_opcode_encode_fn Opcode_rsr_ps_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_rsr_ps_encode_fns[] = {
Opcode_rsr_ps_Slot_inst_encode, 0, 0, 0, 0
};
-xtensa_opcode_encode_fn Opcode_wsr_ps_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_wsr_ps_encode_fns[] = {
Opcode_wsr_ps_Slot_inst_encode, 0, 0, 0, 0
};
-xtensa_opcode_encode_fn Opcode_xsr_ps_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_xsr_ps_encode_fns[] = {
Opcode_xsr_ps_Slot_inst_encode, 0, 0, 0, 0
};
-xtensa_opcode_encode_fn Opcode_rsr_epc1_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_rsr_epc1_encode_fns[] = {
Opcode_rsr_epc1_Slot_inst_encode, 0, 0, 0, 0
};
-xtensa_opcode_encode_fn Opcode_wsr_epc1_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_wsr_epc1_encode_fns[] = {
Opcode_wsr_epc1_Slot_inst_encode, 0, 0, 0, 0
};
-xtensa_opcode_encode_fn Opcode_xsr_epc1_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_xsr_epc1_encode_fns[] = {
Opcode_xsr_epc1_Slot_inst_encode, 0, 0, 0, 0
};
-xtensa_opcode_encode_fn Opcode_rsr_excsave1_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_rsr_excsave1_encode_fns[] = {
Opcode_rsr_excsave1_Slot_inst_encode, 0, 0, 0, 0
};
-xtensa_opcode_encode_fn Opcode_wsr_excsave1_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_wsr_excsave1_encode_fns[] = {
Opcode_wsr_excsave1_Slot_inst_encode, 0, 0, 0, 0
};
-xtensa_opcode_encode_fn Opcode_xsr_excsave1_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_xsr_excsave1_encode_fns[] = {
Opcode_xsr_excsave1_Slot_inst_encode, 0, 0, 0, 0
};
-xtensa_opcode_encode_fn Opcode_rsr_epc2_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_rsr_epc2_encode_fns[] = {
Opcode_rsr_epc2_Slot_inst_encode, 0, 0, 0, 0
};
-xtensa_opcode_encode_fn Opcode_wsr_epc2_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_wsr_epc2_encode_fns[] = {
Opcode_wsr_epc2_Slot_inst_encode, 0, 0, 0, 0
};
-xtensa_opcode_encode_fn Opcode_xsr_epc2_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_xsr_epc2_encode_fns[] = {
Opcode_xsr_epc2_Slot_inst_encode, 0, 0, 0, 0
};
-xtensa_opcode_encode_fn Opcode_rsr_excsave2_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_rsr_excsave2_encode_fns[] = {
Opcode_rsr_excsave2_Slot_inst_encode, 0, 0, 0, 0
};
-xtensa_opcode_encode_fn Opcode_wsr_excsave2_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_wsr_excsave2_encode_fns[] = {
Opcode_wsr_excsave2_Slot_inst_encode, 0, 0, 0, 0
};
-xtensa_opcode_encode_fn Opcode_xsr_excsave2_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_xsr_excsave2_encode_fns[] = {
Opcode_xsr_excsave2_Slot_inst_encode, 0, 0, 0, 0
};
-xtensa_opcode_encode_fn Opcode_rsr_eps2_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_rsr_eps2_encode_fns[] = {
Opcode_rsr_eps2_Slot_inst_encode, 0, 0, 0, 0
};
-xtensa_opcode_encode_fn Opcode_wsr_eps2_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_wsr_eps2_encode_fns[] = {
Opcode_wsr_eps2_Slot_inst_encode, 0, 0, 0, 0
};
-xtensa_opcode_encode_fn Opcode_xsr_eps2_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_xsr_eps2_encode_fns[] = {
Opcode_xsr_eps2_Slot_inst_encode, 0, 0, 0, 0
};
-xtensa_opcode_encode_fn Opcode_rsr_excvaddr_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_rsr_excvaddr_encode_fns[] = {
Opcode_rsr_excvaddr_Slot_inst_encode, 0, 0, 0, 0
};
-xtensa_opcode_encode_fn Opcode_wsr_excvaddr_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_wsr_excvaddr_encode_fns[] = {
Opcode_wsr_excvaddr_Slot_inst_encode, 0, 0, 0, 0
};
-xtensa_opcode_encode_fn Opcode_xsr_excvaddr_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_xsr_excvaddr_encode_fns[] = {
Opcode_xsr_excvaddr_Slot_inst_encode, 0, 0, 0, 0
};
-xtensa_opcode_encode_fn Opcode_rsr_depc_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_rsr_depc_encode_fns[] = {
Opcode_rsr_depc_Slot_inst_encode, 0, 0, 0, 0
};
-xtensa_opcode_encode_fn Opcode_wsr_depc_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_wsr_depc_encode_fns[] = {
Opcode_wsr_depc_Slot_inst_encode, 0, 0, 0, 0
};
-xtensa_opcode_encode_fn Opcode_xsr_depc_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_xsr_depc_encode_fns[] = {
Opcode_xsr_depc_Slot_inst_encode, 0, 0, 0, 0
};
-xtensa_opcode_encode_fn Opcode_rsr_exccause_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_rsr_exccause_encode_fns[] = {
Opcode_rsr_exccause_Slot_inst_encode, 0, 0, 0, 0
};
-xtensa_opcode_encode_fn Opcode_wsr_exccause_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_wsr_exccause_encode_fns[] = {
Opcode_wsr_exccause_Slot_inst_encode, 0, 0, 0, 0
};
-xtensa_opcode_encode_fn Opcode_xsr_exccause_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_xsr_exccause_encode_fns[] = {
Opcode_xsr_exccause_Slot_inst_encode, 0, 0, 0, 0
};
-xtensa_opcode_encode_fn Opcode_rsr_misc0_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_rsr_misc0_encode_fns[] = {
Opcode_rsr_misc0_Slot_inst_encode, 0, 0, 0, 0
};
-xtensa_opcode_encode_fn Opcode_wsr_misc0_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_wsr_misc0_encode_fns[] = {
Opcode_wsr_misc0_Slot_inst_encode, 0, 0, 0, 0
};
-xtensa_opcode_encode_fn Opcode_xsr_misc0_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_xsr_misc0_encode_fns[] = {
Opcode_xsr_misc0_Slot_inst_encode, 0, 0, 0, 0
};
-xtensa_opcode_encode_fn Opcode_rsr_misc1_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_rsr_misc1_encode_fns[] = {
Opcode_rsr_misc1_Slot_inst_encode, 0, 0, 0, 0
};
-xtensa_opcode_encode_fn Opcode_wsr_misc1_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_wsr_misc1_encode_fns[] = {
Opcode_wsr_misc1_Slot_inst_encode, 0, 0, 0, 0
};
-xtensa_opcode_encode_fn Opcode_xsr_misc1_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_xsr_misc1_encode_fns[] = {
Opcode_xsr_misc1_Slot_inst_encode, 0, 0, 0, 0
};
-xtensa_opcode_encode_fn Opcode_rsr_prid_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_rsr_prid_encode_fns[] = {
Opcode_rsr_prid_Slot_inst_encode, 0, 0, 0, 0
};
-xtensa_opcode_encode_fn Opcode_rsr_vecbase_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_rsr_vecbase_encode_fns[] = {
Opcode_rsr_vecbase_Slot_inst_encode, 0, 0, 0, 0
};
-xtensa_opcode_encode_fn Opcode_wsr_vecbase_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_wsr_vecbase_encode_fns[] = {
Opcode_wsr_vecbase_Slot_inst_encode, 0, 0, 0, 0
};
-xtensa_opcode_encode_fn Opcode_xsr_vecbase_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_xsr_vecbase_encode_fns[] = {
Opcode_xsr_vecbase_Slot_inst_encode, 0, 0, 0, 0
};
-xtensa_opcode_encode_fn Opcode_mul16u_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_mul16u_encode_fns[] = {
Opcode_mul16u_Slot_inst_encode, 0, 0, 0, 0
};
-xtensa_opcode_encode_fn Opcode_mul16s_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_mul16s_encode_fns[] = {
Opcode_mul16s_Slot_inst_encode, 0, 0, 0, 0
};
-xtensa_opcode_encode_fn Opcode_mull_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_mull_encode_fns[] = {
Opcode_mull_Slot_inst_encode, 0, 0, 0, 0
};
-xtensa_opcode_encode_fn Opcode_rfi_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_rfi_encode_fns[] = {
Opcode_rfi_Slot_inst_encode, 0, 0, 0, 0
};
-xtensa_opcode_encode_fn Opcode_waiti_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_waiti_encode_fns[] = {
Opcode_waiti_Slot_inst_encode, 0, 0, 0, 0
};
-xtensa_opcode_encode_fn Opcode_rsr_interrupt_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_rsr_interrupt_encode_fns[] = {
Opcode_rsr_interrupt_Slot_inst_encode, 0, 0, 0, 0
};
-xtensa_opcode_encode_fn Opcode_wsr_intset_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_wsr_intset_encode_fns[] = {
Opcode_wsr_intset_Slot_inst_encode, 0, 0, 0, 0
};
-xtensa_opcode_encode_fn Opcode_wsr_intclear_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_wsr_intclear_encode_fns[] = {
Opcode_wsr_intclear_Slot_inst_encode, 0, 0, 0, 0
};
-xtensa_opcode_encode_fn Opcode_rsr_intenable_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_rsr_intenable_encode_fns[] = {
Opcode_rsr_intenable_Slot_inst_encode, 0, 0, 0, 0
};
-xtensa_opcode_encode_fn Opcode_wsr_intenable_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_wsr_intenable_encode_fns[] = {
Opcode_wsr_intenable_Slot_inst_encode, 0, 0, 0, 0
};
-xtensa_opcode_encode_fn Opcode_xsr_intenable_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_xsr_intenable_encode_fns[] = {
Opcode_xsr_intenable_Slot_inst_encode, 0, 0, 0, 0
};
-xtensa_opcode_encode_fn Opcode_break_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_break_encode_fns[] = {
Opcode_break_Slot_inst_encode, 0, 0, 0, 0
};
-xtensa_opcode_encode_fn Opcode_break_n_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_break_n_encode_fns[] = {
0, 0, Opcode_break_n_Slot_inst16b_encode, 0, 0
};
-xtensa_opcode_encode_fn Opcode_rsr_debugcause_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_rsr_debugcause_encode_fns[] = {
Opcode_rsr_debugcause_Slot_inst_encode, 0, 0, 0, 0
};
-xtensa_opcode_encode_fn Opcode_wsr_debugcause_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_wsr_debugcause_encode_fns[] = {
Opcode_wsr_debugcause_Slot_inst_encode, 0, 0, 0, 0
};
-xtensa_opcode_encode_fn Opcode_xsr_debugcause_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_xsr_debugcause_encode_fns[] = {
Opcode_xsr_debugcause_Slot_inst_encode, 0, 0, 0, 0
};
-xtensa_opcode_encode_fn Opcode_rsr_icount_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_rsr_icount_encode_fns[] = {
Opcode_rsr_icount_Slot_inst_encode, 0, 0, 0, 0
};
-xtensa_opcode_encode_fn Opcode_wsr_icount_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_wsr_icount_encode_fns[] = {
Opcode_wsr_icount_Slot_inst_encode, 0, 0, 0, 0
};
-xtensa_opcode_encode_fn Opcode_xsr_icount_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_xsr_icount_encode_fns[] = {
Opcode_xsr_icount_Slot_inst_encode, 0, 0, 0, 0
};
-xtensa_opcode_encode_fn Opcode_rsr_icountlevel_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_rsr_icountlevel_encode_fns[] = {
Opcode_rsr_icountlevel_Slot_inst_encode, 0, 0, 0, 0
};
-xtensa_opcode_encode_fn Opcode_wsr_icountlevel_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_wsr_icountlevel_encode_fns[] = {
Opcode_wsr_icountlevel_Slot_inst_encode, 0, 0, 0, 0
};
-xtensa_opcode_encode_fn Opcode_xsr_icountlevel_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_xsr_icountlevel_encode_fns[] = {
Opcode_xsr_icountlevel_Slot_inst_encode, 0, 0, 0, 0
};
-xtensa_opcode_encode_fn Opcode_rsr_ddr_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_rsr_ddr_encode_fns[] = {
Opcode_rsr_ddr_Slot_inst_encode, 0, 0, 0, 0
};
-xtensa_opcode_encode_fn Opcode_wsr_ddr_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_wsr_ddr_encode_fns[] = {
Opcode_wsr_ddr_Slot_inst_encode, 0, 0, 0, 0
};
-xtensa_opcode_encode_fn Opcode_xsr_ddr_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_xsr_ddr_encode_fns[] = {
Opcode_xsr_ddr_Slot_inst_encode, 0, 0, 0, 0
};
-xtensa_opcode_encode_fn Opcode_rfdo_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_rfdo_encode_fns[] = {
Opcode_rfdo_Slot_inst_encode, 0, 0, 0, 0
};
-xtensa_opcode_encode_fn Opcode_rfdd_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_rfdd_encode_fns[] = {
Opcode_rfdd_Slot_inst_encode, 0, 0, 0, 0
};
-xtensa_opcode_encode_fn Opcode_andb_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_andb_encode_fns[] = {
Opcode_andb_Slot_inst_encode, 0, 0, 0, Opcode_andb_Slot_ae_slot0_encode
};
-xtensa_opcode_encode_fn Opcode_andbc_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_andbc_encode_fns[] = {
Opcode_andbc_Slot_inst_encode, 0, 0, 0, Opcode_andbc_Slot_ae_slot0_encode
};
-xtensa_opcode_encode_fn Opcode_orb_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_orb_encode_fns[] = {
Opcode_orb_Slot_inst_encode, 0, 0, 0, Opcode_orb_Slot_ae_slot0_encode
};
-xtensa_opcode_encode_fn Opcode_orbc_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_orbc_encode_fns[] = {
Opcode_orbc_Slot_inst_encode, 0, 0, 0, Opcode_orbc_Slot_ae_slot0_encode
};
-xtensa_opcode_encode_fn Opcode_xorb_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_xorb_encode_fns[] = {
Opcode_xorb_Slot_inst_encode, 0, 0, 0, Opcode_xorb_Slot_ae_slot0_encode
};
-xtensa_opcode_encode_fn Opcode_any4_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_any4_encode_fns[] = {
Opcode_any4_Slot_inst_encode, 0, 0, 0, Opcode_any4_Slot_ae_slot0_encode
};
-xtensa_opcode_encode_fn Opcode_all4_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_all4_encode_fns[] = {
Opcode_all4_Slot_inst_encode, 0, 0, 0, Opcode_all4_Slot_ae_slot0_encode
};
-xtensa_opcode_encode_fn Opcode_any8_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_any8_encode_fns[] = {
Opcode_any8_Slot_inst_encode, 0, 0, 0, Opcode_any8_Slot_ae_slot0_encode
};
-xtensa_opcode_encode_fn Opcode_all8_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_all8_encode_fns[] = {
Opcode_all8_Slot_inst_encode, 0, 0, 0, Opcode_all8_Slot_ae_slot0_encode
};
-xtensa_opcode_encode_fn Opcode_bf_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_bf_encode_fns[] = {
Opcode_bf_Slot_inst_encode, 0, 0, 0, Opcode_bf_Slot_ae_slot0_encode
};
-xtensa_opcode_encode_fn Opcode_bt_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_bt_encode_fns[] = {
Opcode_bt_Slot_inst_encode, 0, 0, 0, Opcode_bt_Slot_ae_slot0_encode
};
-xtensa_opcode_encode_fn Opcode_movf_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_movf_encode_fns[] = {
Opcode_movf_Slot_inst_encode, 0, 0, 0, Opcode_movf_Slot_ae_slot0_encode
};
-xtensa_opcode_encode_fn Opcode_movt_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_movt_encode_fns[] = {
Opcode_movt_Slot_inst_encode, 0, 0, 0, Opcode_movt_Slot_ae_slot0_encode
};
-xtensa_opcode_encode_fn Opcode_rsr_br_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_rsr_br_encode_fns[] = {
Opcode_rsr_br_Slot_inst_encode, 0, 0, 0, 0
};
-xtensa_opcode_encode_fn Opcode_wsr_br_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_wsr_br_encode_fns[] = {
Opcode_wsr_br_Slot_inst_encode, 0, 0, 0, 0
};
-xtensa_opcode_encode_fn Opcode_xsr_br_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_xsr_br_encode_fns[] = {
Opcode_xsr_br_Slot_inst_encode, 0, 0, 0, 0
};
-xtensa_opcode_encode_fn Opcode_rsr_ccount_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_rsr_ccount_encode_fns[] = {
Opcode_rsr_ccount_Slot_inst_encode, 0, 0, 0, 0
};
-xtensa_opcode_encode_fn Opcode_wsr_ccount_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_wsr_ccount_encode_fns[] = {
Opcode_wsr_ccount_Slot_inst_encode, 0, 0, 0, 0
};
-xtensa_opcode_encode_fn Opcode_xsr_ccount_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_xsr_ccount_encode_fns[] = {
Opcode_xsr_ccount_Slot_inst_encode, 0, 0, 0, 0
};
-xtensa_opcode_encode_fn Opcode_rsr_ccompare0_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_rsr_ccompare0_encode_fns[] = {
Opcode_rsr_ccompare0_Slot_inst_encode, 0, 0, 0, 0
};
-xtensa_opcode_encode_fn Opcode_wsr_ccompare0_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_wsr_ccompare0_encode_fns[] = {
Opcode_wsr_ccompare0_Slot_inst_encode, 0, 0, 0, 0
};
-xtensa_opcode_encode_fn Opcode_xsr_ccompare0_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_xsr_ccompare0_encode_fns[] = {
Opcode_xsr_ccompare0_Slot_inst_encode, 0, 0, 0, 0
};
-xtensa_opcode_encode_fn Opcode_rsr_ccompare1_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_rsr_ccompare1_encode_fns[] = {
Opcode_rsr_ccompare1_Slot_inst_encode, 0, 0, 0, 0
};
-xtensa_opcode_encode_fn Opcode_wsr_ccompare1_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_wsr_ccompare1_encode_fns[] = {
Opcode_wsr_ccompare1_Slot_inst_encode, 0, 0, 0, 0
};
-xtensa_opcode_encode_fn Opcode_xsr_ccompare1_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_xsr_ccompare1_encode_fns[] = {
Opcode_xsr_ccompare1_Slot_inst_encode, 0, 0, 0, 0
};
-xtensa_opcode_encode_fn Opcode_ipf_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ipf_encode_fns[] = {
Opcode_ipf_Slot_inst_encode, 0, 0, 0, 0
};
-xtensa_opcode_encode_fn Opcode_ihi_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ihi_encode_fns[] = {
Opcode_ihi_Slot_inst_encode, 0, 0, 0, 0
};
-xtensa_opcode_encode_fn Opcode_iii_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_iii_encode_fns[] = {
Opcode_iii_Slot_inst_encode, 0, 0, 0, 0
};
-xtensa_opcode_encode_fn Opcode_lict_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_lict_encode_fns[] = {
Opcode_lict_Slot_inst_encode, 0, 0, 0, 0
};
-xtensa_opcode_encode_fn Opcode_licw_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_licw_encode_fns[] = {
Opcode_licw_Slot_inst_encode, 0, 0, 0, 0
};
-xtensa_opcode_encode_fn Opcode_sict_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_sict_encode_fns[] = {
Opcode_sict_Slot_inst_encode, 0, 0, 0, 0
};
-xtensa_opcode_encode_fn Opcode_sicw_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_sicw_encode_fns[] = {
Opcode_sicw_Slot_inst_encode, 0, 0, 0, 0
};
-xtensa_opcode_encode_fn Opcode_dhwb_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_dhwb_encode_fns[] = {
Opcode_dhwb_Slot_inst_encode, 0, 0, 0, 0
};
-xtensa_opcode_encode_fn Opcode_dhwbi_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_dhwbi_encode_fns[] = {
Opcode_dhwbi_Slot_inst_encode, 0, 0, 0, 0
};
-xtensa_opcode_encode_fn Opcode_diwb_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_diwb_encode_fns[] = {
Opcode_diwb_Slot_inst_encode, 0, 0, 0, 0
};
-xtensa_opcode_encode_fn Opcode_diwbi_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_diwbi_encode_fns[] = {
Opcode_diwbi_Slot_inst_encode, 0, 0, 0, 0
};
-xtensa_opcode_encode_fn Opcode_dhi_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_dhi_encode_fns[] = {
Opcode_dhi_Slot_inst_encode, 0, 0, 0, 0
};
-xtensa_opcode_encode_fn Opcode_dii_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_dii_encode_fns[] = {
Opcode_dii_Slot_inst_encode, 0, 0, 0, 0
};
-xtensa_opcode_encode_fn Opcode_dpfr_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_dpfr_encode_fns[] = {
Opcode_dpfr_Slot_inst_encode, 0, 0, 0, 0
};
-xtensa_opcode_encode_fn Opcode_dpfw_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_dpfw_encode_fns[] = {
Opcode_dpfw_Slot_inst_encode, 0, 0, 0, 0
};
-xtensa_opcode_encode_fn Opcode_dpfro_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_dpfro_encode_fns[] = {
Opcode_dpfro_Slot_inst_encode, 0, 0, 0, 0
};
-xtensa_opcode_encode_fn Opcode_dpfwo_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_dpfwo_encode_fns[] = {
Opcode_dpfwo_Slot_inst_encode, 0, 0, 0, 0
};
-xtensa_opcode_encode_fn Opcode_sdct_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_sdct_encode_fns[] = {
Opcode_sdct_Slot_inst_encode, 0, 0, 0, 0
};
-xtensa_opcode_encode_fn Opcode_ldct_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ldct_encode_fns[] = {
Opcode_ldct_Slot_inst_encode, 0, 0, 0, 0
};
-xtensa_opcode_encode_fn Opcode_wsr_ptevaddr_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_wsr_ptevaddr_encode_fns[] = {
Opcode_wsr_ptevaddr_Slot_inst_encode, 0, 0, 0, 0
};
-xtensa_opcode_encode_fn Opcode_rsr_ptevaddr_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_rsr_ptevaddr_encode_fns[] = {
Opcode_rsr_ptevaddr_Slot_inst_encode, 0, 0, 0, 0
};
-xtensa_opcode_encode_fn Opcode_xsr_ptevaddr_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_xsr_ptevaddr_encode_fns[] = {
Opcode_xsr_ptevaddr_Slot_inst_encode, 0, 0, 0, 0
};
-xtensa_opcode_encode_fn Opcode_rsr_rasid_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_rsr_rasid_encode_fns[] = {
Opcode_rsr_rasid_Slot_inst_encode, 0, 0, 0, 0
};
-xtensa_opcode_encode_fn Opcode_wsr_rasid_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_wsr_rasid_encode_fns[] = {
Opcode_wsr_rasid_Slot_inst_encode, 0, 0, 0, 0
};
-xtensa_opcode_encode_fn Opcode_xsr_rasid_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_xsr_rasid_encode_fns[] = {
Opcode_xsr_rasid_Slot_inst_encode, 0, 0, 0, 0
};
-xtensa_opcode_encode_fn Opcode_rsr_itlbcfg_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_rsr_itlbcfg_encode_fns[] = {
Opcode_rsr_itlbcfg_Slot_inst_encode, 0, 0, 0, 0
};
-xtensa_opcode_encode_fn Opcode_wsr_itlbcfg_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_wsr_itlbcfg_encode_fns[] = {
Opcode_wsr_itlbcfg_Slot_inst_encode, 0, 0, 0, 0
};
-xtensa_opcode_encode_fn Opcode_xsr_itlbcfg_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_xsr_itlbcfg_encode_fns[] = {
Opcode_xsr_itlbcfg_Slot_inst_encode, 0, 0, 0, 0
};
-xtensa_opcode_encode_fn Opcode_rsr_dtlbcfg_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_rsr_dtlbcfg_encode_fns[] = {
Opcode_rsr_dtlbcfg_Slot_inst_encode, 0, 0, 0, 0
};
-xtensa_opcode_encode_fn Opcode_wsr_dtlbcfg_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_wsr_dtlbcfg_encode_fns[] = {
Opcode_wsr_dtlbcfg_Slot_inst_encode, 0, 0, 0, 0
};
-xtensa_opcode_encode_fn Opcode_xsr_dtlbcfg_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_xsr_dtlbcfg_encode_fns[] = {
Opcode_xsr_dtlbcfg_Slot_inst_encode, 0, 0, 0, 0
};
-xtensa_opcode_encode_fn Opcode_idtlb_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_idtlb_encode_fns[] = {
Opcode_idtlb_Slot_inst_encode, 0, 0, 0, 0
};
-xtensa_opcode_encode_fn Opcode_pdtlb_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_pdtlb_encode_fns[] = {
Opcode_pdtlb_Slot_inst_encode, 0, 0, 0, 0
};
-xtensa_opcode_encode_fn Opcode_rdtlb0_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_rdtlb0_encode_fns[] = {
Opcode_rdtlb0_Slot_inst_encode, 0, 0, 0, 0
};
-xtensa_opcode_encode_fn Opcode_rdtlb1_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_rdtlb1_encode_fns[] = {
Opcode_rdtlb1_Slot_inst_encode, 0, 0, 0, 0
};
-xtensa_opcode_encode_fn Opcode_wdtlb_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_wdtlb_encode_fns[] = {
Opcode_wdtlb_Slot_inst_encode, 0, 0, 0, 0
};
-xtensa_opcode_encode_fn Opcode_iitlb_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_iitlb_encode_fns[] = {
Opcode_iitlb_Slot_inst_encode, 0, 0, 0, 0
};
-xtensa_opcode_encode_fn Opcode_pitlb_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_pitlb_encode_fns[] = {
Opcode_pitlb_Slot_inst_encode, 0, 0, 0, 0
};
-xtensa_opcode_encode_fn Opcode_ritlb0_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ritlb0_encode_fns[] = {
Opcode_ritlb0_Slot_inst_encode, 0, 0, 0, 0
};
-xtensa_opcode_encode_fn Opcode_ritlb1_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ritlb1_encode_fns[] = {
Opcode_ritlb1_Slot_inst_encode, 0, 0, 0, 0
};
-xtensa_opcode_encode_fn Opcode_witlb_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_witlb_encode_fns[] = {
Opcode_witlb_Slot_inst_encode, 0, 0, 0, 0
};
-xtensa_opcode_encode_fn Opcode_ldpte_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ldpte_encode_fns[] = {
Opcode_ldpte_Slot_inst_encode, 0, 0, 0, 0
};
-xtensa_opcode_encode_fn Opcode_hwwitlba_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_hwwitlba_encode_fns[] = {
Opcode_hwwitlba_Slot_inst_encode, 0, 0, 0, 0
};
-xtensa_opcode_encode_fn Opcode_hwwdtlba_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_hwwdtlba_encode_fns[] = {
Opcode_hwwdtlba_Slot_inst_encode, 0, 0, 0, 0
};
-xtensa_opcode_encode_fn Opcode_rsr_cpenable_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_rsr_cpenable_encode_fns[] = {
Opcode_rsr_cpenable_Slot_inst_encode, 0, 0, 0, 0
};
-xtensa_opcode_encode_fn Opcode_wsr_cpenable_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_wsr_cpenable_encode_fns[] = {
Opcode_wsr_cpenable_Slot_inst_encode, 0, 0, 0, 0
};
-xtensa_opcode_encode_fn Opcode_xsr_cpenable_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_xsr_cpenable_encode_fns[] = {
Opcode_xsr_cpenable_Slot_inst_encode, 0, 0, 0, 0
};
-xtensa_opcode_encode_fn Opcode_clamps_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_clamps_encode_fns[] = {
Opcode_clamps_Slot_inst_encode, 0, 0, 0, Opcode_clamps_Slot_ae_slot0_encode
};
-xtensa_opcode_encode_fn Opcode_min_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_min_encode_fns[] = {
Opcode_min_Slot_inst_encode, 0, 0, 0, Opcode_min_Slot_ae_slot0_encode
};
-xtensa_opcode_encode_fn Opcode_max_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_max_encode_fns[] = {
Opcode_max_Slot_inst_encode, 0, 0, 0, Opcode_max_Slot_ae_slot0_encode
};
-xtensa_opcode_encode_fn Opcode_minu_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_minu_encode_fns[] = {
Opcode_minu_Slot_inst_encode, 0, 0, 0, Opcode_minu_Slot_ae_slot0_encode
};
-xtensa_opcode_encode_fn Opcode_maxu_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_maxu_encode_fns[] = {
Opcode_maxu_Slot_inst_encode, 0, 0, 0, Opcode_maxu_Slot_ae_slot0_encode
};
-xtensa_opcode_encode_fn Opcode_nsa_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_nsa_encode_fns[] = {
Opcode_nsa_Slot_inst_encode, 0, 0, 0, 0
};
-xtensa_opcode_encode_fn Opcode_nsau_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_nsau_encode_fns[] = {
Opcode_nsau_Slot_inst_encode, 0, 0, 0, 0
};
-xtensa_opcode_encode_fn Opcode_sext_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_sext_encode_fns[] = {
Opcode_sext_Slot_inst_encode, 0, 0, 0, Opcode_sext_Slot_ae_slot0_encode
};
-xtensa_opcode_encode_fn Opcode_l32ai_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_l32ai_encode_fns[] = {
Opcode_l32ai_Slot_inst_encode, 0, 0, 0, 0
};
-xtensa_opcode_encode_fn Opcode_s32ri_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_s32ri_encode_fns[] = {
Opcode_s32ri_Slot_inst_encode, 0, 0, 0, 0
};
-xtensa_opcode_encode_fn Opcode_s32c1i_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_s32c1i_encode_fns[] = {
Opcode_s32c1i_Slot_inst_encode, 0, 0, 0, 0
};
-xtensa_opcode_encode_fn Opcode_rsr_scompare1_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_rsr_scompare1_encode_fns[] = {
Opcode_rsr_scompare1_Slot_inst_encode, 0, 0, 0, 0
};
-xtensa_opcode_encode_fn Opcode_wsr_scompare1_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_wsr_scompare1_encode_fns[] = {
Opcode_wsr_scompare1_Slot_inst_encode, 0, 0, 0, 0
};
-xtensa_opcode_encode_fn Opcode_xsr_scompare1_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_xsr_scompare1_encode_fns[] = {
Opcode_xsr_scompare1_Slot_inst_encode, 0, 0, 0, 0
};
-xtensa_opcode_encode_fn Opcode_rsr_atomctl_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_rsr_atomctl_encode_fns[] = {
Opcode_rsr_atomctl_Slot_inst_encode, 0, 0, 0, 0
};
-xtensa_opcode_encode_fn Opcode_wsr_atomctl_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_wsr_atomctl_encode_fns[] = {
Opcode_wsr_atomctl_Slot_inst_encode, 0, 0, 0, 0
};
-xtensa_opcode_encode_fn Opcode_xsr_atomctl_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_xsr_atomctl_encode_fns[] = {
Opcode_xsr_atomctl_Slot_inst_encode, 0, 0, 0, 0
};
-xtensa_opcode_encode_fn Opcode_rer_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_rer_encode_fns[] = {
Opcode_rer_Slot_inst_encode, 0, 0, 0, 0
};
-xtensa_opcode_encode_fn Opcode_wer_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_wer_encode_fns[] = {
Opcode_wer_Slot_inst_encode, 0, 0, 0, 0
};
-xtensa_opcode_encode_fn Opcode_rur_ae_ovf_sar_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_rur_ae_ovf_sar_encode_fns[] = {
Opcode_rur_ae_ovf_sar_Slot_inst_encode, 0, 0, 0, 0
};
-xtensa_opcode_encode_fn Opcode_wur_ae_ovf_sar_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_wur_ae_ovf_sar_encode_fns[] = {
Opcode_wur_ae_ovf_sar_Slot_inst_encode, 0, 0, 0, 0
};
-xtensa_opcode_encode_fn Opcode_rur_ae_bithead_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_rur_ae_bithead_encode_fns[] = {
Opcode_rur_ae_bithead_Slot_inst_encode, 0, 0, 0, 0
};
-xtensa_opcode_encode_fn Opcode_wur_ae_bithead_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_wur_ae_bithead_encode_fns[] = {
Opcode_wur_ae_bithead_Slot_inst_encode, 0, 0, 0, 0
};
-xtensa_opcode_encode_fn Opcode_rur_ae_ts_fts_bu_bp_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_rur_ae_ts_fts_bu_bp_encode_fns[] = {
Opcode_rur_ae_ts_fts_bu_bp_Slot_inst_encode, 0, 0, 0, 0
};
-xtensa_opcode_encode_fn Opcode_wur_ae_ts_fts_bu_bp_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_wur_ae_ts_fts_bu_bp_encode_fns[] = {
Opcode_wur_ae_ts_fts_bu_bp_Slot_inst_encode, 0, 0, 0, 0
};
-xtensa_opcode_encode_fn Opcode_rur_ae_sd_no_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_rur_ae_sd_no_encode_fns[] = {
Opcode_rur_ae_sd_no_Slot_inst_encode, 0, 0, 0, 0
};
-xtensa_opcode_encode_fn Opcode_wur_ae_sd_no_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_wur_ae_sd_no_encode_fns[] = {
Opcode_wur_ae_sd_no_Slot_inst_encode, 0, 0, 0, 0
};
-xtensa_opcode_encode_fn Opcode_rur_ae_overflow_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_rur_ae_overflow_encode_fns[] = {
Opcode_rur_ae_overflow_Slot_inst_encode, 0, 0, 0, 0
};
-xtensa_opcode_encode_fn Opcode_wur_ae_overflow_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_wur_ae_overflow_encode_fns[] = {
Opcode_wur_ae_overflow_Slot_inst_encode, 0, 0, 0, 0
};
-xtensa_opcode_encode_fn Opcode_rur_ae_sar_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_rur_ae_sar_encode_fns[] = {
Opcode_rur_ae_sar_Slot_inst_encode, 0, 0, 0, 0
};
-xtensa_opcode_encode_fn Opcode_wur_ae_sar_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_wur_ae_sar_encode_fns[] = {
Opcode_wur_ae_sar_Slot_inst_encode, 0, 0, 0, 0
};
-xtensa_opcode_encode_fn Opcode_rur_ae_bitptr_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_rur_ae_bitptr_encode_fns[] = {
Opcode_rur_ae_bitptr_Slot_inst_encode, 0, 0, 0, 0
};
-xtensa_opcode_encode_fn Opcode_wur_ae_bitptr_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_wur_ae_bitptr_encode_fns[] = {
Opcode_wur_ae_bitptr_Slot_inst_encode, 0, 0, 0, 0
};
-xtensa_opcode_encode_fn Opcode_rur_ae_bitsused_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_rur_ae_bitsused_encode_fns[] = {
Opcode_rur_ae_bitsused_Slot_inst_encode, 0, 0, 0, 0
};
-xtensa_opcode_encode_fn Opcode_wur_ae_bitsused_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_wur_ae_bitsused_encode_fns[] = {
Opcode_wur_ae_bitsused_Slot_inst_encode, 0, 0, 0, 0
};
-xtensa_opcode_encode_fn Opcode_rur_ae_tablesize_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_rur_ae_tablesize_encode_fns[] = {
Opcode_rur_ae_tablesize_Slot_inst_encode, 0, 0, 0, 0
};
-xtensa_opcode_encode_fn Opcode_wur_ae_tablesize_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_wur_ae_tablesize_encode_fns[] = {
Opcode_wur_ae_tablesize_Slot_inst_encode, 0, 0, 0, 0
};
-xtensa_opcode_encode_fn Opcode_rur_ae_first_ts_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_rur_ae_first_ts_encode_fns[] = {
Opcode_rur_ae_first_ts_Slot_inst_encode, 0, 0, 0, 0
};
-xtensa_opcode_encode_fn Opcode_wur_ae_first_ts_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_wur_ae_first_ts_encode_fns[] = {
Opcode_wur_ae_first_ts_Slot_inst_encode, 0, 0, 0, 0
};
-xtensa_opcode_encode_fn Opcode_rur_ae_nextoffset_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_rur_ae_nextoffset_encode_fns[] = {
Opcode_rur_ae_nextoffset_Slot_inst_encode, 0, 0, 0, 0
};
-xtensa_opcode_encode_fn Opcode_wur_ae_nextoffset_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_wur_ae_nextoffset_encode_fns[] = {
Opcode_wur_ae_nextoffset_Slot_inst_encode, 0, 0, 0, 0
};
-xtensa_opcode_encode_fn Opcode_rur_ae_searchdone_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_rur_ae_searchdone_encode_fns[] = {
Opcode_rur_ae_searchdone_Slot_inst_encode, 0, 0, 0, 0
};
-xtensa_opcode_encode_fn Opcode_wur_ae_searchdone_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_wur_ae_searchdone_encode_fns[] = {
Opcode_wur_ae_searchdone_Slot_inst_encode, 0, 0, 0, 0
};
-xtensa_opcode_encode_fn Opcode_ae_lp16f_i_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_lp16f_i_encode_fns[] = {
Opcode_ae_lp16f_i_Slot_inst_encode, 0, 0, 0, Opcode_ae_lp16f_i_Slot_ae_slot0_encode
};
-xtensa_opcode_encode_fn Opcode_ae_lp16f_iu_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_lp16f_iu_encode_fns[] = {
Opcode_ae_lp16f_iu_Slot_inst_encode, 0, 0, 0, Opcode_ae_lp16f_iu_Slot_ae_slot0_encode
};
-xtensa_opcode_encode_fn Opcode_ae_lp16f_x_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_lp16f_x_encode_fns[] = {
Opcode_ae_lp16f_x_Slot_inst_encode, 0, 0, 0, Opcode_ae_lp16f_x_Slot_ae_slot0_encode
};
-xtensa_opcode_encode_fn Opcode_ae_lp16f_xu_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_lp16f_xu_encode_fns[] = {
Opcode_ae_lp16f_xu_Slot_inst_encode, 0, 0, 0, Opcode_ae_lp16f_xu_Slot_ae_slot0_encode
};
-xtensa_opcode_encode_fn Opcode_ae_lp24_i_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_lp24_i_encode_fns[] = {
Opcode_ae_lp24_i_Slot_inst_encode, 0, 0, 0, Opcode_ae_lp24_i_Slot_ae_slot0_encode
};
-xtensa_opcode_encode_fn Opcode_ae_lp24_iu_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_lp24_iu_encode_fns[] = {
Opcode_ae_lp24_iu_Slot_inst_encode, 0, 0, 0, Opcode_ae_lp24_iu_Slot_ae_slot0_encode
};
-xtensa_opcode_encode_fn Opcode_ae_lp24_x_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_lp24_x_encode_fns[] = {
Opcode_ae_lp24_x_Slot_inst_encode, 0, 0, 0, Opcode_ae_lp24_x_Slot_ae_slot0_encode
};
-xtensa_opcode_encode_fn Opcode_ae_lp24_xu_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_lp24_xu_encode_fns[] = {
Opcode_ae_lp24_xu_Slot_inst_encode, 0, 0, 0, Opcode_ae_lp24_xu_Slot_ae_slot0_encode
};
-xtensa_opcode_encode_fn Opcode_ae_lp24f_i_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_lp24f_i_encode_fns[] = {
Opcode_ae_lp24f_i_Slot_inst_encode, 0, 0, 0, Opcode_ae_lp24f_i_Slot_ae_slot0_encode
};
-xtensa_opcode_encode_fn Opcode_ae_lp24f_iu_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_lp24f_iu_encode_fns[] = {
Opcode_ae_lp24f_iu_Slot_inst_encode, 0, 0, 0, Opcode_ae_lp24f_iu_Slot_ae_slot0_encode
};
-xtensa_opcode_encode_fn Opcode_ae_lp24f_x_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_lp24f_x_encode_fns[] = {
Opcode_ae_lp24f_x_Slot_inst_encode, 0, 0, 0, Opcode_ae_lp24f_x_Slot_ae_slot0_encode
};
-xtensa_opcode_encode_fn Opcode_ae_lp24f_xu_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_lp24f_xu_encode_fns[] = {
Opcode_ae_lp24f_xu_Slot_inst_encode, 0, 0, 0, Opcode_ae_lp24f_xu_Slot_ae_slot0_encode
};
-xtensa_opcode_encode_fn Opcode_ae_lp16x2f_i_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_lp16x2f_i_encode_fns[] = {
Opcode_ae_lp16x2f_i_Slot_inst_encode, 0, 0, 0, Opcode_ae_lp16x2f_i_Slot_ae_slot0_encode
};
-xtensa_opcode_encode_fn Opcode_ae_lp16x2f_iu_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_lp16x2f_iu_encode_fns[] = {
Opcode_ae_lp16x2f_iu_Slot_inst_encode, 0, 0, 0, Opcode_ae_lp16x2f_iu_Slot_ae_slot0_encode
};
-xtensa_opcode_encode_fn Opcode_ae_lp16x2f_x_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_lp16x2f_x_encode_fns[] = {
Opcode_ae_lp16x2f_x_Slot_inst_encode, 0, 0, 0, Opcode_ae_lp16x2f_x_Slot_ae_slot0_encode
};
-xtensa_opcode_encode_fn Opcode_ae_lp16x2f_xu_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_lp16x2f_xu_encode_fns[] = {
Opcode_ae_lp16x2f_xu_Slot_inst_encode, 0, 0, 0, Opcode_ae_lp16x2f_xu_Slot_ae_slot0_encode
};
-xtensa_opcode_encode_fn Opcode_ae_lp24x2f_i_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_lp24x2f_i_encode_fns[] = {
Opcode_ae_lp24x2f_i_Slot_inst_encode, 0, 0, 0, Opcode_ae_lp24x2f_i_Slot_ae_slot0_encode
};
-xtensa_opcode_encode_fn Opcode_ae_lp24x2f_iu_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_lp24x2f_iu_encode_fns[] = {
Opcode_ae_lp24x2f_iu_Slot_inst_encode, 0, 0, 0, Opcode_ae_lp24x2f_iu_Slot_ae_slot0_encode
};
-xtensa_opcode_encode_fn Opcode_ae_lp24x2f_x_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_lp24x2f_x_encode_fns[] = {
Opcode_ae_lp24x2f_x_Slot_inst_encode, 0, 0, 0, Opcode_ae_lp24x2f_x_Slot_ae_slot0_encode
};
-xtensa_opcode_encode_fn Opcode_ae_lp24x2f_xu_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_lp24x2f_xu_encode_fns[] = {
Opcode_ae_lp24x2f_xu_Slot_inst_encode, 0, 0, 0, Opcode_ae_lp24x2f_xu_Slot_ae_slot0_encode
};
-xtensa_opcode_encode_fn Opcode_ae_lp24x2_i_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_lp24x2_i_encode_fns[] = {
Opcode_ae_lp24x2_i_Slot_inst_encode, 0, 0, 0, Opcode_ae_lp24x2_i_Slot_ae_slot0_encode
};
-xtensa_opcode_encode_fn Opcode_ae_lp24x2_iu_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_lp24x2_iu_encode_fns[] = {
Opcode_ae_lp24x2_iu_Slot_inst_encode, 0, 0, 0, Opcode_ae_lp24x2_iu_Slot_ae_slot0_encode
};
-xtensa_opcode_encode_fn Opcode_ae_lp24x2_x_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_lp24x2_x_encode_fns[] = {
Opcode_ae_lp24x2_x_Slot_inst_encode, 0, 0, 0, Opcode_ae_lp24x2_x_Slot_ae_slot0_encode
};
-xtensa_opcode_encode_fn Opcode_ae_lp24x2_xu_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_lp24x2_xu_encode_fns[] = {
Opcode_ae_lp24x2_xu_Slot_inst_encode, 0, 0, 0, Opcode_ae_lp24x2_xu_Slot_ae_slot0_encode
};
-xtensa_opcode_encode_fn Opcode_ae_sp16x2f_i_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_sp16x2f_i_encode_fns[] = {
Opcode_ae_sp16x2f_i_Slot_inst_encode, 0, 0, 0, Opcode_ae_sp16x2f_i_Slot_ae_slot0_encode
};
-xtensa_opcode_encode_fn Opcode_ae_sp16x2f_iu_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_sp16x2f_iu_encode_fns[] = {
Opcode_ae_sp16x2f_iu_Slot_inst_encode, 0, 0, 0, Opcode_ae_sp16x2f_iu_Slot_ae_slot0_encode
};
-xtensa_opcode_encode_fn Opcode_ae_sp16x2f_x_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_sp16x2f_x_encode_fns[] = {
Opcode_ae_sp16x2f_x_Slot_inst_encode, 0, 0, 0, Opcode_ae_sp16x2f_x_Slot_ae_slot0_encode
};
-xtensa_opcode_encode_fn Opcode_ae_sp16x2f_xu_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_sp16x2f_xu_encode_fns[] = {
Opcode_ae_sp16x2f_xu_Slot_inst_encode, 0, 0, 0, Opcode_ae_sp16x2f_xu_Slot_ae_slot0_encode
};
-xtensa_opcode_encode_fn Opcode_ae_sp24x2s_i_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_sp24x2s_i_encode_fns[] = {
Opcode_ae_sp24x2s_i_Slot_inst_encode, 0, 0, 0, Opcode_ae_sp24x2s_i_Slot_ae_slot0_encode
};
-xtensa_opcode_encode_fn Opcode_ae_sp24x2s_iu_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_sp24x2s_iu_encode_fns[] = {
Opcode_ae_sp24x2s_iu_Slot_inst_encode, 0, 0, 0, Opcode_ae_sp24x2s_iu_Slot_ae_slot0_encode
};
-xtensa_opcode_encode_fn Opcode_ae_sp24x2s_x_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_sp24x2s_x_encode_fns[] = {
Opcode_ae_sp24x2s_x_Slot_inst_encode, 0, 0, 0, Opcode_ae_sp24x2s_x_Slot_ae_slot0_encode
};
-xtensa_opcode_encode_fn Opcode_ae_sp24x2s_xu_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_sp24x2s_xu_encode_fns[] = {
Opcode_ae_sp24x2s_xu_Slot_inst_encode, 0, 0, 0, Opcode_ae_sp24x2s_xu_Slot_ae_slot0_encode
};
-xtensa_opcode_encode_fn Opcode_ae_sp24x2f_i_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_sp24x2f_i_encode_fns[] = {
Opcode_ae_sp24x2f_i_Slot_inst_encode, 0, 0, 0, Opcode_ae_sp24x2f_i_Slot_ae_slot0_encode
};
-xtensa_opcode_encode_fn Opcode_ae_sp24x2f_iu_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_sp24x2f_iu_encode_fns[] = {
Opcode_ae_sp24x2f_iu_Slot_inst_encode, 0, 0, 0, Opcode_ae_sp24x2f_iu_Slot_ae_slot0_encode
};
-xtensa_opcode_encode_fn Opcode_ae_sp24x2f_x_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_sp24x2f_x_encode_fns[] = {
Opcode_ae_sp24x2f_x_Slot_inst_encode, 0, 0, 0, Opcode_ae_sp24x2f_x_Slot_ae_slot0_encode
};
-xtensa_opcode_encode_fn Opcode_ae_sp24x2f_xu_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_sp24x2f_xu_encode_fns[] = {
Opcode_ae_sp24x2f_xu_Slot_inst_encode, 0, 0, 0, Opcode_ae_sp24x2f_xu_Slot_ae_slot0_encode
};
-xtensa_opcode_encode_fn Opcode_ae_sp16f_l_i_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_sp16f_l_i_encode_fns[] = {
Opcode_ae_sp16f_l_i_Slot_inst_encode, 0, 0, 0, Opcode_ae_sp16f_l_i_Slot_ae_slot0_encode
};
-xtensa_opcode_encode_fn Opcode_ae_sp16f_l_iu_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_sp16f_l_iu_encode_fns[] = {
Opcode_ae_sp16f_l_iu_Slot_inst_encode, 0, 0, 0, Opcode_ae_sp16f_l_iu_Slot_ae_slot0_encode
};
-xtensa_opcode_encode_fn Opcode_ae_sp16f_l_x_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_sp16f_l_x_encode_fns[] = {
Opcode_ae_sp16f_l_x_Slot_inst_encode, 0, 0, 0, Opcode_ae_sp16f_l_x_Slot_ae_slot0_encode
};
-xtensa_opcode_encode_fn Opcode_ae_sp16f_l_xu_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_sp16f_l_xu_encode_fns[] = {
Opcode_ae_sp16f_l_xu_Slot_inst_encode, 0, 0, 0, Opcode_ae_sp16f_l_xu_Slot_ae_slot0_encode
};
-xtensa_opcode_encode_fn Opcode_ae_sp24s_l_i_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_sp24s_l_i_encode_fns[] = {
Opcode_ae_sp24s_l_i_Slot_inst_encode, 0, 0, 0, Opcode_ae_sp24s_l_i_Slot_ae_slot0_encode
};
-xtensa_opcode_encode_fn Opcode_ae_sp24s_l_iu_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_sp24s_l_iu_encode_fns[] = {
Opcode_ae_sp24s_l_iu_Slot_inst_encode, 0, 0, 0, Opcode_ae_sp24s_l_iu_Slot_ae_slot0_encode
};
-xtensa_opcode_encode_fn Opcode_ae_sp24s_l_x_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_sp24s_l_x_encode_fns[] = {
Opcode_ae_sp24s_l_x_Slot_inst_encode, 0, 0, 0, Opcode_ae_sp24s_l_x_Slot_ae_slot0_encode
};
-xtensa_opcode_encode_fn Opcode_ae_sp24s_l_xu_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_sp24s_l_xu_encode_fns[] = {
Opcode_ae_sp24s_l_xu_Slot_inst_encode, 0, 0, 0, Opcode_ae_sp24s_l_xu_Slot_ae_slot0_encode
};
-xtensa_opcode_encode_fn Opcode_ae_sp24f_l_i_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_sp24f_l_i_encode_fns[] = {
Opcode_ae_sp24f_l_i_Slot_inst_encode, 0, 0, 0, Opcode_ae_sp24f_l_i_Slot_ae_slot0_encode
};
-xtensa_opcode_encode_fn Opcode_ae_sp24f_l_iu_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_sp24f_l_iu_encode_fns[] = {
Opcode_ae_sp24f_l_iu_Slot_inst_encode, 0, 0, 0, Opcode_ae_sp24f_l_iu_Slot_ae_slot0_encode
};
-xtensa_opcode_encode_fn Opcode_ae_sp24f_l_x_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_sp24f_l_x_encode_fns[] = {
Opcode_ae_sp24f_l_x_Slot_inst_encode, 0, 0, 0, Opcode_ae_sp24f_l_x_Slot_ae_slot0_encode
};
-xtensa_opcode_encode_fn Opcode_ae_sp24f_l_xu_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_sp24f_l_xu_encode_fns[] = {
Opcode_ae_sp24f_l_xu_Slot_inst_encode, 0, 0, 0, Opcode_ae_sp24f_l_xu_Slot_ae_slot0_encode
};
-xtensa_opcode_encode_fn Opcode_ae_lq56_i_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_lq56_i_encode_fns[] = {
Opcode_ae_lq56_i_Slot_inst_encode, 0, 0, 0, Opcode_ae_lq56_i_Slot_ae_slot0_encode
};
-xtensa_opcode_encode_fn Opcode_ae_lq56_iu_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_lq56_iu_encode_fns[] = {
Opcode_ae_lq56_iu_Slot_inst_encode, 0, 0, 0, Opcode_ae_lq56_iu_Slot_ae_slot0_encode
};
-xtensa_opcode_encode_fn Opcode_ae_lq56_x_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_lq56_x_encode_fns[] = {
Opcode_ae_lq56_x_Slot_inst_encode, 0, 0, 0, Opcode_ae_lq56_x_Slot_ae_slot0_encode
};
-xtensa_opcode_encode_fn Opcode_ae_lq56_xu_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_lq56_xu_encode_fns[] = {
Opcode_ae_lq56_xu_Slot_inst_encode, 0, 0, 0, Opcode_ae_lq56_xu_Slot_ae_slot0_encode
};
-xtensa_opcode_encode_fn Opcode_ae_lq32f_i_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_lq32f_i_encode_fns[] = {
Opcode_ae_lq32f_i_Slot_inst_encode, 0, 0, 0, Opcode_ae_lq32f_i_Slot_ae_slot0_encode
};
-xtensa_opcode_encode_fn Opcode_ae_lq32f_iu_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_lq32f_iu_encode_fns[] = {
Opcode_ae_lq32f_iu_Slot_inst_encode, 0, 0, 0, Opcode_ae_lq32f_iu_Slot_ae_slot0_encode
};
-xtensa_opcode_encode_fn Opcode_ae_lq32f_x_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_lq32f_x_encode_fns[] = {
Opcode_ae_lq32f_x_Slot_inst_encode, 0, 0, 0, Opcode_ae_lq32f_x_Slot_ae_slot0_encode
};
-xtensa_opcode_encode_fn Opcode_ae_lq32f_xu_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_lq32f_xu_encode_fns[] = {
Opcode_ae_lq32f_xu_Slot_inst_encode, 0, 0, 0, Opcode_ae_lq32f_xu_Slot_ae_slot0_encode
};
-xtensa_opcode_encode_fn Opcode_ae_sq56s_i_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_sq56s_i_encode_fns[] = {
Opcode_ae_sq56s_i_Slot_inst_encode, 0, 0, 0, Opcode_ae_sq56s_i_Slot_ae_slot0_encode
};
-xtensa_opcode_encode_fn Opcode_ae_sq56s_iu_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_sq56s_iu_encode_fns[] = {
Opcode_ae_sq56s_iu_Slot_inst_encode, 0, 0, 0, Opcode_ae_sq56s_iu_Slot_ae_slot0_encode
};
-xtensa_opcode_encode_fn Opcode_ae_sq56s_x_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_sq56s_x_encode_fns[] = {
Opcode_ae_sq56s_x_Slot_inst_encode, 0, 0, 0, Opcode_ae_sq56s_x_Slot_ae_slot0_encode
};
-xtensa_opcode_encode_fn Opcode_ae_sq56s_xu_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_sq56s_xu_encode_fns[] = {
Opcode_ae_sq56s_xu_Slot_inst_encode, 0, 0, 0, Opcode_ae_sq56s_xu_Slot_ae_slot0_encode
};
-xtensa_opcode_encode_fn Opcode_ae_sq32f_i_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_sq32f_i_encode_fns[] = {
Opcode_ae_sq32f_i_Slot_inst_encode, 0, 0, 0, Opcode_ae_sq32f_i_Slot_ae_slot0_encode
};
-xtensa_opcode_encode_fn Opcode_ae_sq32f_iu_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_sq32f_iu_encode_fns[] = {
Opcode_ae_sq32f_iu_Slot_inst_encode, 0, 0, 0, Opcode_ae_sq32f_iu_Slot_ae_slot0_encode
};
-xtensa_opcode_encode_fn Opcode_ae_sq32f_x_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_sq32f_x_encode_fns[] = {
Opcode_ae_sq32f_x_Slot_inst_encode, 0, 0, 0, Opcode_ae_sq32f_x_Slot_ae_slot0_encode
};
-xtensa_opcode_encode_fn Opcode_ae_sq32f_xu_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_sq32f_xu_encode_fns[] = {
Opcode_ae_sq32f_xu_Slot_inst_encode, 0, 0, 0, Opcode_ae_sq32f_xu_Slot_ae_slot0_encode
};
-xtensa_opcode_encode_fn Opcode_ae_zerop48_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_zerop48_encode_fns[] = {
0, 0, 0, Opcode_ae_zerop48_Slot_ae_slot1_encode, 0
};
-xtensa_opcode_encode_fn Opcode_ae_movp48_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_movp48_encode_fns[] = {
Opcode_ae_movp48_Slot_inst_encode, 0, 0, Opcode_ae_movp48_Slot_ae_slot1_encode, Opcode_ae_movp48_Slot_ae_slot0_encode
};
-xtensa_opcode_encode_fn Opcode_ae_selp24_ll_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_selp24_ll_encode_fns[] = {
0, 0, 0, Opcode_ae_selp24_ll_Slot_ae_slot1_encode, 0
};
-xtensa_opcode_encode_fn Opcode_ae_selp24_lh_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_selp24_lh_encode_fns[] = {
0, 0, 0, Opcode_ae_selp24_lh_Slot_ae_slot1_encode, 0
};
-xtensa_opcode_encode_fn Opcode_ae_selp24_hl_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_selp24_hl_encode_fns[] = {
0, 0, 0, Opcode_ae_selp24_hl_Slot_ae_slot1_encode, 0
};
-xtensa_opcode_encode_fn Opcode_ae_selp24_hh_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_selp24_hh_encode_fns[] = {
0, 0, 0, Opcode_ae_selp24_hh_Slot_ae_slot1_encode, 0
};
-xtensa_opcode_encode_fn Opcode_ae_movtp24x2_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_movtp24x2_encode_fns[] = {
0, 0, 0, Opcode_ae_movtp24x2_Slot_ae_slot1_encode, 0
};
-xtensa_opcode_encode_fn Opcode_ae_movfp24x2_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_movfp24x2_encode_fns[] = {
0, 0, 0, Opcode_ae_movfp24x2_Slot_ae_slot1_encode, 0
};
-xtensa_opcode_encode_fn Opcode_ae_movtp48_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_movtp48_encode_fns[] = {
0, 0, 0, Opcode_ae_movtp48_Slot_ae_slot1_encode, 0
};
-xtensa_opcode_encode_fn Opcode_ae_movfp48_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_movfp48_encode_fns[] = {
0, 0, 0, Opcode_ae_movfp48_Slot_ae_slot1_encode, 0
};
-xtensa_opcode_encode_fn Opcode_ae_movpa24x2_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_movpa24x2_encode_fns[] = {
Opcode_ae_movpa24x2_Slot_inst_encode, 0, 0, 0, Opcode_ae_movpa24x2_Slot_ae_slot0_encode
};
-xtensa_opcode_encode_fn Opcode_ae_truncp24a32x2_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_truncp24a32x2_encode_fns[] = {
Opcode_ae_truncp24a32x2_Slot_inst_encode, 0, 0, 0, Opcode_ae_truncp24a32x2_Slot_ae_slot0_encode
};
-xtensa_opcode_encode_fn Opcode_ae_cvta32p24_l_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_cvta32p24_l_encode_fns[] = {
Opcode_ae_cvta32p24_l_Slot_inst_encode, 0, 0, 0, Opcode_ae_cvta32p24_l_Slot_ae_slot0_encode
};
-xtensa_opcode_encode_fn Opcode_ae_cvta32p24_h_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_cvta32p24_h_encode_fns[] = {
Opcode_ae_cvta32p24_h_Slot_inst_encode, 0, 0, 0, Opcode_ae_cvta32p24_h_Slot_ae_slot0_encode
};
-xtensa_opcode_encode_fn Opcode_ae_cvtp24a16x2_ll_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_cvtp24a16x2_ll_encode_fns[] = {
Opcode_ae_cvtp24a16x2_ll_Slot_inst_encode, 0, 0, 0, Opcode_ae_cvtp24a16x2_ll_Slot_ae_slot0_encode
};
-xtensa_opcode_encode_fn Opcode_ae_cvtp24a16x2_lh_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_cvtp24a16x2_lh_encode_fns[] = {
Opcode_ae_cvtp24a16x2_lh_Slot_inst_encode, 0, 0, 0, Opcode_ae_cvtp24a16x2_lh_Slot_ae_slot0_encode
};
-xtensa_opcode_encode_fn Opcode_ae_cvtp24a16x2_hl_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_cvtp24a16x2_hl_encode_fns[] = {
Opcode_ae_cvtp24a16x2_hl_Slot_inst_encode, 0, 0, 0, Opcode_ae_cvtp24a16x2_hl_Slot_ae_slot0_encode
};
-xtensa_opcode_encode_fn Opcode_ae_cvtp24a16x2_hh_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_cvtp24a16x2_hh_encode_fns[] = {
Opcode_ae_cvtp24a16x2_hh_Slot_inst_encode, 0, 0, 0, Opcode_ae_cvtp24a16x2_hh_Slot_ae_slot0_encode
};
-xtensa_opcode_encode_fn Opcode_ae_truncp24q48x2_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_truncp24q48x2_encode_fns[] = {
0, 0, 0, Opcode_ae_truncp24q48x2_Slot_ae_slot1_encode, 0
};
-xtensa_opcode_encode_fn Opcode_ae_truncp16_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_truncp16_encode_fns[] = {
0, 0, 0, Opcode_ae_truncp16_Slot_ae_slot1_encode, 0
};
-xtensa_opcode_encode_fn Opcode_ae_roundsp24q48sym_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_roundsp24q48sym_encode_fns[] = {
0, 0, 0, Opcode_ae_roundsp24q48sym_Slot_ae_slot1_encode, 0
};
-xtensa_opcode_encode_fn Opcode_ae_roundsp24q48asym_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_roundsp24q48asym_encode_fns[] = {
0, 0, 0, Opcode_ae_roundsp24q48asym_Slot_ae_slot1_encode, 0
};
-xtensa_opcode_encode_fn Opcode_ae_roundsp16q48sym_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_roundsp16q48sym_encode_fns[] = {
0, 0, 0, Opcode_ae_roundsp16q48sym_Slot_ae_slot1_encode, 0
};
-xtensa_opcode_encode_fn Opcode_ae_roundsp16q48asym_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_roundsp16q48asym_encode_fns[] = {
0, 0, 0, Opcode_ae_roundsp16q48asym_Slot_ae_slot1_encode, 0
};
-xtensa_opcode_encode_fn Opcode_ae_roundsp16sym_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_roundsp16sym_encode_fns[] = {
0, 0, 0, Opcode_ae_roundsp16sym_Slot_ae_slot1_encode, 0
};
-xtensa_opcode_encode_fn Opcode_ae_roundsp16asym_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_roundsp16asym_encode_fns[] = {
0, 0, 0, Opcode_ae_roundsp16asym_Slot_ae_slot1_encode, 0
};
-xtensa_opcode_encode_fn Opcode_ae_zeroq56_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_zeroq56_encode_fns[] = {
0, 0, 0, Opcode_ae_zeroq56_Slot_ae_slot1_encode, 0
};
-xtensa_opcode_encode_fn Opcode_ae_movq56_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_movq56_encode_fns[] = {
Opcode_ae_movq56_Slot_inst_encode, 0, 0, Opcode_ae_movq56_Slot_ae_slot1_encode, Opcode_ae_movq56_Slot_ae_slot0_encode
};
-xtensa_opcode_encode_fn Opcode_ae_movtq56_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_movtq56_encode_fns[] = {
Opcode_ae_movtq56_Slot_inst_encode, 0, 0, 0, Opcode_ae_movtq56_Slot_ae_slot0_encode
};
-xtensa_opcode_encode_fn Opcode_ae_movfq56_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_movfq56_encode_fns[] = {
Opcode_ae_movfq56_Slot_inst_encode, 0, 0, 0, Opcode_ae_movfq56_Slot_ae_slot0_encode
};
-xtensa_opcode_encode_fn Opcode_ae_cvtq48a32s_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_cvtq48a32s_encode_fns[] = {
Opcode_ae_cvtq48a32s_Slot_inst_encode, 0, 0, 0, Opcode_ae_cvtq48a32s_Slot_ae_slot0_encode
};
-xtensa_opcode_encode_fn Opcode_ae_cvtq48p24s_l_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_cvtq48p24s_l_encode_fns[] = {
0, 0, 0, Opcode_ae_cvtq48p24s_l_Slot_ae_slot1_encode, 0
};
-xtensa_opcode_encode_fn Opcode_ae_cvtq48p24s_h_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_cvtq48p24s_h_encode_fns[] = {
0, 0, 0, Opcode_ae_cvtq48p24s_h_Slot_ae_slot1_encode, 0
};
-xtensa_opcode_encode_fn Opcode_ae_satq48s_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_satq48s_encode_fns[] = {
0, 0, 0, Opcode_ae_satq48s_Slot_ae_slot1_encode, 0
};
-xtensa_opcode_encode_fn Opcode_ae_truncq32_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_truncq32_encode_fns[] = {
0, 0, 0, Opcode_ae_truncq32_Slot_ae_slot1_encode, 0
};
-xtensa_opcode_encode_fn Opcode_ae_roundsq32sym_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_roundsq32sym_encode_fns[] = {
0, 0, 0, Opcode_ae_roundsq32sym_Slot_ae_slot1_encode, 0
};
-xtensa_opcode_encode_fn Opcode_ae_roundsq32asym_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_roundsq32asym_encode_fns[] = {
0, 0, 0, Opcode_ae_roundsq32asym_Slot_ae_slot1_encode, 0
};
-xtensa_opcode_encode_fn Opcode_ae_trunca32q48_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_trunca32q48_encode_fns[] = {
Opcode_ae_trunca32q48_Slot_inst_encode, 0, 0, 0, Opcode_ae_trunca32q48_Slot_ae_slot0_encode
};
-xtensa_opcode_encode_fn Opcode_ae_movap24s_l_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_movap24s_l_encode_fns[] = {
Opcode_ae_movap24s_l_Slot_inst_encode, 0, 0, 0, Opcode_ae_movap24s_l_Slot_ae_slot0_encode
};
-xtensa_opcode_encode_fn Opcode_ae_movap24s_h_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_movap24s_h_encode_fns[] = {
Opcode_ae_movap24s_h_Slot_inst_encode, 0, 0, 0, Opcode_ae_movap24s_h_Slot_ae_slot0_encode
};
-xtensa_opcode_encode_fn Opcode_ae_trunca16p24s_l_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_trunca16p24s_l_encode_fns[] = {
Opcode_ae_trunca16p24s_l_Slot_inst_encode, 0, 0, 0, Opcode_ae_trunca16p24s_l_Slot_ae_slot0_encode
};
-xtensa_opcode_encode_fn Opcode_ae_trunca16p24s_h_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_trunca16p24s_h_encode_fns[] = {
Opcode_ae_trunca16p24s_h_Slot_inst_encode, 0, 0, 0, Opcode_ae_trunca16p24s_h_Slot_ae_slot0_encode
};
-xtensa_opcode_encode_fn Opcode_ae_addp24_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_addp24_encode_fns[] = {
0, 0, 0, Opcode_ae_addp24_Slot_ae_slot1_encode, 0
};
-xtensa_opcode_encode_fn Opcode_ae_subp24_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_subp24_encode_fns[] = {
0, 0, 0, Opcode_ae_subp24_Slot_ae_slot1_encode, 0
};
-xtensa_opcode_encode_fn Opcode_ae_negp24_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_negp24_encode_fns[] = {
0, 0, 0, Opcode_ae_negp24_Slot_ae_slot1_encode, 0
};
-xtensa_opcode_encode_fn Opcode_ae_absp24_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_absp24_encode_fns[] = {
0, 0, 0, Opcode_ae_absp24_Slot_ae_slot1_encode, 0
};
-xtensa_opcode_encode_fn Opcode_ae_maxp24s_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_maxp24s_encode_fns[] = {
0, 0, 0, Opcode_ae_maxp24s_Slot_ae_slot1_encode, 0
};
-xtensa_opcode_encode_fn Opcode_ae_minp24s_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_minp24s_encode_fns[] = {
0, 0, 0, Opcode_ae_minp24s_Slot_ae_slot1_encode, 0
};
-xtensa_opcode_encode_fn Opcode_ae_maxbp24s_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_maxbp24s_encode_fns[] = {
0, 0, 0, Opcode_ae_maxbp24s_Slot_ae_slot1_encode, 0
};
-xtensa_opcode_encode_fn Opcode_ae_minbp24s_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_minbp24s_encode_fns[] = {
0, 0, 0, Opcode_ae_minbp24s_Slot_ae_slot1_encode, 0
};
-xtensa_opcode_encode_fn Opcode_ae_addsp24s_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_addsp24s_encode_fns[] = {
0, 0, 0, Opcode_ae_addsp24s_Slot_ae_slot1_encode, 0
};
-xtensa_opcode_encode_fn Opcode_ae_subsp24s_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_subsp24s_encode_fns[] = {
0, 0, 0, Opcode_ae_subsp24s_Slot_ae_slot1_encode, 0
};
-xtensa_opcode_encode_fn Opcode_ae_negsp24s_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_negsp24s_encode_fns[] = {
0, 0, 0, Opcode_ae_negsp24s_Slot_ae_slot1_encode, 0
};
-xtensa_opcode_encode_fn Opcode_ae_abssp24s_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_abssp24s_encode_fns[] = {
0, 0, 0, Opcode_ae_abssp24s_Slot_ae_slot1_encode, 0
};
-xtensa_opcode_encode_fn Opcode_ae_andp48_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_andp48_encode_fns[] = {
0, 0, 0, Opcode_ae_andp48_Slot_ae_slot1_encode, 0
};
-xtensa_opcode_encode_fn Opcode_ae_nandp48_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_nandp48_encode_fns[] = {
0, 0, 0, Opcode_ae_nandp48_Slot_ae_slot1_encode, 0
};
-xtensa_opcode_encode_fn Opcode_ae_orp48_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_orp48_encode_fns[] = {
0, 0, 0, Opcode_ae_orp48_Slot_ae_slot1_encode, 0
};
-xtensa_opcode_encode_fn Opcode_ae_xorp48_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_xorp48_encode_fns[] = {
0, 0, 0, Opcode_ae_xorp48_Slot_ae_slot1_encode, 0
};
-xtensa_opcode_encode_fn Opcode_ae_ltp24s_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_ltp24s_encode_fns[] = {
0, 0, 0, Opcode_ae_ltp24s_Slot_ae_slot1_encode, 0
};
-xtensa_opcode_encode_fn Opcode_ae_lep24s_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_lep24s_encode_fns[] = {
0, 0, 0, Opcode_ae_lep24s_Slot_ae_slot1_encode, 0
};
-xtensa_opcode_encode_fn Opcode_ae_eqp24_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_eqp24_encode_fns[] = {
0, 0, 0, Opcode_ae_eqp24_Slot_ae_slot1_encode, 0
};
-xtensa_opcode_encode_fn Opcode_ae_addq56_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_addq56_encode_fns[] = {
0, 0, 0, Opcode_ae_addq56_Slot_ae_slot1_encode, 0
};
-xtensa_opcode_encode_fn Opcode_ae_subq56_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_subq56_encode_fns[] = {
0, 0, 0, Opcode_ae_subq56_Slot_ae_slot1_encode, 0
};
-xtensa_opcode_encode_fn Opcode_ae_negq56_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_negq56_encode_fns[] = {
0, 0, 0, Opcode_ae_negq56_Slot_ae_slot1_encode, 0
};
-xtensa_opcode_encode_fn Opcode_ae_absq56_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_absq56_encode_fns[] = {
0, 0, 0, Opcode_ae_absq56_Slot_ae_slot1_encode, 0
};
-xtensa_opcode_encode_fn Opcode_ae_maxq56s_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_maxq56s_encode_fns[] = {
0, 0, 0, Opcode_ae_maxq56s_Slot_ae_slot1_encode, 0
};
-xtensa_opcode_encode_fn Opcode_ae_minq56s_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_minq56s_encode_fns[] = {
0, 0, 0, Opcode_ae_minq56s_Slot_ae_slot1_encode, 0
};
-xtensa_opcode_encode_fn Opcode_ae_maxbq56s_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_maxbq56s_encode_fns[] = {
0, 0, 0, Opcode_ae_maxbq56s_Slot_ae_slot1_encode, 0
};
-xtensa_opcode_encode_fn Opcode_ae_minbq56s_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_minbq56s_encode_fns[] = {
0, 0, 0, Opcode_ae_minbq56s_Slot_ae_slot1_encode, 0
};
-xtensa_opcode_encode_fn Opcode_ae_addsq56s_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_addsq56s_encode_fns[] = {
0, 0, 0, Opcode_ae_addsq56s_Slot_ae_slot1_encode, 0
};
-xtensa_opcode_encode_fn Opcode_ae_subsq56s_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_subsq56s_encode_fns[] = {
0, 0, 0, Opcode_ae_subsq56s_Slot_ae_slot1_encode, 0
};
-xtensa_opcode_encode_fn Opcode_ae_negsq56s_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_negsq56s_encode_fns[] = {
0, 0, 0, Opcode_ae_negsq56s_Slot_ae_slot1_encode, 0
};
-xtensa_opcode_encode_fn Opcode_ae_abssq56s_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_abssq56s_encode_fns[] = {
0, 0, 0, Opcode_ae_abssq56s_Slot_ae_slot1_encode, 0
};
-xtensa_opcode_encode_fn Opcode_ae_andq56_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_andq56_encode_fns[] = {
0, 0, 0, Opcode_ae_andq56_Slot_ae_slot1_encode, 0
};
-xtensa_opcode_encode_fn Opcode_ae_nandq56_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_nandq56_encode_fns[] = {
0, 0, 0, Opcode_ae_nandq56_Slot_ae_slot1_encode, 0
};
-xtensa_opcode_encode_fn Opcode_ae_orq56_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_orq56_encode_fns[] = {
0, 0, 0, Opcode_ae_orq56_Slot_ae_slot1_encode, 0
};
-xtensa_opcode_encode_fn Opcode_ae_xorq56_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_xorq56_encode_fns[] = {
0, 0, 0, Opcode_ae_xorq56_Slot_ae_slot1_encode, 0
};
-xtensa_opcode_encode_fn Opcode_ae_sllip24_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_sllip24_encode_fns[] = {
0, 0, 0, Opcode_ae_sllip24_Slot_ae_slot1_encode, 0
};
-xtensa_opcode_encode_fn Opcode_ae_srlip24_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_srlip24_encode_fns[] = {
0, 0, 0, Opcode_ae_srlip24_Slot_ae_slot1_encode, 0
};
-xtensa_opcode_encode_fn Opcode_ae_sraip24_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_sraip24_encode_fns[] = {
0, 0, 0, Opcode_ae_sraip24_Slot_ae_slot1_encode, 0
};
-xtensa_opcode_encode_fn Opcode_ae_sllsp24_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_sllsp24_encode_fns[] = {
0, 0, 0, Opcode_ae_sllsp24_Slot_ae_slot1_encode, 0
};
-xtensa_opcode_encode_fn Opcode_ae_srlsp24_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_srlsp24_encode_fns[] = {
0, 0, 0, Opcode_ae_srlsp24_Slot_ae_slot1_encode, 0
};
-xtensa_opcode_encode_fn Opcode_ae_srasp24_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_srasp24_encode_fns[] = {
0, 0, 0, Opcode_ae_srasp24_Slot_ae_slot1_encode, 0
};
-xtensa_opcode_encode_fn Opcode_ae_sllisp24s_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_sllisp24s_encode_fns[] = {
0, 0, 0, Opcode_ae_sllisp24s_Slot_ae_slot1_encode, 0
};
-xtensa_opcode_encode_fn Opcode_ae_sllssp24s_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_sllssp24s_encode_fns[] = {
0, 0, 0, Opcode_ae_sllssp24s_Slot_ae_slot1_encode, 0
};
-xtensa_opcode_encode_fn Opcode_ae_slliq56_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_slliq56_encode_fns[] = {
Opcode_ae_slliq56_Slot_inst_encode, 0, 0, 0, Opcode_ae_slliq56_Slot_ae_slot0_encode
};
-xtensa_opcode_encode_fn Opcode_ae_srliq56_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_srliq56_encode_fns[] = {
Opcode_ae_srliq56_Slot_inst_encode, 0, 0, 0, Opcode_ae_srliq56_Slot_ae_slot0_encode
};
-xtensa_opcode_encode_fn Opcode_ae_sraiq56_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_sraiq56_encode_fns[] = {
Opcode_ae_sraiq56_Slot_inst_encode, 0, 0, 0, Opcode_ae_sraiq56_Slot_ae_slot0_encode
};
-xtensa_opcode_encode_fn Opcode_ae_sllsq56_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_sllsq56_encode_fns[] = {
Opcode_ae_sllsq56_Slot_inst_encode, 0, 0, 0, Opcode_ae_sllsq56_Slot_ae_slot0_encode
};
-xtensa_opcode_encode_fn Opcode_ae_srlsq56_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_srlsq56_encode_fns[] = {
Opcode_ae_srlsq56_Slot_inst_encode, 0, 0, 0, Opcode_ae_srlsq56_Slot_ae_slot0_encode
};
-xtensa_opcode_encode_fn Opcode_ae_srasq56_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_srasq56_encode_fns[] = {
Opcode_ae_srasq56_Slot_inst_encode, 0, 0, 0, Opcode_ae_srasq56_Slot_ae_slot0_encode
};
-xtensa_opcode_encode_fn Opcode_ae_sllaq56_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_sllaq56_encode_fns[] = {
Opcode_ae_sllaq56_Slot_inst_encode, 0, 0, 0, Opcode_ae_sllaq56_Slot_ae_slot0_encode
};
-xtensa_opcode_encode_fn Opcode_ae_srlaq56_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_srlaq56_encode_fns[] = {
Opcode_ae_srlaq56_Slot_inst_encode, 0, 0, 0, Opcode_ae_srlaq56_Slot_ae_slot0_encode
};
-xtensa_opcode_encode_fn Opcode_ae_sraaq56_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_sraaq56_encode_fns[] = {
Opcode_ae_sraaq56_Slot_inst_encode, 0, 0, 0, Opcode_ae_sraaq56_Slot_ae_slot0_encode
};
-xtensa_opcode_encode_fn Opcode_ae_sllisq56s_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_sllisq56s_encode_fns[] = {
Opcode_ae_sllisq56s_Slot_inst_encode, 0, 0, 0, Opcode_ae_sllisq56s_Slot_ae_slot0_encode
};
-xtensa_opcode_encode_fn Opcode_ae_sllssq56s_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_sllssq56s_encode_fns[] = {
Opcode_ae_sllssq56s_Slot_inst_encode, 0, 0, 0, Opcode_ae_sllssq56s_Slot_ae_slot0_encode
};
-xtensa_opcode_encode_fn Opcode_ae_sllasq56s_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_sllasq56s_encode_fns[] = {
Opcode_ae_sllasq56s_Slot_inst_encode, 0, 0, 0, Opcode_ae_sllasq56s_Slot_ae_slot0_encode
};
-xtensa_opcode_encode_fn Opcode_ae_ltq56s_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_ltq56s_encode_fns[] = {
0, 0, 0, Opcode_ae_ltq56s_Slot_ae_slot1_encode, 0
};
-xtensa_opcode_encode_fn Opcode_ae_leq56s_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_leq56s_encode_fns[] = {
0, 0, 0, Opcode_ae_leq56s_Slot_ae_slot1_encode, 0
};
-xtensa_opcode_encode_fn Opcode_ae_eqq56_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_eqq56_encode_fns[] = {
0, 0, 0, Opcode_ae_eqq56_Slot_ae_slot1_encode, 0
};
-xtensa_opcode_encode_fn Opcode_ae_nsaq56s_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_nsaq56s_encode_fns[] = {
Opcode_ae_nsaq56s_Slot_inst_encode, 0, 0, 0, Opcode_ae_nsaq56s_Slot_ae_slot0_encode
};
-xtensa_opcode_encode_fn Opcode_ae_mulfs32p16s_ll_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_mulfs32p16s_ll_encode_fns[] = {
0, 0, 0, Opcode_ae_mulfs32p16s_ll_Slot_ae_slot1_encode, 0
};
-xtensa_opcode_encode_fn Opcode_ae_mulfp24s_ll_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_mulfp24s_ll_encode_fns[] = {
0, 0, 0, Opcode_ae_mulfp24s_ll_Slot_ae_slot1_encode, 0
};
-xtensa_opcode_encode_fn Opcode_ae_mulp24s_ll_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_mulp24s_ll_encode_fns[] = {
0, 0, 0, Opcode_ae_mulp24s_ll_Slot_ae_slot1_encode, 0
};
-xtensa_opcode_encode_fn Opcode_ae_mulfs32p16s_lh_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_mulfs32p16s_lh_encode_fns[] = {
0, 0, 0, Opcode_ae_mulfs32p16s_lh_Slot_ae_slot1_encode, 0
};
-xtensa_opcode_encode_fn Opcode_ae_mulfp24s_lh_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_mulfp24s_lh_encode_fns[] = {
0, 0, 0, Opcode_ae_mulfp24s_lh_Slot_ae_slot1_encode, 0
};
-xtensa_opcode_encode_fn Opcode_ae_mulp24s_lh_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_mulp24s_lh_encode_fns[] = {
0, 0, 0, Opcode_ae_mulp24s_lh_Slot_ae_slot1_encode, 0
};
-xtensa_opcode_encode_fn Opcode_ae_mulfs32p16s_hl_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_mulfs32p16s_hl_encode_fns[] = {
0, 0, 0, Opcode_ae_mulfs32p16s_hl_Slot_ae_slot1_encode, 0
};
-xtensa_opcode_encode_fn Opcode_ae_mulfp24s_hl_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_mulfp24s_hl_encode_fns[] = {
0, 0, 0, Opcode_ae_mulfp24s_hl_Slot_ae_slot1_encode, 0
};
-xtensa_opcode_encode_fn Opcode_ae_mulp24s_hl_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_mulp24s_hl_encode_fns[] = {
0, 0, 0, Opcode_ae_mulp24s_hl_Slot_ae_slot1_encode, 0
};
-xtensa_opcode_encode_fn Opcode_ae_mulfs32p16s_hh_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_mulfs32p16s_hh_encode_fns[] = {
0, 0, 0, Opcode_ae_mulfs32p16s_hh_Slot_ae_slot1_encode, 0
};
-xtensa_opcode_encode_fn Opcode_ae_mulfp24s_hh_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_mulfp24s_hh_encode_fns[] = {
0, 0, 0, Opcode_ae_mulfp24s_hh_Slot_ae_slot1_encode, 0
};
-xtensa_opcode_encode_fn Opcode_ae_mulp24s_hh_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_mulp24s_hh_encode_fns[] = {
0, 0, 0, Opcode_ae_mulp24s_hh_Slot_ae_slot1_encode, 0
};
-xtensa_opcode_encode_fn Opcode_ae_mulafs32p16s_ll_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_mulafs32p16s_ll_encode_fns[] = {
0, 0, 0, Opcode_ae_mulafs32p16s_ll_Slot_ae_slot1_encode, 0
};
-xtensa_opcode_encode_fn Opcode_ae_mulafp24s_ll_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_mulafp24s_ll_encode_fns[] = {
0, 0, 0, Opcode_ae_mulafp24s_ll_Slot_ae_slot1_encode, 0
};
-xtensa_opcode_encode_fn Opcode_ae_mulap24s_ll_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_mulap24s_ll_encode_fns[] = {
0, 0, 0, Opcode_ae_mulap24s_ll_Slot_ae_slot1_encode, 0
};
-xtensa_opcode_encode_fn Opcode_ae_mulafs32p16s_lh_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_mulafs32p16s_lh_encode_fns[] = {
0, 0, 0, Opcode_ae_mulafs32p16s_lh_Slot_ae_slot1_encode, 0
};
-xtensa_opcode_encode_fn Opcode_ae_mulafp24s_lh_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_mulafp24s_lh_encode_fns[] = {
0, 0, 0, Opcode_ae_mulafp24s_lh_Slot_ae_slot1_encode, 0
};
-xtensa_opcode_encode_fn Opcode_ae_mulap24s_lh_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_mulap24s_lh_encode_fns[] = {
0, 0, 0, Opcode_ae_mulap24s_lh_Slot_ae_slot1_encode, 0
};
-xtensa_opcode_encode_fn Opcode_ae_mulafs32p16s_hl_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_mulafs32p16s_hl_encode_fns[] = {
0, 0, 0, Opcode_ae_mulafs32p16s_hl_Slot_ae_slot1_encode, 0
};
-xtensa_opcode_encode_fn Opcode_ae_mulafp24s_hl_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_mulafp24s_hl_encode_fns[] = {
0, 0, 0, Opcode_ae_mulafp24s_hl_Slot_ae_slot1_encode, 0
};
-xtensa_opcode_encode_fn Opcode_ae_mulap24s_hl_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_mulap24s_hl_encode_fns[] = {
0, 0, 0, Opcode_ae_mulap24s_hl_Slot_ae_slot1_encode, 0
};
-xtensa_opcode_encode_fn Opcode_ae_mulafs32p16s_hh_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_mulafs32p16s_hh_encode_fns[] = {
0, 0, 0, Opcode_ae_mulafs32p16s_hh_Slot_ae_slot1_encode, 0
};
-xtensa_opcode_encode_fn Opcode_ae_mulafp24s_hh_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_mulafp24s_hh_encode_fns[] = {
0, 0, 0, Opcode_ae_mulafp24s_hh_Slot_ae_slot1_encode, 0
};
-xtensa_opcode_encode_fn Opcode_ae_mulap24s_hh_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_mulap24s_hh_encode_fns[] = {
0, 0, 0, Opcode_ae_mulap24s_hh_Slot_ae_slot1_encode, 0
};
-xtensa_opcode_encode_fn Opcode_ae_mulsfs32p16s_ll_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_mulsfs32p16s_ll_encode_fns[] = {
0, 0, 0, Opcode_ae_mulsfs32p16s_ll_Slot_ae_slot1_encode, 0
};
-xtensa_opcode_encode_fn Opcode_ae_mulsfp24s_ll_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_mulsfp24s_ll_encode_fns[] = {
0, 0, 0, Opcode_ae_mulsfp24s_ll_Slot_ae_slot1_encode, 0
};
-xtensa_opcode_encode_fn Opcode_ae_mulsp24s_ll_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_mulsp24s_ll_encode_fns[] = {
0, 0, 0, Opcode_ae_mulsp24s_ll_Slot_ae_slot1_encode, 0
};
-xtensa_opcode_encode_fn Opcode_ae_mulsfs32p16s_lh_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_mulsfs32p16s_lh_encode_fns[] = {
0, 0, 0, Opcode_ae_mulsfs32p16s_lh_Slot_ae_slot1_encode, 0
};
-xtensa_opcode_encode_fn Opcode_ae_mulsfp24s_lh_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_mulsfp24s_lh_encode_fns[] = {
0, 0, 0, Opcode_ae_mulsfp24s_lh_Slot_ae_slot1_encode, 0
};
-xtensa_opcode_encode_fn Opcode_ae_mulsp24s_lh_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_mulsp24s_lh_encode_fns[] = {
0, 0, 0, Opcode_ae_mulsp24s_lh_Slot_ae_slot1_encode, 0
};
-xtensa_opcode_encode_fn Opcode_ae_mulsfs32p16s_hl_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_mulsfs32p16s_hl_encode_fns[] = {
0, 0, 0, Opcode_ae_mulsfs32p16s_hl_Slot_ae_slot1_encode, 0
};
-xtensa_opcode_encode_fn Opcode_ae_mulsfp24s_hl_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_mulsfp24s_hl_encode_fns[] = {
0, 0, 0, Opcode_ae_mulsfp24s_hl_Slot_ae_slot1_encode, 0
};
-xtensa_opcode_encode_fn Opcode_ae_mulsp24s_hl_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_mulsp24s_hl_encode_fns[] = {
0, 0, 0, Opcode_ae_mulsp24s_hl_Slot_ae_slot1_encode, 0
};
-xtensa_opcode_encode_fn Opcode_ae_mulsfs32p16s_hh_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_mulsfs32p16s_hh_encode_fns[] = {
0, 0, 0, Opcode_ae_mulsfs32p16s_hh_Slot_ae_slot1_encode, 0
};
-xtensa_opcode_encode_fn Opcode_ae_mulsfp24s_hh_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_mulsfp24s_hh_encode_fns[] = {
0, 0, 0, Opcode_ae_mulsfp24s_hh_Slot_ae_slot1_encode, 0
};
-xtensa_opcode_encode_fn Opcode_ae_mulsp24s_hh_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_mulsp24s_hh_encode_fns[] = {
0, 0, 0, Opcode_ae_mulsp24s_hh_Slot_ae_slot1_encode, 0
};
-xtensa_opcode_encode_fn Opcode_ae_mulafs56p24s_ll_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_mulafs56p24s_ll_encode_fns[] = {
0, 0, 0, Opcode_ae_mulafs56p24s_ll_Slot_ae_slot1_encode, 0
};
-xtensa_opcode_encode_fn Opcode_ae_mulas56p24s_ll_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_mulas56p24s_ll_encode_fns[] = {
0, 0, 0, Opcode_ae_mulas56p24s_ll_Slot_ae_slot1_encode, 0
};
-xtensa_opcode_encode_fn Opcode_ae_mulafs56p24s_lh_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_mulafs56p24s_lh_encode_fns[] = {
0, 0, 0, Opcode_ae_mulafs56p24s_lh_Slot_ae_slot1_encode, 0
};
-xtensa_opcode_encode_fn Opcode_ae_mulas56p24s_lh_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_mulas56p24s_lh_encode_fns[] = {
0, 0, 0, Opcode_ae_mulas56p24s_lh_Slot_ae_slot1_encode, 0
};
-xtensa_opcode_encode_fn Opcode_ae_mulafs56p24s_hl_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_mulafs56p24s_hl_encode_fns[] = {
0, 0, 0, Opcode_ae_mulafs56p24s_hl_Slot_ae_slot1_encode, 0
};
-xtensa_opcode_encode_fn Opcode_ae_mulas56p24s_hl_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_mulas56p24s_hl_encode_fns[] = {
0, 0, 0, Opcode_ae_mulas56p24s_hl_Slot_ae_slot1_encode, 0
};
-xtensa_opcode_encode_fn Opcode_ae_mulafs56p24s_hh_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_mulafs56p24s_hh_encode_fns[] = {
0, 0, 0, Opcode_ae_mulafs56p24s_hh_Slot_ae_slot1_encode, 0
};
-xtensa_opcode_encode_fn Opcode_ae_mulas56p24s_hh_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_mulas56p24s_hh_encode_fns[] = {
0, 0, 0, Opcode_ae_mulas56p24s_hh_Slot_ae_slot1_encode, 0
};
-xtensa_opcode_encode_fn Opcode_ae_mulsfs56p24s_ll_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_mulsfs56p24s_ll_encode_fns[] = {
0, 0, 0, Opcode_ae_mulsfs56p24s_ll_Slot_ae_slot1_encode, 0
};
-xtensa_opcode_encode_fn Opcode_ae_mulss56p24s_ll_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_mulss56p24s_ll_encode_fns[] = {
0, 0, 0, Opcode_ae_mulss56p24s_ll_Slot_ae_slot1_encode, 0
};
-xtensa_opcode_encode_fn Opcode_ae_mulsfs56p24s_lh_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_mulsfs56p24s_lh_encode_fns[] = {
0, 0, 0, Opcode_ae_mulsfs56p24s_lh_Slot_ae_slot1_encode, 0
};
-xtensa_opcode_encode_fn Opcode_ae_mulss56p24s_lh_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_mulss56p24s_lh_encode_fns[] = {
0, 0, 0, Opcode_ae_mulss56p24s_lh_Slot_ae_slot1_encode, 0
};
-xtensa_opcode_encode_fn Opcode_ae_mulsfs56p24s_hl_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_mulsfs56p24s_hl_encode_fns[] = {
0, 0, 0, Opcode_ae_mulsfs56p24s_hl_Slot_ae_slot1_encode, 0
};
-xtensa_opcode_encode_fn Opcode_ae_mulss56p24s_hl_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_mulss56p24s_hl_encode_fns[] = {
0, 0, 0, Opcode_ae_mulss56p24s_hl_Slot_ae_slot1_encode, 0
};
-xtensa_opcode_encode_fn Opcode_ae_mulsfs56p24s_hh_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_mulsfs56p24s_hh_encode_fns[] = {
0, 0, 0, Opcode_ae_mulsfs56p24s_hh_Slot_ae_slot1_encode, 0
};
-xtensa_opcode_encode_fn Opcode_ae_mulss56p24s_hh_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_mulss56p24s_hh_encode_fns[] = {
0, 0, 0, Opcode_ae_mulss56p24s_hh_Slot_ae_slot1_encode, 0
};
-xtensa_opcode_encode_fn Opcode_ae_mulfq32sp16s_l_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_mulfq32sp16s_l_encode_fns[] = {
0, 0, 0, Opcode_ae_mulfq32sp16s_l_Slot_ae_slot1_encode, 0
};
-xtensa_opcode_encode_fn Opcode_ae_mulfq32sp16s_h_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_mulfq32sp16s_h_encode_fns[] = {
0, 0, 0, Opcode_ae_mulfq32sp16s_h_Slot_ae_slot1_encode, 0
};
-xtensa_opcode_encode_fn Opcode_ae_mulfq32sp16u_l_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_mulfq32sp16u_l_encode_fns[] = {
0, 0, 0, Opcode_ae_mulfq32sp16u_l_Slot_ae_slot1_encode, 0
};
-xtensa_opcode_encode_fn Opcode_ae_mulfq32sp16u_h_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_mulfq32sp16u_h_encode_fns[] = {
0, 0, 0, Opcode_ae_mulfq32sp16u_h_Slot_ae_slot1_encode, 0
};
-xtensa_opcode_encode_fn Opcode_ae_mulq32sp16s_l_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_mulq32sp16s_l_encode_fns[] = {
0, 0, 0, Opcode_ae_mulq32sp16s_l_Slot_ae_slot1_encode, 0
};
-xtensa_opcode_encode_fn Opcode_ae_mulq32sp16s_h_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_mulq32sp16s_h_encode_fns[] = {
0, 0, 0, Opcode_ae_mulq32sp16s_h_Slot_ae_slot1_encode, 0
};
-xtensa_opcode_encode_fn Opcode_ae_mulq32sp16u_l_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_mulq32sp16u_l_encode_fns[] = {
0, 0, 0, Opcode_ae_mulq32sp16u_l_Slot_ae_slot1_encode, 0
};
-xtensa_opcode_encode_fn Opcode_ae_mulq32sp16u_h_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_mulq32sp16u_h_encode_fns[] = {
0, 0, 0, Opcode_ae_mulq32sp16u_h_Slot_ae_slot1_encode, 0
};
-xtensa_opcode_encode_fn Opcode_ae_mulafq32sp16s_l_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_mulafq32sp16s_l_encode_fns[] = {
0, 0, 0, Opcode_ae_mulafq32sp16s_l_Slot_ae_slot1_encode, 0
};
-xtensa_opcode_encode_fn Opcode_ae_mulafq32sp16s_h_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_mulafq32sp16s_h_encode_fns[] = {
0, 0, 0, Opcode_ae_mulafq32sp16s_h_Slot_ae_slot1_encode, 0
};
-xtensa_opcode_encode_fn Opcode_ae_mulafq32sp16u_l_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_mulafq32sp16u_l_encode_fns[] = {
0, 0, 0, Opcode_ae_mulafq32sp16u_l_Slot_ae_slot1_encode, 0
};
-xtensa_opcode_encode_fn Opcode_ae_mulafq32sp16u_h_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_mulafq32sp16u_h_encode_fns[] = {
0, 0, 0, Opcode_ae_mulafq32sp16u_h_Slot_ae_slot1_encode, 0
};
-xtensa_opcode_encode_fn Opcode_ae_mulaq32sp16s_l_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_mulaq32sp16s_l_encode_fns[] = {
0, 0, 0, Opcode_ae_mulaq32sp16s_l_Slot_ae_slot1_encode, 0
};
-xtensa_opcode_encode_fn Opcode_ae_mulaq32sp16s_h_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_mulaq32sp16s_h_encode_fns[] = {
0, 0, 0, Opcode_ae_mulaq32sp16s_h_Slot_ae_slot1_encode, 0
};
-xtensa_opcode_encode_fn Opcode_ae_mulaq32sp16u_l_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_mulaq32sp16u_l_encode_fns[] = {
0, 0, 0, Opcode_ae_mulaq32sp16u_l_Slot_ae_slot1_encode, 0
};
-xtensa_opcode_encode_fn Opcode_ae_mulaq32sp16u_h_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_mulaq32sp16u_h_encode_fns[] = {
0, 0, 0, Opcode_ae_mulaq32sp16u_h_Slot_ae_slot1_encode, 0
};
-xtensa_opcode_encode_fn Opcode_ae_mulsfq32sp16s_l_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_mulsfq32sp16s_l_encode_fns[] = {
0, 0, 0, Opcode_ae_mulsfq32sp16s_l_Slot_ae_slot1_encode, 0
};
-xtensa_opcode_encode_fn Opcode_ae_mulsfq32sp16s_h_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_mulsfq32sp16s_h_encode_fns[] = {
0, 0, 0, Opcode_ae_mulsfq32sp16s_h_Slot_ae_slot1_encode, 0
};
-xtensa_opcode_encode_fn Opcode_ae_mulsfq32sp16u_l_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_mulsfq32sp16u_l_encode_fns[] = {
0, 0, 0, Opcode_ae_mulsfq32sp16u_l_Slot_ae_slot1_encode, 0
};
-xtensa_opcode_encode_fn Opcode_ae_mulsfq32sp16u_h_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_mulsfq32sp16u_h_encode_fns[] = {
0, 0, 0, Opcode_ae_mulsfq32sp16u_h_Slot_ae_slot1_encode, 0
};
-xtensa_opcode_encode_fn Opcode_ae_mulsq32sp16s_l_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_mulsq32sp16s_l_encode_fns[] = {
0, 0, 0, Opcode_ae_mulsq32sp16s_l_Slot_ae_slot1_encode, 0
};
-xtensa_opcode_encode_fn Opcode_ae_mulsq32sp16s_h_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_mulsq32sp16s_h_encode_fns[] = {
0, 0, 0, Opcode_ae_mulsq32sp16s_h_Slot_ae_slot1_encode, 0
};
-xtensa_opcode_encode_fn Opcode_ae_mulsq32sp16u_l_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_mulsq32sp16u_l_encode_fns[] = {
0, 0, 0, Opcode_ae_mulsq32sp16u_l_Slot_ae_slot1_encode, 0
};
-xtensa_opcode_encode_fn Opcode_ae_mulsq32sp16u_h_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_mulsq32sp16u_h_encode_fns[] = {
0, 0, 0, Opcode_ae_mulsq32sp16u_h_Slot_ae_slot1_encode, 0
};
-xtensa_opcode_encode_fn Opcode_ae_mulzaaq32sp16s_ll_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_mulzaaq32sp16s_ll_encode_fns[] = {
0, 0, 0, Opcode_ae_mulzaaq32sp16s_ll_Slot_ae_slot1_encode, 0
};
-xtensa_opcode_encode_fn Opcode_ae_mulzaafq32sp16s_ll_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_mulzaafq32sp16s_ll_encode_fns[] = {
0, 0, 0, Opcode_ae_mulzaafq32sp16s_ll_Slot_ae_slot1_encode, 0
};
-xtensa_opcode_encode_fn Opcode_ae_mulzaaq32sp16u_ll_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_mulzaaq32sp16u_ll_encode_fns[] = {
0, 0, 0, Opcode_ae_mulzaaq32sp16u_ll_Slot_ae_slot1_encode, 0
};
-xtensa_opcode_encode_fn Opcode_ae_mulzaafq32sp16u_ll_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_mulzaafq32sp16u_ll_encode_fns[] = {
0, 0, 0, Opcode_ae_mulzaafq32sp16u_ll_Slot_ae_slot1_encode, 0
};
-xtensa_opcode_encode_fn Opcode_ae_mulzaaq32sp16s_hh_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_mulzaaq32sp16s_hh_encode_fns[] = {
0, 0, 0, Opcode_ae_mulzaaq32sp16s_hh_Slot_ae_slot1_encode, 0
};
-xtensa_opcode_encode_fn Opcode_ae_mulzaafq32sp16s_hh_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_mulzaafq32sp16s_hh_encode_fns[] = {
0, 0, 0, Opcode_ae_mulzaafq32sp16s_hh_Slot_ae_slot1_encode, 0
};
-xtensa_opcode_encode_fn Opcode_ae_mulzaaq32sp16u_hh_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_mulzaaq32sp16u_hh_encode_fns[] = {
0, 0, 0, Opcode_ae_mulzaaq32sp16u_hh_Slot_ae_slot1_encode, 0
};
-xtensa_opcode_encode_fn Opcode_ae_mulzaafq32sp16u_hh_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_mulzaafq32sp16u_hh_encode_fns[] = {
0, 0, 0, Opcode_ae_mulzaafq32sp16u_hh_Slot_ae_slot1_encode, 0
};
-xtensa_opcode_encode_fn Opcode_ae_mulzaaq32sp16s_lh_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_mulzaaq32sp16s_lh_encode_fns[] = {
0, 0, 0, Opcode_ae_mulzaaq32sp16s_lh_Slot_ae_slot1_encode, 0
};
-xtensa_opcode_encode_fn Opcode_ae_mulzaafq32sp16s_lh_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_mulzaafq32sp16s_lh_encode_fns[] = {
0, 0, 0, Opcode_ae_mulzaafq32sp16s_lh_Slot_ae_slot1_encode, 0
};
-xtensa_opcode_encode_fn Opcode_ae_mulzaaq32sp16u_lh_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_mulzaaq32sp16u_lh_encode_fns[] = {
0, 0, 0, Opcode_ae_mulzaaq32sp16u_lh_Slot_ae_slot1_encode, 0
};
-xtensa_opcode_encode_fn Opcode_ae_mulzaafq32sp16u_lh_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_mulzaafq32sp16u_lh_encode_fns[] = {
0, 0, 0, Opcode_ae_mulzaafq32sp16u_lh_Slot_ae_slot1_encode, 0
};
-xtensa_opcode_encode_fn Opcode_ae_mulzasq32sp16s_ll_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_mulzasq32sp16s_ll_encode_fns[] = {
0, 0, 0, Opcode_ae_mulzasq32sp16s_ll_Slot_ae_slot1_encode, 0
};
-xtensa_opcode_encode_fn Opcode_ae_mulzasfq32sp16s_ll_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_mulzasfq32sp16s_ll_encode_fns[] = {
0, 0, 0, Opcode_ae_mulzasfq32sp16s_ll_Slot_ae_slot1_encode, 0
};
-xtensa_opcode_encode_fn Opcode_ae_mulzasq32sp16u_ll_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_mulzasq32sp16u_ll_encode_fns[] = {
0, 0, 0, Opcode_ae_mulzasq32sp16u_ll_Slot_ae_slot1_encode, 0
};
-xtensa_opcode_encode_fn Opcode_ae_mulzasfq32sp16u_ll_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_mulzasfq32sp16u_ll_encode_fns[] = {
0, 0, 0, Opcode_ae_mulzasfq32sp16u_ll_Slot_ae_slot1_encode, 0
};
-xtensa_opcode_encode_fn Opcode_ae_mulzasq32sp16s_hh_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_mulzasq32sp16s_hh_encode_fns[] = {
0, 0, 0, Opcode_ae_mulzasq32sp16s_hh_Slot_ae_slot1_encode, 0
};
-xtensa_opcode_encode_fn Opcode_ae_mulzasfq32sp16s_hh_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_mulzasfq32sp16s_hh_encode_fns[] = {
0, 0, 0, Opcode_ae_mulzasfq32sp16s_hh_Slot_ae_slot1_encode, 0
};
-xtensa_opcode_encode_fn Opcode_ae_mulzasq32sp16u_hh_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_mulzasq32sp16u_hh_encode_fns[] = {
0, 0, 0, Opcode_ae_mulzasq32sp16u_hh_Slot_ae_slot1_encode, 0
};
-xtensa_opcode_encode_fn Opcode_ae_mulzasfq32sp16u_hh_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_mulzasfq32sp16u_hh_encode_fns[] = {
0, 0, 0, Opcode_ae_mulzasfq32sp16u_hh_Slot_ae_slot1_encode, 0
};
-xtensa_opcode_encode_fn Opcode_ae_mulzasq32sp16s_lh_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_mulzasq32sp16s_lh_encode_fns[] = {
0, 0, 0, Opcode_ae_mulzasq32sp16s_lh_Slot_ae_slot1_encode, 0
};
-xtensa_opcode_encode_fn Opcode_ae_mulzasfq32sp16s_lh_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_mulzasfq32sp16s_lh_encode_fns[] = {
0, 0, 0, Opcode_ae_mulzasfq32sp16s_lh_Slot_ae_slot1_encode, 0
};
-xtensa_opcode_encode_fn Opcode_ae_mulzasq32sp16u_lh_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_mulzasq32sp16u_lh_encode_fns[] = {
0, 0, 0, Opcode_ae_mulzasq32sp16u_lh_Slot_ae_slot1_encode, 0
};
-xtensa_opcode_encode_fn Opcode_ae_mulzasfq32sp16u_lh_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_mulzasfq32sp16u_lh_encode_fns[] = {
0, 0, 0, Opcode_ae_mulzasfq32sp16u_lh_Slot_ae_slot1_encode, 0
};
-xtensa_opcode_encode_fn Opcode_ae_mulzsaq32sp16s_ll_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_mulzsaq32sp16s_ll_encode_fns[] = {
0, 0, 0, Opcode_ae_mulzsaq32sp16s_ll_Slot_ae_slot1_encode, 0
};
-xtensa_opcode_encode_fn Opcode_ae_mulzsafq32sp16s_ll_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_mulzsafq32sp16s_ll_encode_fns[] = {
0, 0, 0, Opcode_ae_mulzsafq32sp16s_ll_Slot_ae_slot1_encode, 0
};
-xtensa_opcode_encode_fn Opcode_ae_mulzsaq32sp16u_ll_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_mulzsaq32sp16u_ll_encode_fns[] = {
0, 0, 0, Opcode_ae_mulzsaq32sp16u_ll_Slot_ae_slot1_encode, 0
};
-xtensa_opcode_encode_fn Opcode_ae_mulzsafq32sp16u_ll_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_mulzsafq32sp16u_ll_encode_fns[] = {
0, 0, 0, Opcode_ae_mulzsafq32sp16u_ll_Slot_ae_slot1_encode, 0
};
-xtensa_opcode_encode_fn Opcode_ae_mulzsaq32sp16s_hh_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_mulzsaq32sp16s_hh_encode_fns[] = {
0, 0, 0, Opcode_ae_mulzsaq32sp16s_hh_Slot_ae_slot1_encode, 0
};
-xtensa_opcode_encode_fn Opcode_ae_mulzsafq32sp16s_hh_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_mulzsafq32sp16s_hh_encode_fns[] = {
0, 0, 0, Opcode_ae_mulzsafq32sp16s_hh_Slot_ae_slot1_encode, 0
};
-xtensa_opcode_encode_fn Opcode_ae_mulzsaq32sp16u_hh_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_mulzsaq32sp16u_hh_encode_fns[] = {
0, 0, 0, Opcode_ae_mulzsaq32sp16u_hh_Slot_ae_slot1_encode, 0
};
-xtensa_opcode_encode_fn Opcode_ae_mulzsafq32sp16u_hh_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_mulzsafq32sp16u_hh_encode_fns[] = {
0, 0, 0, Opcode_ae_mulzsafq32sp16u_hh_Slot_ae_slot1_encode, 0
};
-xtensa_opcode_encode_fn Opcode_ae_mulzsaq32sp16s_lh_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_mulzsaq32sp16s_lh_encode_fns[] = {
0, 0, 0, Opcode_ae_mulzsaq32sp16s_lh_Slot_ae_slot1_encode, 0
};
-xtensa_opcode_encode_fn Opcode_ae_mulzsafq32sp16s_lh_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_mulzsafq32sp16s_lh_encode_fns[] = {
0, 0, 0, Opcode_ae_mulzsafq32sp16s_lh_Slot_ae_slot1_encode, 0
};
-xtensa_opcode_encode_fn Opcode_ae_mulzsaq32sp16u_lh_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_mulzsaq32sp16u_lh_encode_fns[] = {
0, 0, 0, Opcode_ae_mulzsaq32sp16u_lh_Slot_ae_slot1_encode, 0
};
-xtensa_opcode_encode_fn Opcode_ae_mulzsafq32sp16u_lh_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_mulzsafq32sp16u_lh_encode_fns[] = {
0, 0, 0, Opcode_ae_mulzsafq32sp16u_lh_Slot_ae_slot1_encode, 0
};
-xtensa_opcode_encode_fn Opcode_ae_mulzssq32sp16s_ll_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_mulzssq32sp16s_ll_encode_fns[] = {
0, 0, 0, Opcode_ae_mulzssq32sp16s_ll_Slot_ae_slot1_encode, 0
};
-xtensa_opcode_encode_fn Opcode_ae_mulzssfq32sp16s_ll_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_mulzssfq32sp16s_ll_encode_fns[] = {
0, 0, 0, Opcode_ae_mulzssfq32sp16s_ll_Slot_ae_slot1_encode, 0
};
-xtensa_opcode_encode_fn Opcode_ae_mulzssq32sp16u_ll_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_mulzssq32sp16u_ll_encode_fns[] = {
0, 0, 0, Opcode_ae_mulzssq32sp16u_ll_Slot_ae_slot1_encode, 0
};
-xtensa_opcode_encode_fn Opcode_ae_mulzssfq32sp16u_ll_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_mulzssfq32sp16u_ll_encode_fns[] = {
0, 0, 0, Opcode_ae_mulzssfq32sp16u_ll_Slot_ae_slot1_encode, 0
};
-xtensa_opcode_encode_fn Opcode_ae_mulzssq32sp16s_hh_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_mulzssq32sp16s_hh_encode_fns[] = {
0, 0, 0, Opcode_ae_mulzssq32sp16s_hh_Slot_ae_slot1_encode, 0
};
-xtensa_opcode_encode_fn Opcode_ae_mulzssfq32sp16s_hh_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_mulzssfq32sp16s_hh_encode_fns[] = {
0, 0, 0, Opcode_ae_mulzssfq32sp16s_hh_Slot_ae_slot1_encode, 0
};
-xtensa_opcode_encode_fn Opcode_ae_mulzssq32sp16u_hh_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_mulzssq32sp16u_hh_encode_fns[] = {
0, 0, 0, Opcode_ae_mulzssq32sp16u_hh_Slot_ae_slot1_encode, 0
};
-xtensa_opcode_encode_fn Opcode_ae_mulzssfq32sp16u_hh_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_mulzssfq32sp16u_hh_encode_fns[] = {
0, 0, 0, Opcode_ae_mulzssfq32sp16u_hh_Slot_ae_slot1_encode, 0
};
-xtensa_opcode_encode_fn Opcode_ae_mulzssq32sp16s_lh_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_mulzssq32sp16s_lh_encode_fns[] = {
0, 0, 0, Opcode_ae_mulzssq32sp16s_lh_Slot_ae_slot1_encode, 0
};
-xtensa_opcode_encode_fn Opcode_ae_mulzssfq32sp16s_lh_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_mulzssfq32sp16s_lh_encode_fns[] = {
0, 0, 0, Opcode_ae_mulzssfq32sp16s_lh_Slot_ae_slot1_encode, 0
};
-xtensa_opcode_encode_fn Opcode_ae_mulzssq32sp16u_lh_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_mulzssq32sp16u_lh_encode_fns[] = {
0, 0, 0, Opcode_ae_mulzssq32sp16u_lh_Slot_ae_slot1_encode, 0
};
-xtensa_opcode_encode_fn Opcode_ae_mulzssfq32sp16u_lh_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_mulzssfq32sp16u_lh_encode_fns[] = {
0, 0, 0, Opcode_ae_mulzssfq32sp16u_lh_Slot_ae_slot1_encode, 0
};
-xtensa_opcode_encode_fn Opcode_ae_mulzaafp24s_hh_ll_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_mulzaafp24s_hh_ll_encode_fns[] = {
0, 0, 0, Opcode_ae_mulzaafp24s_hh_ll_Slot_ae_slot1_encode, 0
};
-xtensa_opcode_encode_fn Opcode_ae_mulzaap24s_hh_ll_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_mulzaap24s_hh_ll_encode_fns[] = {
0, 0, 0, Opcode_ae_mulzaap24s_hh_ll_Slot_ae_slot1_encode, 0
};
-xtensa_opcode_encode_fn Opcode_ae_mulzaafp24s_hl_lh_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_mulzaafp24s_hl_lh_encode_fns[] = {
0, 0, 0, Opcode_ae_mulzaafp24s_hl_lh_Slot_ae_slot1_encode, 0
};
-xtensa_opcode_encode_fn Opcode_ae_mulzaap24s_hl_lh_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_mulzaap24s_hl_lh_encode_fns[] = {
0, 0, 0, Opcode_ae_mulzaap24s_hl_lh_Slot_ae_slot1_encode, 0
};
-xtensa_opcode_encode_fn Opcode_ae_mulzasfp24s_hh_ll_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_mulzasfp24s_hh_ll_encode_fns[] = {
0, 0, 0, Opcode_ae_mulzasfp24s_hh_ll_Slot_ae_slot1_encode, 0
};
-xtensa_opcode_encode_fn Opcode_ae_mulzasp24s_hh_ll_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_mulzasp24s_hh_ll_encode_fns[] = {
0, 0, 0, Opcode_ae_mulzasp24s_hh_ll_Slot_ae_slot1_encode, 0
};
-xtensa_opcode_encode_fn Opcode_ae_mulzasfp24s_hl_lh_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_mulzasfp24s_hl_lh_encode_fns[] = {
0, 0, 0, Opcode_ae_mulzasfp24s_hl_lh_Slot_ae_slot1_encode, 0
};
-xtensa_opcode_encode_fn Opcode_ae_mulzasp24s_hl_lh_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_mulzasp24s_hl_lh_encode_fns[] = {
0, 0, 0, Opcode_ae_mulzasp24s_hl_lh_Slot_ae_slot1_encode, 0
};
-xtensa_opcode_encode_fn Opcode_ae_mulzsafp24s_hh_ll_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_mulzsafp24s_hh_ll_encode_fns[] = {
0, 0, 0, Opcode_ae_mulzsafp24s_hh_ll_Slot_ae_slot1_encode, 0
};
-xtensa_opcode_encode_fn Opcode_ae_mulzsap24s_hh_ll_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_mulzsap24s_hh_ll_encode_fns[] = {
0, 0, 0, Opcode_ae_mulzsap24s_hh_ll_Slot_ae_slot1_encode, 0
};
-xtensa_opcode_encode_fn Opcode_ae_mulzsafp24s_hl_lh_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_mulzsafp24s_hl_lh_encode_fns[] = {
0, 0, 0, Opcode_ae_mulzsafp24s_hl_lh_Slot_ae_slot1_encode, 0
};
-xtensa_opcode_encode_fn Opcode_ae_mulzsap24s_hl_lh_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_mulzsap24s_hl_lh_encode_fns[] = {
0, 0, 0, Opcode_ae_mulzsap24s_hl_lh_Slot_ae_slot1_encode, 0
};
-xtensa_opcode_encode_fn Opcode_ae_mulzssfp24s_hh_ll_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_mulzssfp24s_hh_ll_encode_fns[] = {
0, 0, 0, Opcode_ae_mulzssfp24s_hh_ll_Slot_ae_slot1_encode, 0
};
-xtensa_opcode_encode_fn Opcode_ae_mulzssp24s_hh_ll_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_mulzssp24s_hh_ll_encode_fns[] = {
0, 0, 0, Opcode_ae_mulzssp24s_hh_ll_Slot_ae_slot1_encode, 0
};
-xtensa_opcode_encode_fn Opcode_ae_mulzssfp24s_hl_lh_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_mulzssfp24s_hl_lh_encode_fns[] = {
0, 0, 0, Opcode_ae_mulzssfp24s_hl_lh_Slot_ae_slot1_encode, 0
};
-xtensa_opcode_encode_fn Opcode_ae_mulzssp24s_hl_lh_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_mulzssp24s_hl_lh_encode_fns[] = {
0, 0, 0, Opcode_ae_mulzssp24s_hl_lh_Slot_ae_slot1_encode, 0
};
-xtensa_opcode_encode_fn Opcode_ae_mulaafp24s_hh_ll_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_mulaafp24s_hh_ll_encode_fns[] = {
0, 0, 0, Opcode_ae_mulaafp24s_hh_ll_Slot_ae_slot1_encode, 0
};
-xtensa_opcode_encode_fn Opcode_ae_mulaap24s_hh_ll_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_mulaap24s_hh_ll_encode_fns[] = {
0, 0, 0, Opcode_ae_mulaap24s_hh_ll_Slot_ae_slot1_encode, 0
};
-xtensa_opcode_encode_fn Opcode_ae_mulaafp24s_hl_lh_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_mulaafp24s_hl_lh_encode_fns[] = {
0, 0, 0, Opcode_ae_mulaafp24s_hl_lh_Slot_ae_slot1_encode, 0
};
-xtensa_opcode_encode_fn Opcode_ae_mulaap24s_hl_lh_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_mulaap24s_hl_lh_encode_fns[] = {
0, 0, 0, Opcode_ae_mulaap24s_hl_lh_Slot_ae_slot1_encode, 0
};
-xtensa_opcode_encode_fn Opcode_ae_mulasfp24s_hh_ll_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_mulasfp24s_hh_ll_encode_fns[] = {
0, 0, 0, Opcode_ae_mulasfp24s_hh_ll_Slot_ae_slot1_encode, 0
};
-xtensa_opcode_encode_fn Opcode_ae_mulasp24s_hh_ll_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_mulasp24s_hh_ll_encode_fns[] = {
0, 0, 0, Opcode_ae_mulasp24s_hh_ll_Slot_ae_slot1_encode, 0
};
-xtensa_opcode_encode_fn Opcode_ae_mulasfp24s_hl_lh_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_mulasfp24s_hl_lh_encode_fns[] = {
0, 0, 0, Opcode_ae_mulasfp24s_hl_lh_Slot_ae_slot1_encode, 0
};
-xtensa_opcode_encode_fn Opcode_ae_mulasp24s_hl_lh_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_mulasp24s_hl_lh_encode_fns[] = {
0, 0, 0, Opcode_ae_mulasp24s_hl_lh_Slot_ae_slot1_encode, 0
};
-xtensa_opcode_encode_fn Opcode_ae_mulsafp24s_hh_ll_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_mulsafp24s_hh_ll_encode_fns[] = {
0, 0, 0, Opcode_ae_mulsafp24s_hh_ll_Slot_ae_slot1_encode, 0
};
-xtensa_opcode_encode_fn Opcode_ae_mulsap24s_hh_ll_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_mulsap24s_hh_ll_encode_fns[] = {
0, 0, 0, Opcode_ae_mulsap24s_hh_ll_Slot_ae_slot1_encode, 0
};
-xtensa_opcode_encode_fn Opcode_ae_mulsafp24s_hl_lh_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_mulsafp24s_hl_lh_encode_fns[] = {
0, 0, 0, Opcode_ae_mulsafp24s_hl_lh_Slot_ae_slot1_encode, 0
};
-xtensa_opcode_encode_fn Opcode_ae_mulsap24s_hl_lh_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_mulsap24s_hl_lh_encode_fns[] = {
0, 0, 0, Opcode_ae_mulsap24s_hl_lh_Slot_ae_slot1_encode, 0
};
-xtensa_opcode_encode_fn Opcode_ae_mulssfp24s_hh_ll_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_mulssfp24s_hh_ll_encode_fns[] = {
0, 0, 0, Opcode_ae_mulssfp24s_hh_ll_Slot_ae_slot1_encode, 0
};
-xtensa_opcode_encode_fn Opcode_ae_mulssp24s_hh_ll_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_mulssp24s_hh_ll_encode_fns[] = {
0, 0, 0, Opcode_ae_mulssp24s_hh_ll_Slot_ae_slot1_encode, 0
};
-xtensa_opcode_encode_fn Opcode_ae_mulssfp24s_hl_lh_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_mulssfp24s_hl_lh_encode_fns[] = {
0, 0, 0, Opcode_ae_mulssfp24s_hl_lh_Slot_ae_slot1_encode, 0
};
-xtensa_opcode_encode_fn Opcode_ae_mulssp24s_hl_lh_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_mulssp24s_hl_lh_encode_fns[] = {
0, 0, 0, Opcode_ae_mulssp24s_hl_lh_Slot_ae_slot1_encode, 0
};
-xtensa_opcode_encode_fn Opcode_ae_sha32_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_sha32_encode_fns[] = {
Opcode_ae_sha32_Slot_inst_encode, 0, 0, 0, 0
};
-xtensa_opcode_encode_fn Opcode_ae_vldl32t_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_vldl32t_encode_fns[] = {
Opcode_ae_vldl32t_Slot_inst_encode, 0, 0, 0, 0
};
-xtensa_opcode_encode_fn Opcode_ae_vldl16t_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_vldl16t_encode_fns[] = {
Opcode_ae_vldl16t_Slot_inst_encode, 0, 0, 0, 0
};
-xtensa_opcode_encode_fn Opcode_ae_vldl16c_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_vldl16c_encode_fns[] = {
Opcode_ae_vldl16c_Slot_inst_encode, 0, 0, 0, 0
};
-xtensa_opcode_encode_fn Opcode_ae_vldsht_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_vldsht_encode_fns[] = {
Opcode_ae_vldsht_Slot_inst_encode, 0, 0, 0, 0
};
-xtensa_opcode_encode_fn Opcode_ae_lb_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_lb_encode_fns[] = {
Opcode_ae_lb_Slot_inst_encode, 0, 0, 0, 0
};
-xtensa_opcode_encode_fn Opcode_ae_lbi_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_lbi_encode_fns[] = {
Opcode_ae_lbi_Slot_inst_encode, 0, 0, 0, 0
};
-xtensa_opcode_encode_fn Opcode_ae_lbk_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_lbk_encode_fns[] = {
Opcode_ae_lbk_Slot_inst_encode, 0, 0, 0, 0
};
-xtensa_opcode_encode_fn Opcode_ae_lbki_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_lbki_encode_fns[] = {
Opcode_ae_lbki_Slot_inst_encode, 0, 0, 0, 0
};
-xtensa_opcode_encode_fn Opcode_ae_db_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_db_encode_fns[] = {
Opcode_ae_db_Slot_inst_encode, 0, 0, 0, 0
};
-xtensa_opcode_encode_fn Opcode_ae_dbi_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_dbi_encode_fns[] = {
Opcode_ae_dbi_Slot_inst_encode, 0, 0, 0, 0
};
-xtensa_opcode_encode_fn Opcode_ae_vlel32t_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_vlel32t_encode_fns[] = {
Opcode_ae_vlel32t_Slot_inst_encode, 0, 0, 0, 0
};
-xtensa_opcode_encode_fn Opcode_ae_vlel16t_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_vlel16t_encode_fns[] = {
Opcode_ae_vlel16t_Slot_inst_encode, 0, 0, 0, 0
};
-xtensa_opcode_encode_fn Opcode_ae_sb_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_sb_encode_fns[] = {
Opcode_ae_sb_Slot_inst_encode, 0, 0, 0, 0
};
-xtensa_opcode_encode_fn Opcode_ae_sbi_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_sbi_encode_fns[] = {
Opcode_ae_sbi_Slot_inst_encode, 0, 0, 0, 0
};
-xtensa_opcode_encode_fn Opcode_ae_vles16c_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_vles16c_encode_fns[] = {
Opcode_ae_vles16c_Slot_inst_encode, 0, 0, 0, 0
};
-xtensa_opcode_encode_fn Opcode_ae_sbf_encode_fns[] = {
+static xtensa_opcode_encode_fn Opcode_ae_sbf_encode_fns[] = {
Opcode_ae_sbf_Slot_inst_encode, 0, 0, 0, 0
};
@@ -30818,7 +30818,7 @@
}
break;
}
- return 0;
+ return XTENSA_UNDEFINED;
}
static int
@@ -30869,7 +30869,7 @@
}
break;
}
- return 0;
+ return XTENSA_UNDEFINED;
}
static int
@@ -30886,7 +30886,7 @@
case 11:
return OPCODE_ADDI_N;
}
- return 0;
+ return XTENSA_UNDEFINED;
}
static int
@@ -31561,7 +31561,7 @@
return OPCODE_BF;
break;
}
- return 0;
+ return XTENSA_UNDEFINED;
}
static int
@@ -32279,7 +32279,7 @@
return OPCODE_AE_MULZSSQ32SP16U_LL;
break;
}
- return 0;
+ return XTENSA_UNDEFINED;
}
diff --git a/target/xtensa/cpu.h b/target/xtensa/cpu.h
index b665bfc..4d81526 100644
--- a/target/xtensa/cpu.h
+++ b/target/xtensa/cpu.h
@@ -131,6 +131,7 @@
ACCLO = 16,
ACCHI = 17,
MR = 32,
+ PREFCTL = 40,
WINDOW_BASE = 72,
WINDOW_START = 73,
PTEVADDR = 83,
@@ -345,14 +346,21 @@
} location[MAX_NMEMORY];
} XtensaMemory;
+typedef struct opcode_arg {
+ uint32_t imm;
+ uint32_t raw_imm;
+ void *in;
+ void *out;
+} OpcodeArg;
+
typedef struct DisasContext DisasContext;
-typedef void (*XtensaOpcodeOp)(DisasContext *dc, const uint32_t arg[],
+typedef void (*XtensaOpcodeOp)(DisasContext *dc, const OpcodeArg arg[],
const uint32_t par[]);
typedef bool (*XtensaOpcodeBoolTest)(DisasContext *dc,
- const uint32_t arg[],
+ const OpcodeArg arg[],
const uint32_t par[]);
typedef uint32_t (*XtensaOpcodeUintTest)(DisasContext *dc,
- const uint32_t arg[],
+ const OpcodeArg arg[],
const uint32_t par[]);
enum {
@@ -368,19 +376,34 @@
XTENSA_OP_DIVIDE_BY_ZERO = 0x100,
+ /* Postprocessing flags */
XTENSA_OP_CHECK_INTERRUPTS = 0x200,
XTENSA_OP_EXIT_TB_M1 = 0x400,
XTENSA_OP_EXIT_TB_0 = 0x800,
+ XTENSA_OP_SYNC_REGISTER_WINDOW = 0x1000,
+
+ XTENSA_OP_POSTPROCESS =
+ XTENSA_OP_CHECK_INTERRUPTS |
+ XTENSA_OP_EXIT_TB_M1 |
+ XTENSA_OP_EXIT_TB_0 |
+ XTENSA_OP_SYNC_REGISTER_WINDOW,
+
+ XTENSA_OP_NAME_ARRAY = 0x8000,
+
+ XTENSA_OP_CONTROL_FLOW = 0x10000,
+ XTENSA_OP_STORE = 0x20000,
+ XTENSA_OP_LOAD = 0x40000,
+ XTENSA_OP_LOAD_STORE =
+ XTENSA_OP_LOAD | XTENSA_OP_STORE,
};
typedef struct XtensaOpcodeOps {
- const char *name;
+ const void *name;
XtensaOpcodeOp translate;
XtensaOpcodeBoolTest test_ill;
XtensaOpcodeUintTest test_overflow;
const uint32_t *par;
uint32_t op_flags;
- uint32_t windowed_register_op;
uint32_t coprocessor;
} XtensaOpcodeOps;
@@ -438,6 +461,8 @@
xtensa_isa isa;
XtensaOpcodeOps **opcode_ops;
const XtensaOpcodeTranslators **opcode_translators;
+ xtensa_regfile a_regfile;
+ void ***regfile;
uint32_t clock_freq_khz;
@@ -474,6 +499,7 @@
float64 f64;
} fregs[16];
float_status fp_status;
+ uint32_t windowbase_next;
#ifndef CONFIG_USER_ONLY
xtensa_tlb_entry itlb[7][MAX_TLB_WAY_SIZE];
@@ -565,8 +591,8 @@
XTENSA_CPU_TYPE_NAME(XTENSA_DEFAULT_CPU_NOMMU_MODEL)
void xtensa_translate_init(void);
+void **xtensa_get_regfile_by_name(const char *name);
void xtensa_breakpoint_handler(CPUState *cs);
-void xtensa_finalize_config(XtensaConfig *config);
void xtensa_register_core(XtensaConfigList *node);
void xtensa_sim_open_console(Chardev *chr);
void check_interrupts(CPUXtensaState *s);
@@ -588,8 +614,6 @@
env->static_vectors = n;
}
void xtensa_runstall(CPUXtensaState *env, bool runstall);
-XtensaOpcodeOps *xtensa_find_opcode_ops(const XtensaOpcodeTranslators *t,
- const char *opcode);
#define XTENSA_OPTION_BIT(opt) (((uint64_t)1) << (opt))
#define XTENSA_OPTION_ALL (~(uint64_t)0)
diff --git a/target/xtensa/helper.c b/target/xtensa/helper.c
index bcf2f20..f4867a9 100644
--- a/target/xtensa/helper.c
+++ b/target/xtensa/helper.c
@@ -30,24 +30,60 @@
#include "exec/exec-all.h"
#include "exec/gdbstub.h"
#include "exec/helper-proto.h"
+#include "qemu/error-report.h"
#include "qemu/host-utils.h"
static struct XtensaConfigList *xtensa_cores;
-static void xtensa_core_class_init(ObjectClass *oc, void *data)
+static void add_translator_to_hash(GHashTable *translator,
+ const char *name,
+ const XtensaOpcodeOps *opcode)
{
- CPUClass *cc = CPU_CLASS(oc);
- XtensaCPUClass *xcc = XTENSA_CPU_CLASS(oc);
- const XtensaConfig *config = data;
+ if (!g_hash_table_insert(translator, (void *)name, (void *)opcode)) {
+ error_report("Multiple definitions of '%s' opcode in a single table",
+ name);
+ }
+}
- xcc->config = config;
+static GHashTable *hash_opcode_translators(const XtensaOpcodeTranslators *t)
+{
+ unsigned i, j;
+ GHashTable *translator = g_hash_table_new(g_str_hash, g_str_equal);
- /* Use num_core_regs to see only non-privileged registers in an unmodified
- * gdb. Use num_regs to see all registers. gdb modification is required
- * for that: reset bit 0 in the 'flags' field of the registers definitions
- * in the gdb/xtensa-config.c inside gdb source tree or inside gdb overlay.
- */
- cc->gdb_num_core_regs = config->gdb_regmap.num_regs;
+ for (i = 0; i < t->num_opcodes; ++i) {
+ if (t->opcode[i].op_flags & XTENSA_OP_NAME_ARRAY) {
+ const char * const *name = t->opcode[i].name;
+
+ for (j = 0; name[j]; ++j) {
+ add_translator_to_hash(translator,
+ (void *)name[j],
+ (void *)(t->opcode + i));
+ }
+ } else {
+ add_translator_to_hash(translator,
+ (void *)t->opcode[i].name,
+ (void *)(t->opcode + i));
+ }
+ }
+ return translator;
+}
+
+static XtensaOpcodeOps *
+xtensa_find_opcode_ops(const XtensaOpcodeTranslators *t,
+ const char *name)
+{
+ static GHashTable *translators;
+ GHashTable *translator;
+
+ if (translators == NULL) {
+ translators = g_hash_table_new(g_direct_hash, g_direct_equal);
+ }
+ translator = g_hash_table_lookup(translators, t);
+ if (translator == NULL) {
+ translator = hash_opcode_translators(t);
+ g_hash_table_insert(translators, (void *)t, translator);
+ }
+ return g_hash_table_lookup(translator, name);
}
static void init_libisa(XtensaConfig *config)
@@ -55,11 +91,13 @@
unsigned i, j;
unsigned opcodes;
unsigned formats;
+ unsigned regfiles;
config->isa = xtensa_isa_init(config->isa_internal, NULL, NULL);
assert(xtensa_isa_maxlength(config->isa) <= MAX_INSN_LENGTH);
opcodes = xtensa_isa_num_opcodes(config->isa);
formats = xtensa_isa_num_formats(config->isa);
+ regfiles = xtensa_isa_num_regfiles(config->isa);
config->opcode_ops = g_new(XtensaOpcodeOps *, opcodes);
for (i = 0; i < formats; ++i) {
@@ -88,9 +126,23 @@
#endif
config->opcode_ops[i] = ops;
}
+ config->a_regfile = xtensa_regfile_lookup(config->isa, "AR");
+
+ config->regfile = g_new(void **, regfiles);
+ for (i = 0; i < regfiles; ++i) {
+ const char *name = xtensa_regfile_name(config->isa, i);
+
+ config->regfile[i] = xtensa_get_regfile_by_name(name);
+#ifdef DEBUG
+ if (config->regfile[i] == NULL) {
+ fprintf(stderr, "regfile '%s' not found for %s\n",
+ name, config->name);
+ }
+#endif
+ }
}
-void xtensa_finalize_config(XtensaConfig *config)
+static void xtensa_finalize_config(XtensaConfig *config)
{
if (config->isa_internal) {
init_libisa(config);
@@ -111,6 +163,24 @@
}
}
+static void xtensa_core_class_init(ObjectClass *oc, void *data)
+{
+ CPUClass *cc = CPU_CLASS(oc);
+ XtensaCPUClass *xcc = XTENSA_CPU_CLASS(oc);
+ XtensaConfig *config = data;
+
+ xtensa_finalize_config(config);
+ xcc->config = config;
+
+ /*
+ * Use num_core_regs to see only non-privileged registers in an unmodified
+ * gdb. Use num_regs to see all registers. gdb modification is required
+ * for that: reset bit 0 in the 'flags' field of the registers definitions
+ * in the gdb/xtensa-config.c inside gdb source tree or inside gdb overlay.
+ */
+ cc->gdb_num_core_regs = config->gdb_regmap.num_regs;
+}
+
void xtensa_register_core(XtensaConfigList *node)
{
TypeInfo type = {
diff --git a/target/xtensa/helper.h b/target/xtensa/helper.h
index 2a7db35..0b9ec67 100644
--- a/target/xtensa/helper.h
+++ b/target/xtensa/helper.h
@@ -3,12 +3,11 @@
DEF_HELPER_4(exception_cause_vaddr, noreturn, env, i32, i32, i32)
DEF_HELPER_3(debug_exception, noreturn, env, i32, i32)
-DEF_HELPER_2(wsr_windowbase, void, env, i32)
+DEF_HELPER_1(sync_windowbase, void, env)
DEF_HELPER_4(entry, void, env, i32, i32, i32)
DEF_HELPER_2(test_ill_retw, void, env, i32)
DEF_HELPER_2(test_underflow_retw, void, env, i32)
-DEF_HELPER_2(retw, i32, env, i32)
-DEF_HELPER_2(rotw, void, env, i32)
+DEF_HELPER_2(retw, void, env, i32)
DEF_HELPER_3(window_check, noreturn, env, i32, i32)
DEF_HELPER_1(restore_owb, void, env)
DEF_HELPER_2(movsp, void, env, i32)
diff --git a/target/xtensa/import_core.sh b/target/xtensa/import_core.sh
index 039406b..e4a2e39 100755
--- a/target/xtensa/import_core.sh
+++ b/target/xtensa/import_core.sh
@@ -27,7 +27,7 @@
# Fix up known issues in the xtensa-modules.c
#
tar -xf "$OVERLAY" -O binutils/xtensa-modules.c | \
- sed -e 's/\(xtensa_opcode_encode_fn.*\[\] =\)/static \1/' \
+ sed -e 's/^\(xtensa_opcode_encode_fn.*\[\] =\)/static \1/' \
-e '/^int num_bypass_groups()/,/}/d' \
-e '/^int num_bypass_group_chunks()/,/}/d' \
-e '/^uint32 \*bypass_entry(int i)/,/}/d' \
diff --git a/target/xtensa/overlay_tool.h b/target/xtensa/overlay_tool.h
index 12609a0..ea07576 100644
--- a/target/xtensa/overlay_tool.h
+++ b/target/xtensa/overlay_tool.h
@@ -377,7 +377,6 @@
static XtensaConfigList node = { \
.config = &core, \
}; \
- xtensa_finalize_config(&core); \
xtensa_register_core(&node); \
}
#else
diff --git a/target/xtensa/translate.c b/target/xtensa/translate.c
index d1e9f59..77bc04d 100644
--- a/target/xtensa/translate.c
+++ b/target/xtensa/translate.c
@@ -71,7 +71,7 @@
unsigned cpenable;
- uint32_t *raw_arg;
+ uint32_t op_flags;
xtensa_insnbuf insnbuf;
xtensa_insnbuf slotbuf;
};
@@ -79,8 +79,15 @@
static TCGv_i32 cpu_pc;
static TCGv_i32 cpu_R[16];
static TCGv_i32 cpu_FR[16];
+static TCGv_i32 cpu_MR[4];
+static TCGv_i32 cpu_BR[16];
+static TCGv_i32 cpu_BR4[4];
+static TCGv_i32 cpu_BR8[2];
static TCGv_i32 cpu_SR[256];
static TCGv_i32 cpu_UR[256];
+static TCGv_i32 cpu_windowbase_next;
+
+static GHashTable *xtensa_regfile_table;
#include "exec/gen-icount.h"
@@ -127,6 +134,7 @@
[MR + 1] = XTENSA_REG("MR1", XTENSA_OPTION_MAC16),
[MR + 2] = XTENSA_REG("MR2", XTENSA_OPTION_MAC16),
[MR + 3] = XTENSA_REG("MR3", XTENSA_OPTION_MAC16),
+ [PREFCTL] = XTENSA_REG_BITS("PREFCTL", XTENSA_OPTION_ALL),
[WINDOW_BASE] = XTENSA_REG("WINDOW_BASE", XTENSA_OPTION_WINDOWED_REGISTER),
[WINDOW_START] = XTENSA_REG("WINDOW_START",
XTENSA_OPTION_WINDOWED_REGISTER),
@@ -220,6 +228,15 @@
"f8", "f9", "f10", "f11",
"f12", "f13", "f14", "f15",
};
+ static const char * const mregnames[] = {
+ "m0", "m1", "m2", "m3",
+ };
+ static const char * const bregnames[] = {
+ "b0", "b1", "b2", "b3",
+ "b4", "b5", "b6", "b7",
+ "b8", "b9", "b10", "b11",
+ "b12", "b13", "b14", "b15",
+ };
int i;
cpu_pc = tcg_global_mem_new_i32(cpu_env,
@@ -227,14 +244,41 @@
for (i = 0; i < 16; i++) {
cpu_R[i] = tcg_global_mem_new_i32(cpu_env,
- offsetof(CPUXtensaState, regs[i]),
- regnames[i]);
+ offsetof(CPUXtensaState, regs[i]),
+ regnames[i]);
}
for (i = 0; i < 16; i++) {
cpu_FR[i] = tcg_global_mem_new_i32(cpu_env,
- offsetof(CPUXtensaState, fregs[i].f32[FP_F32_LOW]),
- fregnames[i]);
+ offsetof(CPUXtensaState,
+ fregs[i].f32[FP_F32_LOW]),
+ fregnames[i]);
+ }
+
+ for (i = 0; i < 4; i++) {
+ cpu_MR[i] = tcg_global_mem_new_i32(cpu_env,
+ offsetof(CPUXtensaState,
+ sregs[MR + i]),
+ mregnames[i]);
+ }
+
+ for (i = 0; i < 16; i++) {
+ cpu_BR[i] = tcg_global_mem_new_i32(cpu_env,
+ offsetof(CPUXtensaState,
+ sregs[BR]),
+ bregnames[i]);
+ if (i % 4 == 0) {
+ cpu_BR4[i / 4] = tcg_global_mem_new_i32(cpu_env,
+ offsetof(CPUXtensaState,
+ sregs[BR]),
+ bregnames[i]);
+ }
+ if (i % 8 == 0) {
+ cpu_BR8[i / 8] = tcg_global_mem_new_i32(cpu_env,
+ offsetof(CPUXtensaState,
+ sregs[BR]),
+ bregnames[i]);
+ }
}
for (i = 0; i < 256; ++i) {
@@ -252,6 +296,31 @@
uregnames[i].name);
}
}
+
+ cpu_windowbase_next =
+ tcg_global_mem_new_i32(cpu_env,
+ offsetof(CPUXtensaState, windowbase_next),
+ "windowbase_next");
+}
+
+void **xtensa_get_regfile_by_name(const char *name)
+{
+ if (xtensa_regfile_table == NULL) {
+ xtensa_regfile_table = g_hash_table_new(g_str_hash, g_str_equal);
+ g_hash_table_insert(xtensa_regfile_table,
+ (void *)"AR", (void *)cpu_R);
+ g_hash_table_insert(xtensa_regfile_table,
+ (void *)"MR", (void *)cpu_MR);
+ g_hash_table_insert(xtensa_regfile_table,
+ (void *)"FR", (void *)cpu_FR);
+ g_hash_table_insert(xtensa_regfile_table,
+ (void *)"BR", (void *)cpu_BR);
+ g_hash_table_insert(xtensa_regfile_table,
+ (void *)"BR4", (void *)cpu_BR4);
+ g_hash_table_insert(xtensa_regfile_table,
+ (void *)"BR8", (void *)cpu_BR8);
+ }
+ return (void **)g_hash_table_lookup(xtensa_regfile_table, (void *)name);
}
static inline bool option_enabled(DisasContext *dc, int opt)
@@ -363,6 +432,8 @@
return true;
}
+static int gen_postprocess(DisasContext *dc, int slot);
+
static void gen_jump_slot(DisasContext *dc, TCGv dest, int slot)
{
tcg_gen_mov_i32(cpu_pc, dest);
@@ -372,6 +443,9 @@
if (dc->base.singlestep_enabled) {
gen_exception(dc, EXCP_DEBUG);
} else {
+ if (dc->op_flags & XTENSA_OP_POSTPROCESS) {
+ slot = gen_postprocess(dc, slot);
+ }
if (slot >= 0) {
tcg_gen_goto_tb(slot);
tcg_gen_exit_tb(dc->base.tb, slot);
@@ -387,13 +461,19 @@
gen_jump_slot(dc, dest, -1);
}
+static int adjust_jump_slot(DisasContext *dc, uint32_t dest, int slot)
+{
+ if (((dc->base.pc_first ^ dest) & TARGET_PAGE_MASK) != 0) {
+ return -1;
+ } else {
+ return slot;
+ }
+}
+
static void gen_jumpi(DisasContext *dc, uint32_t dest, int slot)
{
TCGv_i32 tmp = tcg_const_i32(dest);
- if (((dc->base.pc_first ^ dest) & TARGET_PAGE_MASK) != 0) {
- slot = -1;
- }
- gen_jump_slot(dc, tmp, slot);
+ gen_jump_slot(dc, tmp, adjust_jump_slot(dc, dest, slot));
tcg_temp_free(tmp);
}
@@ -410,21 +490,6 @@
gen_jump_slot(dc, dest, slot);
}
-static void gen_callw(DisasContext *dc, int callinc, TCGv_i32 dest)
-{
- gen_callw_slot(dc, callinc, dest, -1);
-}
-
-static void gen_callwi(DisasContext *dc, int callinc, uint32_t dest, int slot)
-{
- TCGv_i32 tmp = tcg_const_i32(dest);
- if (((dc->base.pc_first ^ dest) & TARGET_PAGE_MASK) != 0) {
- slot = -1;
- }
- gen_callw_slot(dc, callinc, tmp, slot);
- tcg_temp_free(tmp);
-}
-
static bool gen_check_loop_end(DisasContext *dc, int slot)
{
if (dc->base.pc_next == dc->lend) {
@@ -560,7 +625,7 @@
#ifndef CONFIG_USER_ONLY
static void gen_wsr_windowbase(DisasContext *dc, uint32_t sr, TCGv_i32 v)
{
- gen_helper_wsr_windowbase(cpu_env, v);
+ tcg_gen_mov_i32(cpu_windowbase_next, v);
}
static void gen_wsr_windowstart(DisasContext *dc, uint32_t sr, TCGv_i32 v)
@@ -841,11 +906,11 @@
return m;
}
-static void gen_zero_check(DisasContext *dc, const uint32_t arg[])
+static void gen_zero_check(DisasContext *dc, const OpcodeArg arg[])
{
TCGLabel *label = gen_new_label();
- tcg_gen_brcondi_i32(TCG_COND_NE, cpu_R[arg[2]], 0, label);
+ tcg_gen_brcondi_i32(TCG_COND_NE, arg[2].in, 0, label);
gen_exception_cause(dc, INTEGER_DIVIDE_BY_ZERO_CAUSE);
gen_set_label(label);
}
@@ -855,6 +920,270 @@
return xtensa_isa_length_from_chars(dc->config->isa, &op0);
}
+static int gen_postprocess(DisasContext *dc, int slot)
+{
+ uint32_t op_flags = dc->op_flags;
+
+ if (op_flags & XTENSA_OP_CHECK_INTERRUPTS) {
+ gen_check_interrupts(dc);
+ }
+ if (op_flags & XTENSA_OP_SYNC_REGISTER_WINDOW) {
+ gen_helper_sync_windowbase(cpu_env);
+ }
+ if (op_flags & XTENSA_OP_EXIT_TB_M1) {
+ slot = -1;
+ }
+ return slot;
+}
+
+struct opcode_arg_copy {
+ uint32_t resource;
+ void *temp;
+ OpcodeArg *arg;
+};
+
+struct opcode_arg_info {
+ uint32_t resource;
+ int index;
+};
+
+struct slot_prop {
+ XtensaOpcodeOps *ops;
+ OpcodeArg arg[MAX_OPCODE_ARGS];
+ struct opcode_arg_info in[MAX_OPCODE_ARGS];
+ struct opcode_arg_info out[MAX_OPCODE_ARGS];
+ unsigned n_in;
+ unsigned n_out;
+ uint32_t op_flags;
+};
+
+enum resource_type {
+ RES_REGFILE,
+ RES_STATE,
+ RES_MAX,
+};
+
+static uint32_t encode_resource(enum resource_type r, unsigned g, unsigned n)
+{
+ assert(r < RES_MAX && g < 256 && n < 65536);
+ return (r << 24) | (g << 16) | n;
+}
+
+static enum resource_type get_resource_type(uint32_t resource)
+{
+ return resource >> 24;
+}
+
+/*
+ * a depends on b if b must be executed before a,
+ * because a's side effects will destroy b's inputs.
+ */
+static bool op_depends_on(const struct slot_prop *a,
+ const struct slot_prop *b)
+{
+ unsigned i = 0;
+ unsigned j = 0;
+
+ if (a->op_flags & XTENSA_OP_CONTROL_FLOW) {
+ return true;
+ }
+ if ((a->op_flags & XTENSA_OP_LOAD_STORE) <
+ (b->op_flags & XTENSA_OP_LOAD_STORE)) {
+ return true;
+ }
+ while (i < a->n_out && j < b->n_in) {
+ if (a->out[i].resource < b->in[j].resource) {
+ ++i;
+ } else if (a->out[i].resource > b->in[j].resource) {
+ ++j;
+ } else {
+ return true;
+ }
+ }
+ return false;
+}
+
+/*
+ * Try to break a dependency on b, append temporary register copy records
+ * to the end of copy and update n_copy in case of success.
+ * This is not always possible: e.g. control flow must always be the last,
+ * load/store must be first and state dependencies are not supported yet.
+ */
+static bool break_dependency(struct slot_prop *a,
+ struct slot_prop *b,
+ struct opcode_arg_copy *copy,
+ unsigned *n_copy)
+{
+ unsigned i = 0;
+ unsigned j = 0;
+ unsigned n = *n_copy;
+ bool rv = false;
+
+ if (a->op_flags & XTENSA_OP_CONTROL_FLOW) {
+ return false;
+ }
+ if ((a->op_flags & XTENSA_OP_LOAD_STORE) <
+ (b->op_flags & XTENSA_OP_LOAD_STORE)) {
+ return false;
+ }
+ while (i < a->n_out && j < b->n_in) {
+ if (a->out[i].resource < b->in[j].resource) {
+ ++i;
+ } else if (a->out[i].resource > b->in[j].resource) {
+ ++j;
+ } else {
+ int index = b->in[j].index;
+
+ if (get_resource_type(a->out[i].resource) != RES_REGFILE ||
+ index < 0) {
+ return false;
+ }
+ copy[n].resource = b->in[j].resource;
+ copy[n].arg = b->arg + index;
+ ++n;
+ ++i;
+ ++j;
+ rv = true;
+ }
+ }
+ *n_copy = n;
+ return rv;
+}
+
+/*
+ * Calculate evaluation order for slot opcodes.
+ * Build opcode order graph and output its nodes in topological sort order.
+ * An edge a -> b in the graph means that opcode a must be followed by
+ * opcode b.
+ */
+static bool tsort(struct slot_prop *slot,
+ struct slot_prop *sorted[],
+ unsigned n,
+ struct opcode_arg_copy *copy,
+ unsigned *n_copy)
+{
+ struct tsnode {
+ unsigned n_in_edge;
+ unsigned n_out_edge;
+ unsigned out_edge[MAX_INSN_SLOTS];
+ } node[MAX_INSN_SLOTS];
+
+ unsigned in[MAX_INSN_SLOTS];
+ unsigned i, j;
+ unsigned n_in = 0;
+ unsigned n_out = 0;
+ unsigned n_edge = 0;
+ unsigned in_idx = 0;
+ unsigned node_idx = 0;
+
+ for (i = 0; i < n; ++i) {
+ node[i].n_in_edge = 0;
+ node[i].n_out_edge = 0;
+ }
+
+ for (i = 0; i < n; ++i) {
+ unsigned n_out_edge = 0;
+
+ for (j = 0; j < n; ++j) {
+ if (i != j && op_depends_on(slot + j, slot + i)) {
+ node[i].out_edge[n_out_edge] = j;
+ ++node[j].n_in_edge;
+ ++n_out_edge;
+ ++n_edge;
+ }
+ }
+ node[i].n_out_edge = n_out_edge;
+ }
+
+ for (i = 0; i < n; ++i) {
+ if (!node[i].n_in_edge) {
+ in[n_in] = i;
+ ++n_in;
+ }
+ }
+
+again:
+ for (; in_idx < n_in; ++in_idx) {
+ i = in[in_idx];
+ sorted[n_out] = slot + i;
+ ++n_out;
+ for (j = 0; j < node[i].n_out_edge; ++j) {
+ --n_edge;
+ if (--node[node[i].out_edge[j]].n_in_edge == 0) {
+ in[n_in] = node[i].out_edge[j];
+ ++n_in;
+ }
+ }
+ }
+ if (n_edge) {
+ for (; node_idx < n; ++node_idx) {
+ struct tsnode *cnode = node + node_idx;
+
+ if (cnode->n_in_edge) {
+ for (j = 0; j < cnode->n_out_edge; ++j) {
+ unsigned k = cnode->out_edge[j];
+
+ if (break_dependency(slot + k, slot + node_idx,
+ copy, n_copy) &&
+ --node[k].n_in_edge == 0) {
+ in[n_in] = k;
+ ++n_in;
+ --n_edge;
+ cnode->out_edge[j] =
+ cnode->out_edge[cnode->n_out_edge - 1];
+ --cnode->n_out_edge;
+ goto again;
+ }
+ }
+ }
+ }
+ }
+ return n_edge == 0;
+}
+
+static void opcode_add_resource(struct slot_prop *op,
+ uint32_t resource, char direction,
+ int index)
+{
+ switch (direction) {
+ case 'm':
+ case 'i':
+ assert(op->n_in < ARRAY_SIZE(op->in));
+ op->in[op->n_in].resource = resource;
+ op->in[op->n_in].index = index;
+ ++op->n_in;
+ /* fall through */
+ case 'o':
+ if (direction == 'm' || direction == 'o') {
+ assert(op->n_out < ARRAY_SIZE(op->out));
+ op->out[op->n_out].resource = resource;
+ op->out[op->n_out].index = index;
+ ++op->n_out;
+ }
+ break;
+ default:
+ g_assert_not_reached();
+ }
+}
+
+static int resource_compare(const void *a, const void *b)
+{
+ const struct opcode_arg_info *pa = a;
+ const struct opcode_arg_info *pb = b;
+
+ return pa->resource < pb->resource ?
+ -1 : (pa->resource > pb->resource ? 1 : 0);
+}
+
+static int arg_copy_compare(const void *a, const void *b)
+{
+ const struct opcode_arg_copy *pa = a;
+ const struct opcode_arg_copy *pb = b;
+
+ return pa->resource < pb->resource ?
+ -1 : (pa->resource > pb->resource ? 1 : 0);
+}
+
static void disas_xtensa_insn(CPUXtensaState *env, DisasContext *dc)
{
xtensa_isa isa = dc->config->isa;
@@ -864,11 +1193,10 @@
int slot, slots;
unsigned i;
uint32_t op_flags = 0;
- struct {
- XtensaOpcodeOps *ops;
- uint32_t arg[MAX_OPCODE_ARGS];
- uint32_t raw_arg[MAX_OPCODE_ARGS];
- } slot_prop[MAX_INSN_SLOTS];
+ struct slot_prop slot_prop[MAX_INSN_SLOTS];
+ struct slot_prop *ordered[MAX_INSN_SLOTS];
+ struct opcode_arg_copy arg_copy[MAX_INSN_SLOTS * MAX_OPCODE_ARGS];
+ unsigned n_arg_copy = 0;
uint32_t debug_cause = 0;
uint32_t windowed_register = 0;
uint32_t coprocessor = 0;
@@ -898,12 +1226,9 @@
for (slot = 0; slot < slots; ++slot) {
xtensa_opcode opc;
int opnd, vopnd, opnds;
- uint32_t *raw_arg = slot_prop[slot].raw_arg;
- uint32_t *arg = slot_prop[slot].arg;
+ OpcodeArg *arg = slot_prop[slot].arg;
XtensaOpcodeOps *ops;
- dc->raw_arg = raw_arg;
-
xtensa_format_get_slot(isa, fmt, slot, dc->insnbuf, dc->slotbuf);
opc = xtensa_opcode_decode(isa, fmt, slot, dc->slotbuf);
if (opc == XTENSA_UNDEFINED) {
@@ -916,17 +1241,37 @@
opnds = xtensa_opcode_num_operands(isa, opc);
for (opnd = vopnd = 0; opnd < opnds; ++opnd) {
+ void **register_file = NULL;
+
+ if (xtensa_operand_is_register(isa, opc, opnd)) {
+ xtensa_regfile rf = xtensa_operand_regfile(isa, opc, opnd);
+
+ register_file = dc->config->regfile[rf];
+
+ if (rf == dc->config->a_regfile) {
+ uint32_t v;
+
+ xtensa_operand_get_field(isa, opc, opnd, fmt, slot,
+ dc->slotbuf, &v);
+ xtensa_operand_decode(isa, opc, opnd, &v);
+ windowed_register |= 1u << v;
+ }
+ }
if (xtensa_operand_is_visible(isa, opc, opnd)) {
uint32_t v;
xtensa_operand_get_field(isa, opc, opnd, fmt, slot,
dc->slotbuf, &v);
xtensa_operand_decode(isa, opc, opnd, &v);
- raw_arg[vopnd] = v;
+ arg[vopnd].raw_imm = v;
if (xtensa_operand_is_PCrelative(isa, opc, opnd)) {
xtensa_operand_undo_reloc(isa, opc, opnd, &v, dc->pc);
}
- arg[vopnd] = v;
+ arg[vopnd].imm = v;
+ if (register_file) {
+ arg[vopnd].in = register_file[v];
+ arg[vopnd].out = register_file[v];
+ }
++vopnd;
}
}
@@ -952,17 +1297,69 @@
if (ops->test_overflow) {
windowed_register |= ops->test_overflow(dc, arg, ops->par);
}
- if (ops->windowed_register_op) {
- uint32_t reg_opnd = ops->windowed_register_op;
-
- while (reg_opnd) {
- unsigned i = ctz32(reg_opnd);
-
- windowed_register |= 1 << arg[i];
- reg_opnd ^= 1 << i;
- }
- }
coprocessor |= ops->coprocessor;
+
+ if (slots > 1) {
+ slot_prop[slot].n_in = 0;
+ slot_prop[slot].n_out = 0;
+ slot_prop[slot].op_flags = ops->op_flags & XTENSA_OP_LOAD_STORE;
+
+ opnds = xtensa_opcode_num_operands(isa, opc);
+
+ for (opnd = vopnd = 0; opnd < opnds; ++opnd) {
+ bool visible = xtensa_operand_is_visible(isa, opc, opnd);
+
+ if (xtensa_operand_is_register(isa, opc, opnd)) {
+ xtensa_regfile rf = xtensa_operand_regfile(isa, opc, opnd);
+ uint32_t v = 0;
+
+ xtensa_operand_get_field(isa, opc, opnd, fmt, slot,
+ dc->slotbuf, &v);
+ xtensa_operand_decode(isa, opc, opnd, &v);
+ opcode_add_resource(slot_prop + slot,
+ encode_resource(RES_REGFILE, rf, v),
+ xtensa_operand_inout(isa, opc, opnd),
+ visible ? vopnd : -1);
+ }
+ if (visible) {
+ ++vopnd;
+ }
+ }
+
+ opnds = xtensa_opcode_num_stateOperands(isa, opc);
+
+ for (opnd = 0; opnd < opnds; ++opnd) {
+ xtensa_state state = xtensa_stateOperand_state(isa, opc, opnd);
+
+ opcode_add_resource(slot_prop + slot,
+ encode_resource(RES_STATE, 0, state),
+ xtensa_stateOperand_inout(isa, opc, opnd),
+ -1);
+ }
+ if (xtensa_opcode_is_branch(isa, opc) ||
+ xtensa_opcode_is_jump(isa, opc) ||
+ xtensa_opcode_is_loop(isa, opc) ||
+ xtensa_opcode_is_call(isa, opc)) {
+ slot_prop[slot].op_flags |= XTENSA_OP_CONTROL_FLOW;
+ }
+
+ qsort(slot_prop[slot].in, slot_prop[slot].n_in,
+ sizeof(slot_prop[slot].in[0]), resource_compare);
+ qsort(slot_prop[slot].out, slot_prop[slot].n_out,
+ sizeof(slot_prop[slot].out[0]), resource_compare);
+ }
+ }
+
+ if (slots > 1) {
+ if (!tsort(slot_prop, ordered, slots, arg_copy, &n_arg_copy)) {
+ qemu_log_mask(LOG_UNIMP,
+ "Circular resource dependencies (pc = %08x)\n",
+ dc->pc);
+ gen_exception_cause(dc, ILLEGAL_INSTRUCTION_CAUSE);
+ return;
+ }
+ } else {
+ ordered[0] = slot_prop + 0;
}
if ((op_flags & XTENSA_OP_PRIVILEGED) &&
@@ -1002,6 +1399,29 @@
return;
}
+ if (n_arg_copy) {
+ uint32_t resource;
+ void *temp;
+ unsigned j;
+
+ qsort(arg_copy, n_arg_copy, sizeof(*arg_copy), arg_copy_compare);
+ for (i = j = 0; i < n_arg_copy; ++i) {
+ if (i == 0 || arg_copy[i].resource != resource) {
+ resource = arg_copy[i].resource;
+ temp = tcg_temp_local_new();
+ tcg_gen_mov_i32(temp, arg_copy[i].arg->in);
+ arg_copy[i].temp = temp;
+
+ if (i != j) {
+ arg_copy[j] = arg_copy[i];
+ }
+ ++j;
+ }
+ arg_copy[i].arg->in = temp;
+ }
+ n_arg_copy = j;
+ }
+
if (op_flags & XTENSA_OP_DIVIDE_BY_ZERO) {
for (slot = 0; slot < slots; ++slot) {
if (slot_prop[slot].ops->op_flags & XTENSA_OP_DIVIDE_BY_ZERO) {
@@ -1010,29 +1430,31 @@
}
}
- for (slot = 0; slot < slots; ++slot) {
- XtensaOpcodeOps *ops = slot_prop[slot].ops;
+ dc->op_flags = op_flags;
- dc->raw_arg = slot_prop[slot].raw_arg;
- ops->translate(dc, slot_prop[slot].arg, ops->par);
+ for (slot = 0; slot < slots; ++slot) {
+ struct slot_prop *pslot = ordered[slot];
+ XtensaOpcodeOps *ops = pslot->ops;
+
+ ops->translate(dc, pslot->arg, ops->par);
+ }
+
+ for (i = 0; i < n_arg_copy; ++i) {
+ tcg_temp_free(arg_copy[i].temp);
}
if (dc->base.is_jmp == DISAS_NEXT) {
- if (op_flags & XTENSA_OP_CHECK_INTERRUPTS) {
- gen_check_interrupts(dc);
- }
-
+ gen_postprocess(dc, 0);
+ dc->op_flags = 0;
if (op_flags & XTENSA_OP_EXIT_TB_M1) {
/* Change in mmu index, memory mapping or tb->flags; exit tb */
gen_jumpi_check_loop_end(dc, -1);
} else if (op_flags & XTENSA_OP_EXIT_TB_0) {
gen_jumpi_check_loop_end(dc, 0);
+ } else {
+ gen_check_loop_end(dc, 0);
}
}
-
- if (dc->base.is_jmp == DISAS_NEXT) {
- gen_check_loop_end(dc, 0);
- }
dc->pc = dc->base.pc_next;
}
@@ -1283,105 +1705,91 @@
env->pc = data[0];
}
-static int compare_opcode_ops(const void *a, const void *b)
-{
- return strcmp((const char *)a,
- ((const XtensaOpcodeOps *)b)->name);
-}
-
-XtensaOpcodeOps *
-xtensa_find_opcode_ops(const XtensaOpcodeTranslators *t,
- const char *name)
-{
- return bsearch(name, t->opcode, t->num_opcodes,
- sizeof(XtensaOpcodeOps), compare_opcode_ops);
-}
-
-static void translate_abs(DisasContext *dc, const uint32_t arg[],
+static void translate_abs(DisasContext *dc, const OpcodeArg arg[],
const uint32_t par[])
{
TCGv_i32 zero = tcg_const_i32(0);
TCGv_i32 neg = tcg_temp_new_i32();
- tcg_gen_neg_i32(neg, cpu_R[arg[1]]);
- tcg_gen_movcond_i32(TCG_COND_GE, cpu_R[arg[0]],
- cpu_R[arg[1]], zero, cpu_R[arg[1]], neg);
+ tcg_gen_neg_i32(neg, arg[1].in);
+ tcg_gen_movcond_i32(TCG_COND_GE, arg[0].out,
+ arg[1].in, zero, arg[1].in, neg);
tcg_temp_free(neg);
tcg_temp_free(zero);
}
-static void translate_add(DisasContext *dc, const uint32_t arg[],
+static void translate_add(DisasContext *dc, const OpcodeArg arg[],
const uint32_t par[])
{
- tcg_gen_add_i32(cpu_R[arg[0]], cpu_R[arg[1]], cpu_R[arg[2]]);
+ tcg_gen_add_i32(arg[0].out, arg[1].in, arg[2].in);
}
-static void translate_addi(DisasContext *dc, const uint32_t arg[],
+static void translate_addi(DisasContext *dc, const OpcodeArg arg[],
const uint32_t par[])
{
- tcg_gen_addi_i32(cpu_R[arg[0]], cpu_R[arg[1]], arg[2]);
+ tcg_gen_addi_i32(arg[0].out, arg[1].in, arg[2].imm);
}
-static void translate_addx(DisasContext *dc, const uint32_t arg[],
+static void translate_addx(DisasContext *dc, const OpcodeArg arg[],
const uint32_t par[])
{
TCGv_i32 tmp = tcg_temp_new_i32();
- tcg_gen_shli_i32(tmp, cpu_R[arg[1]], par[0]);
- tcg_gen_add_i32(cpu_R[arg[0]], tmp, cpu_R[arg[2]]);
+ tcg_gen_shli_i32(tmp, arg[1].in, par[0]);
+ tcg_gen_add_i32(arg[0].out, tmp, arg[2].in);
tcg_temp_free(tmp);
}
-static void translate_all(DisasContext *dc, const uint32_t arg[],
+static void translate_all(DisasContext *dc, const OpcodeArg arg[],
const uint32_t par[])
{
uint32_t shift = par[1];
- TCGv_i32 mask = tcg_const_i32(((1 << shift) - 1) << arg[1]);
+ TCGv_i32 mask = tcg_const_i32(((1 << shift) - 1) << arg[1].imm);
TCGv_i32 tmp = tcg_temp_new_i32();
- tcg_gen_and_i32(tmp, cpu_SR[BR], mask);
+ tcg_gen_and_i32(tmp, arg[1].in, mask);
if (par[0]) {
- tcg_gen_addi_i32(tmp, tmp, 1 << arg[1]);
+ tcg_gen_addi_i32(tmp, tmp, 1 << arg[1].imm);
} else {
tcg_gen_add_i32(tmp, tmp, mask);
}
- tcg_gen_shri_i32(tmp, tmp, arg[1] + shift);
- tcg_gen_deposit_i32(cpu_SR[BR], cpu_SR[BR],
- tmp, arg[0], 1);
+ tcg_gen_shri_i32(tmp, tmp, arg[1].imm + shift);
+ tcg_gen_deposit_i32(arg[0].out, arg[0].out,
+ tmp, arg[0].imm, 1);
tcg_temp_free(mask);
tcg_temp_free(tmp);
}
-static void translate_and(DisasContext *dc, const uint32_t arg[],
+static void translate_and(DisasContext *dc, const OpcodeArg arg[],
const uint32_t par[])
{
- tcg_gen_and_i32(cpu_R[arg[0]], cpu_R[arg[1]], cpu_R[arg[2]]);
+ tcg_gen_and_i32(arg[0].out, arg[1].in, arg[2].in);
}
-static void translate_ball(DisasContext *dc, const uint32_t arg[],
+static void translate_ball(DisasContext *dc, const OpcodeArg arg[],
const uint32_t par[])
{
TCGv_i32 tmp = tcg_temp_new_i32();
- tcg_gen_and_i32(tmp, cpu_R[arg[0]], cpu_R[arg[1]]);
- gen_brcond(dc, par[0], tmp, cpu_R[arg[1]], arg[2]);
+ tcg_gen_and_i32(tmp, arg[0].in, arg[1].in);
+ gen_brcond(dc, par[0], tmp, arg[1].in, arg[2].imm);
tcg_temp_free(tmp);
}
-static void translate_bany(DisasContext *dc, const uint32_t arg[],
+static void translate_bany(DisasContext *dc, const OpcodeArg arg[],
const uint32_t par[])
{
TCGv_i32 tmp = tcg_temp_new_i32();
- tcg_gen_and_i32(tmp, cpu_R[arg[0]], cpu_R[arg[1]]);
- gen_brcondi(dc, par[0], tmp, 0, arg[2]);
+ tcg_gen_and_i32(tmp, arg[0].in, arg[1].in);
+ gen_brcondi(dc, par[0], tmp, 0, arg[2].imm);
tcg_temp_free(tmp);
}
-static void translate_b(DisasContext *dc, const uint32_t arg[],
+static void translate_b(DisasContext *dc, const OpcodeArg arg[],
const uint32_t par[])
{
- gen_brcond(dc, par[0], cpu_R[arg[0]], cpu_R[arg[1]], arg[2]);
+ gen_brcond(dc, par[0], arg[0].in, arg[1].in, arg[2].imm);
}
-static void translate_bb(DisasContext *dc, const uint32_t arg[],
+static void translate_bb(DisasContext *dc, const OpcodeArg arg[],
const uint32_t par[])
{
#ifdef TARGET_WORDS_BIGENDIAN
@@ -1390,41 +1798,41 @@
TCGv_i32 bit = tcg_const_i32(0x00000001u);
#endif
TCGv_i32 tmp = tcg_temp_new_i32();
- tcg_gen_andi_i32(tmp, cpu_R[arg[1]], 0x1f);
+ tcg_gen_andi_i32(tmp, arg[1].in, 0x1f);
#ifdef TARGET_WORDS_BIGENDIAN
tcg_gen_shr_i32(bit, bit, tmp);
#else
tcg_gen_shl_i32(bit, bit, tmp);
#endif
- tcg_gen_and_i32(tmp, cpu_R[arg[0]], bit);
- gen_brcondi(dc, par[0], tmp, 0, arg[2]);
+ tcg_gen_and_i32(tmp, arg[0].in, bit);
+ gen_brcondi(dc, par[0], tmp, 0, arg[2].imm);
tcg_temp_free(tmp);
tcg_temp_free(bit);
}
-static void translate_bbi(DisasContext *dc, const uint32_t arg[],
+static void translate_bbi(DisasContext *dc, const OpcodeArg arg[],
const uint32_t par[])
{
TCGv_i32 tmp = tcg_temp_new_i32();
#ifdef TARGET_WORDS_BIGENDIAN
- tcg_gen_andi_i32(tmp, cpu_R[arg[0]], 0x80000000u >> arg[1]);
+ tcg_gen_andi_i32(tmp, arg[0].in, 0x80000000u >> arg[1].imm);
#else
- tcg_gen_andi_i32(tmp, cpu_R[arg[0]], 0x00000001u << arg[1]);
+ tcg_gen_andi_i32(tmp, arg[0].in, 0x00000001u << arg[1].imm);
#endif
- gen_brcondi(dc, par[0], tmp, 0, arg[2]);
+ gen_brcondi(dc, par[0], tmp, 0, arg[2].imm);
tcg_temp_free(tmp);
}
-static void translate_bi(DisasContext *dc, const uint32_t arg[],
+static void translate_bi(DisasContext *dc, const OpcodeArg arg[],
const uint32_t par[])
{
- gen_brcondi(dc, par[0], cpu_R[arg[0]], arg[1], arg[2]);
+ gen_brcondi(dc, par[0], arg[0].in, arg[1].imm, arg[2].imm);
}
-static void translate_bz(DisasContext *dc, const uint32_t arg[],
+static void translate_bz(DisasContext *dc, const OpcodeArg arg[],
const uint32_t par[])
{
- gen_brcondi(dc, par[0], cpu_R[arg[0]], 0, arg[1]);
+ gen_brcondi(dc, par[0], arg[0].in, 0, arg[1].imm);
}
enum {
@@ -1435,7 +1843,7 @@
BOOLEAN_XOR,
};
-static void translate_boolean(DisasContext *dc, const uint32_t arg[],
+static void translate_boolean(DisasContext *dc, const OpcodeArg arg[],
const uint32_t par[])
{
static void (* const op[])(TCGv_i32, TCGv_i32, TCGv_i32) = {
@@ -1449,114 +1857,110 @@
TCGv_i32 tmp1 = tcg_temp_new_i32();
TCGv_i32 tmp2 = tcg_temp_new_i32();
- tcg_gen_shri_i32(tmp1, cpu_SR[BR], arg[1]);
- tcg_gen_shri_i32(tmp2, cpu_SR[BR], arg[2]);
+ tcg_gen_shri_i32(tmp1, arg[1].in, arg[1].imm);
+ tcg_gen_shri_i32(tmp2, arg[2].in, arg[2].imm);
op[par[0]](tmp1, tmp1, tmp2);
- tcg_gen_deposit_i32(cpu_SR[BR], cpu_SR[BR], tmp1, arg[0], 1);
+ tcg_gen_deposit_i32(arg[0].out, arg[0].out, tmp1, arg[0].imm, 1);
tcg_temp_free(tmp1);
tcg_temp_free(tmp2);
}
-static void translate_bp(DisasContext *dc, const uint32_t arg[],
+static void translate_bp(DisasContext *dc, const OpcodeArg arg[],
const uint32_t par[])
{
TCGv_i32 tmp = tcg_temp_new_i32();
- tcg_gen_andi_i32(tmp, cpu_SR[BR], 1 << arg[0]);
- gen_brcondi(dc, par[0], tmp, 0, arg[1]);
+ tcg_gen_andi_i32(tmp, arg[0].in, 1 << arg[0].imm);
+ gen_brcondi(dc, par[0], tmp, 0, arg[1].imm);
tcg_temp_free(tmp);
}
-static void translate_call0(DisasContext *dc, const uint32_t arg[],
+static void translate_call0(DisasContext *dc, const OpcodeArg arg[],
const uint32_t par[])
{
tcg_gen_movi_i32(cpu_R[0], dc->base.pc_next);
- gen_jumpi(dc, arg[0], 0);
+ gen_jumpi(dc, arg[0].imm, 0);
}
-static uint32_t test_overflow_callw(DisasContext *dc, const uint32_t arg[],
- const uint32_t par[])
-{
- return 1 << (par[0] * 4);
-}
-
-static void translate_callw(DisasContext *dc, const uint32_t arg[],
+static void translate_callw(DisasContext *dc, const OpcodeArg arg[],
const uint32_t par[])
{
- gen_callwi(dc, par[0], arg[0], 0);
+ TCGv_i32 tmp = tcg_const_i32(arg[0].imm);
+ gen_callw_slot(dc, par[0], tmp, adjust_jump_slot(dc, arg[0].imm, 0));
+ tcg_temp_free(tmp);
}
-static void translate_callx0(DisasContext *dc, const uint32_t arg[],
+static void translate_callx0(DisasContext *dc, const OpcodeArg arg[],
const uint32_t par[])
{
TCGv_i32 tmp = tcg_temp_new_i32();
- tcg_gen_mov_i32(tmp, cpu_R[arg[0]]);
+ tcg_gen_mov_i32(tmp, arg[0].in);
tcg_gen_movi_i32(cpu_R[0], dc->base.pc_next);
gen_jump(dc, tmp);
tcg_temp_free(tmp);
}
-static void translate_callxw(DisasContext *dc, const uint32_t arg[],
+static void translate_callxw(DisasContext *dc, const OpcodeArg arg[],
const uint32_t par[])
{
TCGv_i32 tmp = tcg_temp_new_i32();
- tcg_gen_mov_i32(tmp, cpu_R[arg[0]]);
- gen_callw(dc, par[0], tmp);
+ tcg_gen_mov_i32(tmp, arg[0].in);
+ gen_callw_slot(dc, par[0], tmp, -1);
tcg_temp_free(tmp);
}
-static void translate_clamps(DisasContext *dc, const uint32_t arg[],
+static void translate_clamps(DisasContext *dc, const OpcodeArg arg[],
const uint32_t par[])
{
- TCGv_i32 tmp1 = tcg_const_i32(-1u << arg[2]);
- TCGv_i32 tmp2 = tcg_const_i32((1 << arg[2]) - 1);
+ TCGv_i32 tmp1 = tcg_const_i32(-1u << arg[2].imm);
+ TCGv_i32 tmp2 = tcg_const_i32((1 << arg[2].imm) - 1);
- tcg_gen_smax_i32(tmp1, tmp1, cpu_R[arg[1]]);
- tcg_gen_smin_i32(cpu_R[arg[0]], tmp1, tmp2);
+ tcg_gen_smax_i32(tmp1, tmp1, arg[1].in);
+ tcg_gen_smin_i32(arg[0].out, tmp1, tmp2);
tcg_temp_free(tmp1);
tcg_temp_free(tmp2);
}
-static void translate_clrb_expstate(DisasContext *dc, const uint32_t arg[],
+static void translate_clrb_expstate(DisasContext *dc, const OpcodeArg arg[],
const uint32_t par[])
{
/* TODO: GPIO32 may be a part of coprocessor */
- tcg_gen_andi_i32(cpu_UR[EXPSTATE], cpu_UR[EXPSTATE], ~(1u << arg[0]));
+ tcg_gen_andi_i32(cpu_UR[EXPSTATE], cpu_UR[EXPSTATE], ~(1u << arg[0].imm));
}
-static void translate_const16(DisasContext *dc, const uint32_t arg[],
+static void translate_const16(DisasContext *dc, const OpcodeArg arg[],
const uint32_t par[])
{
- TCGv_i32 c = tcg_const_i32(arg[1]);
+ TCGv_i32 c = tcg_const_i32(arg[1].imm);
- tcg_gen_deposit_i32(cpu_R[arg[0]], c, cpu_R[arg[0]], 16, 16);
+ tcg_gen_deposit_i32(arg[0].out, c, arg[0].in, 16, 16);
tcg_temp_free(c);
}
-static void translate_dcache(DisasContext *dc, const uint32_t arg[],
+static void translate_dcache(DisasContext *dc, const OpcodeArg arg[],
const uint32_t par[])
{
TCGv_i32 addr = tcg_temp_new_i32();
TCGv_i32 res = tcg_temp_new_i32();
- tcg_gen_addi_i32(addr, cpu_R[arg[0]], arg[1]);
+ tcg_gen_addi_i32(addr, arg[0].in, arg[1].imm);
tcg_gen_qemu_ld8u(res, addr, dc->cring);
tcg_temp_free(addr);
tcg_temp_free(res);
}
-static void translate_depbits(DisasContext *dc, const uint32_t arg[],
+static void translate_depbits(DisasContext *dc, const OpcodeArg arg[],
const uint32_t par[])
{
- tcg_gen_deposit_i32(cpu_R[arg[1]], cpu_R[arg[1]], cpu_R[arg[0]],
- arg[2], arg[3]);
+ tcg_gen_deposit_i32(arg[1].out, arg[1].in, arg[0].in,
+ arg[2].imm, arg[3].imm);
}
-static bool test_ill_entry(DisasContext *dc, const uint32_t arg[],
+static bool test_ill_entry(DisasContext *dc, const OpcodeArg arg[],
const uint32_t par[])
{
- if (arg[0] > 3 || !dc->cwoe) {
+ if (arg[0].imm > 3 || !dc->cwoe) {
qemu_log_mask(LOG_GUEST_ERROR,
"Illegal entry instruction(pc = %08x)\n", dc->pc);
return true;
@@ -1565,88 +1969,88 @@
}
}
-static uint32_t test_overflow_entry(DisasContext *dc, const uint32_t arg[],
+static uint32_t test_overflow_entry(DisasContext *dc, const OpcodeArg arg[],
const uint32_t par[])
{
return 1 << (dc->callinc * 4);
}
-static void translate_entry(DisasContext *dc, const uint32_t arg[],
+static void translate_entry(DisasContext *dc, const OpcodeArg arg[],
const uint32_t par[])
{
TCGv_i32 pc = tcg_const_i32(dc->pc);
- TCGv_i32 s = tcg_const_i32(arg[0]);
- TCGv_i32 imm = tcg_const_i32(arg[1]);
+ TCGv_i32 s = tcg_const_i32(arg[0].imm);
+ TCGv_i32 imm = tcg_const_i32(arg[1].imm);
gen_helper_entry(cpu_env, pc, s, imm);
tcg_temp_free(imm);
tcg_temp_free(s);
tcg_temp_free(pc);
}
-static void translate_extui(DisasContext *dc, const uint32_t arg[],
+static void translate_extui(DisasContext *dc, const OpcodeArg arg[],
const uint32_t par[])
{
- int maskimm = (1 << arg[3]) - 1;
+ int maskimm = (1 << arg[3].imm) - 1;
TCGv_i32 tmp = tcg_temp_new_i32();
- tcg_gen_shri_i32(tmp, cpu_R[arg[1]], arg[2]);
- tcg_gen_andi_i32(cpu_R[arg[0]], tmp, maskimm);
+ tcg_gen_shri_i32(tmp, arg[1].in, arg[2].imm);
+ tcg_gen_andi_i32(arg[0].out, tmp, maskimm);
tcg_temp_free(tmp);
}
-static void translate_icache(DisasContext *dc, const uint32_t arg[],
+static void translate_icache(DisasContext *dc, const OpcodeArg arg[],
const uint32_t par[])
{
#ifndef CONFIG_USER_ONLY
TCGv_i32 addr = tcg_temp_new_i32();
tcg_gen_movi_i32(cpu_pc, dc->pc);
- tcg_gen_addi_i32(addr, cpu_R[arg[0]], arg[1]);
+ tcg_gen_addi_i32(addr, arg[0].in, arg[1].imm);
gen_helper_itlb_hit_test(cpu_env, addr);
tcg_temp_free(addr);
#endif
}
-static void translate_itlb(DisasContext *dc, const uint32_t arg[],
+static void translate_itlb(DisasContext *dc, const OpcodeArg arg[],
const uint32_t par[])
{
#ifndef CONFIG_USER_ONLY
TCGv_i32 dtlb = tcg_const_i32(par[0]);
- gen_helper_itlb(cpu_env, cpu_R[arg[0]], dtlb);
+ gen_helper_itlb(cpu_env, arg[0].in, dtlb);
tcg_temp_free(dtlb);
#endif
}
-static void translate_j(DisasContext *dc, const uint32_t arg[],
+static void translate_j(DisasContext *dc, const OpcodeArg arg[],
const uint32_t par[])
{
- gen_jumpi(dc, arg[0], 0);
+ gen_jumpi(dc, arg[0].imm, 0);
}
-static void translate_jx(DisasContext *dc, const uint32_t arg[],
+static void translate_jx(DisasContext *dc, const OpcodeArg arg[],
const uint32_t par[])
{
- gen_jump(dc, cpu_R[arg[0]]);
+ gen_jump(dc, arg[0].in);
}
-static void translate_l32e(DisasContext *dc, const uint32_t arg[],
+static void translate_l32e(DisasContext *dc, const OpcodeArg arg[],
const uint32_t par[])
{
TCGv_i32 addr = tcg_temp_new_i32();
- tcg_gen_addi_i32(addr, cpu_R[arg[1]], arg[2]);
+ tcg_gen_addi_i32(addr, arg[1].in, arg[2].imm);
gen_load_store_alignment(dc, 2, addr, false);
- tcg_gen_qemu_ld_tl(cpu_R[arg[0]], addr, dc->ring, MO_TEUL);
+ tcg_gen_qemu_ld_tl(arg[0].out, addr, dc->ring, MO_TEUL);
tcg_temp_free(addr);
}
-static void translate_ldst(DisasContext *dc, const uint32_t arg[],
+static void translate_ldst(DisasContext *dc, const OpcodeArg arg[],
const uint32_t par[])
{
TCGv_i32 addr = tcg_temp_new_i32();
- tcg_gen_addi_i32(addr, cpu_R[arg[1]], arg[2]);
+ tcg_gen_addi_i32(addr, arg[1].in, arg[2].imm);
if (par[0] & MO_SIZE) {
gen_load_store_alignment(dc, par[0] & MO_SIZE, addr, par[1]);
}
@@ -1654,9 +2058,9 @@
if (par[1]) {
tcg_gen_mb(TCG_BAR_STRL | TCG_MO_ALL);
}
- tcg_gen_qemu_st_tl(cpu_R[arg[0]], addr, dc->cring, par[0]);
+ tcg_gen_qemu_st_tl(arg[0].in, addr, dc->cring, par[0]);
} else {
- tcg_gen_qemu_ld_tl(cpu_R[arg[0]], addr, dc->cring, par[0]);
+ tcg_gen_qemu_ld_tl(arg[0].out, addr, dc->cring, par[0]);
if (par[1]) {
tcg_gen_mb(TCG_BAR_LDAQ | TCG_MO_ALL);
}
@@ -1664,33 +2068,33 @@
tcg_temp_free(addr);
}
-static void translate_l32r(DisasContext *dc, const uint32_t arg[],
+static void translate_l32r(DisasContext *dc, const OpcodeArg arg[],
const uint32_t par[])
{
TCGv_i32 tmp;
if (dc->base.tb->flags & XTENSA_TBFLAG_LITBASE) {
- tmp = tcg_const_i32(dc->raw_arg[1] - 1);
+ tmp = tcg_const_i32(arg[1].raw_imm - 1);
tcg_gen_add_i32(tmp, cpu_SR[LITBASE], tmp);
} else {
- tmp = tcg_const_i32(arg[1]);
+ tmp = tcg_const_i32(arg[1].imm);
}
- tcg_gen_qemu_ld32u(cpu_R[arg[0]], tmp, dc->cring);
+ tcg_gen_qemu_ld32u(arg[0].out, tmp, dc->cring);
tcg_temp_free(tmp);
}
-static void translate_loop(DisasContext *dc, const uint32_t arg[],
+static void translate_loop(DisasContext *dc, const OpcodeArg arg[],
const uint32_t par[])
{
- uint32_t lend = arg[1];
+ uint32_t lend = arg[1].imm;
- tcg_gen_subi_i32(cpu_SR[LCOUNT], cpu_R[arg[0]], 1);
+ tcg_gen_subi_i32(cpu_SR[LCOUNT], arg[0].in, 1);
tcg_gen_movi_i32(cpu_SR[LBEG], dc->base.pc_next);
tcg_gen_movi_i32(cpu_SR[LEND], lend);
if (par[0] != TCG_COND_NEVER) {
TCGLabel *label = gen_new_label();
- tcg_gen_brcondi_i32(par[0], cpu_R[arg[0]], 0, label);
+ tcg_gen_brcondi_i32(par[0], arg[0].in, 0, label);
gen_jumpi(dc, lend, 1);
gen_set_label(label);
}
@@ -1716,41 +2120,25 @@
MAC16_XH = 0x2,
};
-enum {
- MAC16_AA,
- MAC16_AD,
- MAC16_DA,
- MAC16_DD,
-
- MAC16_XD = 0x1,
- MAC16_DX = 0x2,
-};
-
-static void translate_mac16(DisasContext *dc, const uint32_t arg[],
+static void translate_mac16(DisasContext *dc, const OpcodeArg arg[],
const uint32_t par[])
{
int op = par[0];
- bool is_m1_sr = par[1] & MAC16_DX;
- bool is_m2_sr = par[1] & MAC16_XD;
- unsigned half = par[2];
- uint32_t ld_offset = par[3];
+ unsigned half = par[1];
+ uint32_t ld_offset = par[2];
unsigned off = ld_offset ? 2 : 0;
TCGv_i32 vaddr = tcg_temp_new_i32();
TCGv_i32 mem32 = tcg_temp_new_i32();
if (ld_offset) {
- tcg_gen_addi_i32(vaddr, cpu_R[arg[1]], ld_offset);
+ tcg_gen_addi_i32(vaddr, arg[1].in, ld_offset);
gen_load_store_alignment(dc, 2, vaddr, false);
tcg_gen_qemu_ld32u(mem32, vaddr, dc->cring);
}
if (op != MAC16_NONE) {
- TCGv_i32 m1 = gen_mac16_m(is_m1_sr ?
- cpu_SR[MR + arg[off]] :
- cpu_R[arg[off]],
+ TCGv_i32 m1 = gen_mac16_m(arg[off].in,
half & MAC16_HX, op == MAC16_UMUL);
- TCGv_i32 m2 = gen_mac16_m(is_m2_sr ?
- cpu_SR[MR + arg[off + 1]] :
- cpu_R[arg[off + 1]],
+ TCGv_i32 m2 = gen_mac16_m(arg[off + 1].in,
half & MAC16_XH, op == MAC16_UMUL);
if (op == MAC16_MUL || op == MAC16_UMUL) {
@@ -1784,221 +2172,221 @@
tcg_temp_free(m2);
}
if (ld_offset) {
- tcg_gen_mov_i32(cpu_R[arg[1]], vaddr);
- tcg_gen_mov_i32(cpu_SR[MR + arg[0]], mem32);
+ tcg_gen_mov_i32(arg[1].out, vaddr);
+ tcg_gen_mov_i32(cpu_SR[MR + arg[0].imm], mem32);
}
tcg_temp_free(vaddr);
tcg_temp_free(mem32);
}
-static void translate_memw(DisasContext *dc, const uint32_t arg[],
+static void translate_memw(DisasContext *dc, const OpcodeArg arg[],
const uint32_t par[])
{
tcg_gen_mb(TCG_BAR_SC | TCG_MO_ALL);
}
-static void translate_smin(DisasContext *dc, const uint32_t arg[],
+static void translate_smin(DisasContext *dc, const OpcodeArg arg[],
const uint32_t par[])
{
- tcg_gen_smin_i32(cpu_R[arg[0]], cpu_R[arg[1]], cpu_R[arg[2]]);
+ tcg_gen_smin_i32(arg[0].out, arg[1].in, arg[2].in);
}
-static void translate_umin(DisasContext *dc, const uint32_t arg[],
+static void translate_umin(DisasContext *dc, const OpcodeArg arg[],
const uint32_t par[])
{
- tcg_gen_umin_i32(cpu_R[arg[0]], cpu_R[arg[1]], cpu_R[arg[2]]);
+ tcg_gen_umin_i32(arg[0].out, arg[1].in, arg[2].in);
}
-static void translate_smax(DisasContext *dc, const uint32_t arg[],
+static void translate_smax(DisasContext *dc, const OpcodeArg arg[],
const uint32_t par[])
{
- tcg_gen_smax_i32(cpu_R[arg[0]], cpu_R[arg[1]], cpu_R[arg[2]]);
+ tcg_gen_smax_i32(arg[0].out, arg[1].in, arg[2].in);
}
-static void translate_umax(DisasContext *dc, const uint32_t arg[],
+static void translate_umax(DisasContext *dc, const OpcodeArg arg[],
const uint32_t par[])
{
- tcg_gen_umax_i32(cpu_R[arg[0]], cpu_R[arg[1]], cpu_R[arg[2]]);
+ tcg_gen_umax_i32(arg[0].out, arg[1].in, arg[2].in);
}
-static void translate_mov(DisasContext *dc, const uint32_t arg[],
+static void translate_mov(DisasContext *dc, const OpcodeArg arg[],
const uint32_t par[])
{
- tcg_gen_mov_i32(cpu_R[arg[0]], cpu_R[arg[1]]);
+ tcg_gen_mov_i32(arg[0].out, arg[1].in);
}
-static void translate_movcond(DisasContext *dc, const uint32_t arg[],
+static void translate_movcond(DisasContext *dc, const OpcodeArg arg[],
const uint32_t par[])
{
TCGv_i32 zero = tcg_const_i32(0);
- tcg_gen_movcond_i32(par[0], cpu_R[arg[0]],
- cpu_R[arg[2]], zero, cpu_R[arg[1]], cpu_R[arg[0]]);
+ tcg_gen_movcond_i32(par[0], arg[0].out,
+ arg[2].in, zero, arg[1].in, arg[0].in);
tcg_temp_free(zero);
}
-static void translate_movi(DisasContext *dc, const uint32_t arg[],
+static void translate_movi(DisasContext *dc, const OpcodeArg arg[],
const uint32_t par[])
{
- tcg_gen_movi_i32(cpu_R[arg[0]], arg[1]);
+ tcg_gen_movi_i32(arg[0].out, arg[1].imm);
}
-static void translate_movp(DisasContext *dc, const uint32_t arg[],
+static void translate_movp(DisasContext *dc, const OpcodeArg arg[],
const uint32_t par[])
{
TCGv_i32 zero = tcg_const_i32(0);
TCGv_i32 tmp = tcg_temp_new_i32();
- tcg_gen_andi_i32(tmp, cpu_SR[BR], 1 << arg[2]);
+ tcg_gen_andi_i32(tmp, arg[2].in, 1 << arg[2].imm);
tcg_gen_movcond_i32(par[0],
- cpu_R[arg[0]], tmp, zero,
- cpu_R[arg[1]], cpu_R[arg[0]]);
+ arg[0].out, tmp, zero,
+ arg[1].in, arg[0].in);
tcg_temp_free(tmp);
tcg_temp_free(zero);
}
-static void translate_movsp(DisasContext *dc, const uint32_t arg[],
+static void translate_movsp(DisasContext *dc, const OpcodeArg arg[],
const uint32_t par[])
{
- tcg_gen_mov_i32(cpu_R[arg[0]], cpu_R[arg[1]]);
+ tcg_gen_mov_i32(arg[0].out, arg[1].in);
}
-static void translate_mul16(DisasContext *dc, const uint32_t arg[],
+static void translate_mul16(DisasContext *dc, const OpcodeArg arg[],
const uint32_t par[])
{
TCGv_i32 v1 = tcg_temp_new_i32();
TCGv_i32 v2 = tcg_temp_new_i32();
if (par[0]) {
- tcg_gen_ext16s_i32(v1, cpu_R[arg[1]]);
- tcg_gen_ext16s_i32(v2, cpu_R[arg[2]]);
+ tcg_gen_ext16s_i32(v1, arg[1].in);
+ tcg_gen_ext16s_i32(v2, arg[2].in);
} else {
- tcg_gen_ext16u_i32(v1, cpu_R[arg[1]]);
- tcg_gen_ext16u_i32(v2, cpu_R[arg[2]]);
+ tcg_gen_ext16u_i32(v1, arg[1].in);
+ tcg_gen_ext16u_i32(v2, arg[2].in);
}
- tcg_gen_mul_i32(cpu_R[arg[0]], v1, v2);
+ tcg_gen_mul_i32(arg[0].out, v1, v2);
tcg_temp_free(v2);
tcg_temp_free(v1);
}
-static void translate_mull(DisasContext *dc, const uint32_t arg[],
+static void translate_mull(DisasContext *dc, const OpcodeArg arg[],
const uint32_t par[])
{
- tcg_gen_mul_i32(cpu_R[arg[0]], cpu_R[arg[1]], cpu_R[arg[2]]);
+ tcg_gen_mul_i32(arg[0].out, arg[1].in, arg[2].in);
}
-static void translate_mulh(DisasContext *dc, const uint32_t arg[],
+static void translate_mulh(DisasContext *dc, const OpcodeArg arg[],
const uint32_t par[])
{
TCGv_i32 lo = tcg_temp_new();
if (par[0]) {
- tcg_gen_muls2_i32(lo, cpu_R[arg[0]], cpu_R[arg[1]], cpu_R[arg[2]]);
+ tcg_gen_muls2_i32(lo, arg[0].out, arg[1].in, arg[2].in);
} else {
- tcg_gen_mulu2_i32(lo, cpu_R[arg[0]], cpu_R[arg[1]], cpu_R[arg[2]]);
+ tcg_gen_mulu2_i32(lo, arg[0].out, arg[1].in, arg[2].in);
}
tcg_temp_free(lo);
}
-static void translate_neg(DisasContext *dc, const uint32_t arg[],
+static void translate_neg(DisasContext *dc, const OpcodeArg arg[],
const uint32_t par[])
{
- tcg_gen_neg_i32(cpu_R[arg[0]], cpu_R[arg[1]]);
+ tcg_gen_neg_i32(arg[0].out, arg[1].in);
}
-static void translate_nop(DisasContext *dc, const uint32_t arg[],
+static void translate_nop(DisasContext *dc, const OpcodeArg arg[],
const uint32_t par[])
{
}
-static void translate_nsa(DisasContext *dc, const uint32_t arg[],
+static void translate_nsa(DisasContext *dc, const OpcodeArg arg[],
const uint32_t par[])
{
- tcg_gen_clrsb_i32(cpu_R[arg[0]], cpu_R[arg[1]]);
+ tcg_gen_clrsb_i32(arg[0].out, arg[1].in);
}
-static void translate_nsau(DisasContext *dc, const uint32_t arg[],
+static void translate_nsau(DisasContext *dc, const OpcodeArg arg[],
const uint32_t par[])
{
- tcg_gen_clzi_i32(cpu_R[arg[0]], cpu_R[arg[1]], 32);
+ tcg_gen_clzi_i32(arg[0].out, arg[1].in, 32);
}
-static void translate_or(DisasContext *dc, const uint32_t arg[],
+static void translate_or(DisasContext *dc, const OpcodeArg arg[],
const uint32_t par[])
{
- tcg_gen_or_i32(cpu_R[arg[0]], cpu_R[arg[1]], cpu_R[arg[2]]);
+ tcg_gen_or_i32(arg[0].out, arg[1].in, arg[2].in);
}
-static void translate_ptlb(DisasContext *dc, const uint32_t arg[],
+static void translate_ptlb(DisasContext *dc, const OpcodeArg arg[],
const uint32_t par[])
{
#ifndef CONFIG_USER_ONLY
TCGv_i32 dtlb = tcg_const_i32(par[0]);
tcg_gen_movi_i32(cpu_pc, dc->pc);
- gen_helper_ptlb(cpu_R[arg[0]], cpu_env, cpu_R[arg[1]], dtlb);
+ gen_helper_ptlb(arg[0].out, cpu_env, arg[1].in, dtlb);
tcg_temp_free(dtlb);
#endif
}
-static void translate_quos(DisasContext *dc, const uint32_t arg[],
+static void translate_quos(DisasContext *dc, const OpcodeArg arg[],
const uint32_t par[])
{
TCGLabel *label1 = gen_new_label();
TCGLabel *label2 = gen_new_label();
- tcg_gen_brcondi_i32(TCG_COND_NE, cpu_R[arg[1]], 0x80000000,
+ tcg_gen_brcondi_i32(TCG_COND_NE, arg[1].in, 0x80000000,
label1);
- tcg_gen_brcondi_i32(TCG_COND_NE, cpu_R[arg[2]], 0xffffffff,
+ tcg_gen_brcondi_i32(TCG_COND_NE, arg[2].in, 0xffffffff,
label1);
- tcg_gen_movi_i32(cpu_R[arg[0]],
+ tcg_gen_movi_i32(arg[0].out,
par[0] ? 0x80000000 : 0);
tcg_gen_br(label2);
gen_set_label(label1);
if (par[0]) {
- tcg_gen_div_i32(cpu_R[arg[0]],
- cpu_R[arg[1]], cpu_R[arg[2]]);
+ tcg_gen_div_i32(arg[0].out,
+ arg[1].in, arg[2].in);
} else {
- tcg_gen_rem_i32(cpu_R[arg[0]],
- cpu_R[arg[1]], cpu_R[arg[2]]);
+ tcg_gen_rem_i32(arg[0].out,
+ arg[1].in, arg[2].in);
}
gen_set_label(label2);
}
-static void translate_quou(DisasContext *dc, const uint32_t arg[],
+static void translate_quou(DisasContext *dc, const OpcodeArg arg[],
const uint32_t par[])
{
- tcg_gen_divu_i32(cpu_R[arg[0]],
- cpu_R[arg[1]], cpu_R[arg[2]]);
+ tcg_gen_divu_i32(arg[0].out,
+ arg[1].in, arg[2].in);
}
-static void translate_read_impwire(DisasContext *dc, const uint32_t arg[],
+static void translate_read_impwire(DisasContext *dc, const OpcodeArg arg[],
const uint32_t par[])
{
/* TODO: GPIO32 may be a part of coprocessor */
- tcg_gen_movi_i32(cpu_R[arg[0]], 0);
+ tcg_gen_movi_i32(arg[0].out, 0);
}
-static void translate_remu(DisasContext *dc, const uint32_t arg[],
+static void translate_remu(DisasContext *dc, const OpcodeArg arg[],
const uint32_t par[])
{
- tcg_gen_remu_i32(cpu_R[arg[0]],
- cpu_R[arg[1]], cpu_R[arg[2]]);
+ tcg_gen_remu_i32(arg[0].out,
+ arg[1].in, arg[2].in);
}
-static void translate_rer(DisasContext *dc, const uint32_t arg[],
+static void translate_rer(DisasContext *dc, const OpcodeArg arg[],
const uint32_t par[])
{
- gen_helper_rer(cpu_R[arg[0]], cpu_env, cpu_R[arg[1]]);
+ gen_helper_rer(arg[0].out, cpu_env, arg[1].in);
}
-static void translate_ret(DisasContext *dc, const uint32_t arg[],
+static void translate_ret(DisasContext *dc, const OpcodeArg arg[],
const uint32_t par[])
{
gen_jump(dc, cpu_R[0]);
}
-static bool test_ill_retw(DisasContext *dc, const uint32_t arg[],
+static bool test_ill_retw(DisasContext *dc, const OpcodeArg arg[],
const uint32_t par[])
{
if (!dc->cwoe) {
@@ -2014,36 +2402,41 @@
}
}
-static void translate_retw(DisasContext *dc, const uint32_t arg[],
+static void translate_retw(DisasContext *dc, const OpcodeArg arg[],
const uint32_t par[])
{
- TCGv_i32 tmp = tcg_const_i32(dc->pc);
- gen_helper_retw(tmp, cpu_env, tmp);
+ TCGv_i32 tmp = tcg_const_i32(1);
+ tcg_gen_shl_i32(tmp, tmp, cpu_SR[WINDOW_BASE]);
+ tcg_gen_andc_i32(cpu_SR[WINDOW_START],
+ cpu_SR[WINDOW_START], tmp);
+ tcg_gen_movi_i32(tmp, dc->pc);
+ tcg_gen_deposit_i32(tmp, tmp, cpu_R[0], 0, 30);
+ gen_helper_retw(cpu_env, cpu_R[0]);
gen_jump(dc, tmp);
tcg_temp_free(tmp);
}
-static void translate_rfde(DisasContext *dc, const uint32_t arg[],
+static void translate_rfde(DisasContext *dc, const OpcodeArg arg[],
const uint32_t par[])
{
gen_jump(dc, cpu_SR[dc->config->ndepc ? DEPC : EPC1]);
}
-static void translate_rfe(DisasContext *dc, const uint32_t arg[],
+static void translate_rfe(DisasContext *dc, const OpcodeArg arg[],
const uint32_t par[])
{
tcg_gen_andi_i32(cpu_SR[PS], cpu_SR[PS], ~PS_EXCM);
gen_jump(dc, cpu_SR[EPC1]);
}
-static void translate_rfi(DisasContext *dc, const uint32_t arg[],
+static void translate_rfi(DisasContext *dc, const OpcodeArg arg[],
const uint32_t par[])
{
- tcg_gen_mov_i32(cpu_SR[PS], cpu_SR[EPS2 + arg[0] - 2]);
- gen_jump(dc, cpu_SR[EPC1 + arg[0] - 1]);
+ tcg_gen_mov_i32(cpu_SR[PS], cpu_SR[EPS2 + arg[0].imm - 2]);
+ gen_jump(dc, cpu_SR[EPC1 + arg[0].imm - 1]);
}
-static void translate_rfw(DisasContext *dc, const uint32_t arg[],
+static void translate_rfw(DisasContext *dc, const OpcodeArg arg[],
const uint32_t par[])
{
TCGv_i32 tmp = tcg_const_i32(1);
@@ -2064,35 +2457,33 @@
gen_jump(dc, cpu_SR[EPC1]);
}
-static void translate_rotw(DisasContext *dc, const uint32_t arg[],
+static void translate_rotw(DisasContext *dc, const OpcodeArg arg[],
const uint32_t par[])
{
- TCGv_i32 tmp = tcg_const_i32(arg[0]);
- gen_helper_rotw(cpu_env, tmp);
- tcg_temp_free(tmp);
+ tcg_gen_addi_i32(cpu_windowbase_next, cpu_SR[WINDOW_BASE], arg[0].imm);
}
-static void translate_rsil(DisasContext *dc, const uint32_t arg[],
+static void translate_rsil(DisasContext *dc, const OpcodeArg arg[],
const uint32_t par[])
{
- tcg_gen_mov_i32(cpu_R[arg[0]], cpu_SR[PS]);
+ tcg_gen_mov_i32(arg[0].out, cpu_SR[PS]);
tcg_gen_andi_i32(cpu_SR[PS], cpu_SR[PS], ~PS_INTLEVEL);
- tcg_gen_ori_i32(cpu_SR[PS], cpu_SR[PS], arg[1]);
+ tcg_gen_ori_i32(cpu_SR[PS], cpu_SR[PS], arg[1].imm);
}
-static bool test_ill_rsr(DisasContext *dc, const uint32_t arg[],
+static bool test_ill_rsr(DisasContext *dc, const OpcodeArg arg[],
const uint32_t par[])
{
return !check_sr(dc, par[0], SR_R);
}
-static void translate_rsr(DisasContext *dc, const uint32_t arg[],
+static void translate_rsr(DisasContext *dc, const OpcodeArg arg[],
const uint32_t par[])
{
- gen_rsr(dc, cpu_R[arg[0]], par[0]);
+ gen_rsr(dc, arg[0].out, par[0]);
}
-static void translate_rtlb(DisasContext *dc, const uint32_t arg[],
+static void translate_rtlb(DisasContext *dc, const OpcodeArg arg[],
const uint32_t par[])
{
#ifndef CONFIG_USER_ONLY
@@ -2103,26 +2494,26 @@
};
TCGv_i32 dtlb = tcg_const_i32(par[0]);
- helper[par[1]](cpu_R[arg[0]], cpu_env, cpu_R[arg[1]], dtlb);
+ helper[par[1]](arg[0].out, cpu_env, arg[1].in, dtlb);
tcg_temp_free(dtlb);
#endif
}
-static void translate_rur(DisasContext *dc, const uint32_t arg[],
+static void translate_rur(DisasContext *dc, const OpcodeArg arg[],
const uint32_t par[])
{
if (uregnames[par[0]].name) {
- tcg_gen_mov_i32(cpu_R[arg[0]], cpu_UR[par[0]]);
+ tcg_gen_mov_i32(arg[0].out, cpu_UR[par[0]]);
} else {
qemu_log_mask(LOG_UNIMP, "RUR %d not implemented\n", par[0]);
}
}
-static void translate_setb_expstate(DisasContext *dc, const uint32_t arg[],
+static void translate_setb_expstate(DisasContext *dc, const OpcodeArg arg[],
const uint32_t par[])
{
/* TODO: GPIO32 may be a part of coprocessor */
- tcg_gen_ori_i32(cpu_UR[EXPSTATE], cpu_UR[EXPSTATE], 1u << arg[0]);
+ tcg_gen_ori_i32(cpu_UR[EXPSTATE], cpu_UR[EXPSTATE], 1u << arg[0].imm);
}
#ifdef CONFIG_USER_ONLY
@@ -2139,59 +2530,59 @@
}
#endif
-static void translate_s32c1i(DisasContext *dc, const uint32_t arg[],
+static void translate_s32c1i(DisasContext *dc, const OpcodeArg arg[],
const uint32_t par[])
{
TCGv_i32 tmp = tcg_temp_local_new_i32();
TCGv_i32 addr = tcg_temp_local_new_i32();
- tcg_gen_mov_i32(tmp, cpu_R[arg[0]]);
- tcg_gen_addi_i32(addr, cpu_R[arg[1]], arg[2]);
+ tcg_gen_mov_i32(tmp, arg[0].in);
+ tcg_gen_addi_i32(addr, arg[1].in, arg[2].imm);
gen_load_store_alignment(dc, 2, addr, true);
gen_check_atomctl(dc, addr);
- tcg_gen_atomic_cmpxchg_i32(cpu_R[arg[0]], addr, cpu_SR[SCOMPARE1],
+ tcg_gen_atomic_cmpxchg_i32(arg[0].out, addr, cpu_SR[SCOMPARE1],
tmp, dc->cring, MO_TEUL);
tcg_temp_free(addr);
tcg_temp_free(tmp);
}
-static void translate_s32e(DisasContext *dc, const uint32_t arg[],
+static void translate_s32e(DisasContext *dc, const OpcodeArg arg[],
const uint32_t par[])
{
TCGv_i32 addr = tcg_temp_new_i32();
- tcg_gen_addi_i32(addr, cpu_R[arg[1]], arg[2]);
+ tcg_gen_addi_i32(addr, arg[1].in, arg[2].imm);
gen_load_store_alignment(dc, 2, addr, false);
- tcg_gen_qemu_st_tl(cpu_R[arg[0]], addr, dc->ring, MO_TEUL);
+ tcg_gen_qemu_st_tl(arg[0].in, addr, dc->ring, MO_TEUL);
tcg_temp_free(addr);
}
-static void translate_salt(DisasContext *dc, const uint32_t arg[],
+static void translate_salt(DisasContext *dc, const OpcodeArg arg[],
const uint32_t par[])
{
tcg_gen_setcond_i32(par[0],
- cpu_R[arg[0]],
- cpu_R[arg[1]], cpu_R[arg[2]]);
+ arg[0].out,
+ arg[1].in, arg[2].in);
}
-static void translate_sext(DisasContext *dc, const uint32_t arg[],
+static void translate_sext(DisasContext *dc, const OpcodeArg arg[],
const uint32_t par[])
{
- int shift = 31 - arg[2];
+ int shift = 31 - arg[2].imm;
if (shift == 24) {
- tcg_gen_ext8s_i32(cpu_R[arg[0]], cpu_R[arg[1]]);
+ tcg_gen_ext8s_i32(arg[0].out, arg[1].in);
} else if (shift == 16) {
- tcg_gen_ext16s_i32(cpu_R[arg[0]], cpu_R[arg[1]]);
+ tcg_gen_ext16s_i32(arg[0].out, arg[1].in);
} else {
TCGv_i32 tmp = tcg_temp_new_i32();
- tcg_gen_shli_i32(tmp, cpu_R[arg[1]], shift);
- tcg_gen_sari_i32(cpu_R[arg[0]], tmp, shift);
+ tcg_gen_shli_i32(tmp, arg[1].in, shift);
+ tcg_gen_sari_i32(arg[0].out, tmp, shift);
tcg_temp_free(tmp);
}
}
-static bool test_ill_simcall(DisasContext *dc, const uint32_t arg[],
+static bool test_ill_simcall(DisasContext *dc, const OpcodeArg arg[],
const uint32_t par[])
{
#ifdef CONFIG_USER_ONLY
@@ -2205,7 +2596,7 @@
return ill;
}
-static void translate_simcall(DisasContext *dc, const uint32_t arg[],
+static void translate_simcall(DisasContext *dc, const OpcodeArg arg[],
const uint32_t par[])
{
#ifndef CONFIG_USER_ONLY
@@ -2221,73 +2612,73 @@
TCGv_i64 tmp = tcg_temp_new_i64(); \
tcg_gen_extu_i32_i64(tmp, reg); \
tcg_gen_##cmd##_i64(v, v, tmp); \
- tcg_gen_extrl_i64_i32(cpu_R[arg[0]], v); \
+ tcg_gen_extrl_i64_i32(arg[0].out, v); \
tcg_temp_free_i64(v); \
tcg_temp_free_i64(tmp); \
} while (0)
#define gen_shift(cmd) gen_shift_reg(cmd, cpu_SR[SAR])
-static void translate_sll(DisasContext *dc, const uint32_t arg[],
+static void translate_sll(DisasContext *dc, const OpcodeArg arg[],
const uint32_t par[])
{
if (dc->sar_m32_5bit) {
- tcg_gen_shl_i32(cpu_R[arg[0]], cpu_R[arg[1]], dc->sar_m32);
+ tcg_gen_shl_i32(arg[0].out, arg[1].in, dc->sar_m32);
} else {
TCGv_i64 v = tcg_temp_new_i64();
TCGv_i32 s = tcg_const_i32(32);
tcg_gen_sub_i32(s, s, cpu_SR[SAR]);
tcg_gen_andi_i32(s, s, 0x3f);
- tcg_gen_extu_i32_i64(v, cpu_R[arg[1]]);
+ tcg_gen_extu_i32_i64(v, arg[1].in);
gen_shift_reg(shl, s);
tcg_temp_free(s);
}
}
-static void translate_slli(DisasContext *dc, const uint32_t arg[],
+static void translate_slli(DisasContext *dc, const OpcodeArg arg[],
const uint32_t par[])
{
- if (arg[2] == 32) {
+ if (arg[2].imm == 32) {
qemu_log_mask(LOG_GUEST_ERROR, "slli a%d, a%d, 32 is undefined\n",
- arg[0], arg[1]);
+ arg[0].imm, arg[1].imm);
}
- tcg_gen_shli_i32(cpu_R[arg[0]], cpu_R[arg[1]], arg[2] & 0x1f);
+ tcg_gen_shli_i32(arg[0].out, arg[1].in, arg[2].imm & 0x1f);
}
-static void translate_sra(DisasContext *dc, const uint32_t arg[],
+static void translate_sra(DisasContext *dc, const OpcodeArg arg[],
const uint32_t par[])
{
if (dc->sar_m32_5bit) {
- tcg_gen_sar_i32(cpu_R[arg[0]], cpu_R[arg[1]], cpu_SR[SAR]);
+ tcg_gen_sar_i32(arg[0].out, arg[1].in, cpu_SR[SAR]);
} else {
TCGv_i64 v = tcg_temp_new_i64();
- tcg_gen_ext_i32_i64(v, cpu_R[arg[1]]);
+ tcg_gen_ext_i32_i64(v, arg[1].in);
gen_shift(sar);
}
}
-static void translate_srai(DisasContext *dc, const uint32_t arg[],
+static void translate_srai(DisasContext *dc, const OpcodeArg arg[],
const uint32_t par[])
{
- tcg_gen_sari_i32(cpu_R[arg[0]], cpu_R[arg[1]], arg[2]);
+ tcg_gen_sari_i32(arg[0].out, arg[1].in, arg[2].imm);
}
-static void translate_src(DisasContext *dc, const uint32_t arg[],
+static void translate_src(DisasContext *dc, const OpcodeArg arg[],
const uint32_t par[])
{
TCGv_i64 v = tcg_temp_new_i64();
- tcg_gen_concat_i32_i64(v, cpu_R[arg[2]], cpu_R[arg[1]]);
+ tcg_gen_concat_i32_i64(v, arg[2].in, arg[1].in);
gen_shift(shr);
}
-static void translate_srl(DisasContext *dc, const uint32_t arg[],
+static void translate_srl(DisasContext *dc, const OpcodeArg arg[],
const uint32_t par[])
{
if (dc->sar_m32_5bit) {
- tcg_gen_shr_i32(cpu_R[arg[0]], cpu_R[arg[1]], cpu_SR[SAR]);
+ tcg_gen_shr_i32(arg[0].out, arg[1].in, cpu_SR[SAR]);
} else {
TCGv_i64 v = tcg_temp_new_i64();
- tcg_gen_extu_i32_i64(v, cpu_R[arg[1]]);
+ tcg_gen_extu_i32_i64(v, arg[1].in);
gen_shift(shr);
}
}
@@ -2295,138 +2686,138 @@
#undef gen_shift
#undef gen_shift_reg
-static void translate_srli(DisasContext *dc, const uint32_t arg[],
+static void translate_srli(DisasContext *dc, const OpcodeArg arg[],
const uint32_t par[])
{
- tcg_gen_shri_i32(cpu_R[arg[0]], cpu_R[arg[1]], arg[2]);
+ tcg_gen_shri_i32(arg[0].out, arg[1].in, arg[2].imm);
}
-static void translate_ssa8b(DisasContext *dc, const uint32_t arg[],
+static void translate_ssa8b(DisasContext *dc, const OpcodeArg arg[],
const uint32_t par[])
{
TCGv_i32 tmp = tcg_temp_new_i32();
- tcg_gen_shli_i32(tmp, cpu_R[arg[0]], 3);
+ tcg_gen_shli_i32(tmp, arg[0].in, 3);
gen_left_shift_sar(dc, tmp);
tcg_temp_free(tmp);
}
-static void translate_ssa8l(DisasContext *dc, const uint32_t arg[],
+static void translate_ssa8l(DisasContext *dc, const OpcodeArg arg[],
const uint32_t par[])
{
TCGv_i32 tmp = tcg_temp_new_i32();
- tcg_gen_shli_i32(tmp, cpu_R[arg[0]], 3);
+ tcg_gen_shli_i32(tmp, arg[0].in, 3);
gen_right_shift_sar(dc, tmp);
tcg_temp_free(tmp);
}
-static void translate_ssai(DisasContext *dc, const uint32_t arg[],
+static void translate_ssai(DisasContext *dc, const OpcodeArg arg[],
const uint32_t par[])
{
- TCGv_i32 tmp = tcg_const_i32(arg[0]);
+ TCGv_i32 tmp = tcg_const_i32(arg[0].imm);
gen_right_shift_sar(dc, tmp);
tcg_temp_free(tmp);
}
-static void translate_ssl(DisasContext *dc, const uint32_t arg[],
+static void translate_ssl(DisasContext *dc, const OpcodeArg arg[],
const uint32_t par[])
{
- gen_left_shift_sar(dc, cpu_R[arg[0]]);
+ gen_left_shift_sar(dc, arg[0].in);
}
-static void translate_ssr(DisasContext *dc, const uint32_t arg[],
+static void translate_ssr(DisasContext *dc, const OpcodeArg arg[],
const uint32_t par[])
{
- gen_right_shift_sar(dc, cpu_R[arg[0]]);
+ gen_right_shift_sar(dc, arg[0].in);
}
-static void translate_sub(DisasContext *dc, const uint32_t arg[],
+static void translate_sub(DisasContext *dc, const OpcodeArg arg[],
const uint32_t par[])
{
- tcg_gen_sub_i32(cpu_R[arg[0]], cpu_R[arg[1]], cpu_R[arg[2]]);
+ tcg_gen_sub_i32(arg[0].out, arg[1].in, arg[2].in);
}
-static void translate_subx(DisasContext *dc, const uint32_t arg[],
+static void translate_subx(DisasContext *dc, const OpcodeArg arg[],
const uint32_t par[])
{
TCGv_i32 tmp = tcg_temp_new_i32();
- tcg_gen_shli_i32(tmp, cpu_R[arg[1]], par[0]);
- tcg_gen_sub_i32(cpu_R[arg[0]], tmp, cpu_R[arg[2]]);
+ tcg_gen_shli_i32(tmp, arg[1].in, par[0]);
+ tcg_gen_sub_i32(arg[0].out, tmp, arg[2].in);
tcg_temp_free(tmp);
}
-static void translate_waiti(DisasContext *dc, const uint32_t arg[],
+static void translate_waiti(DisasContext *dc, const OpcodeArg arg[],
const uint32_t par[])
{
#ifndef CONFIG_USER_ONLY
- gen_waiti(dc, arg[0]);
+ gen_waiti(dc, arg[0].imm);
#endif
}
-static void translate_wtlb(DisasContext *dc, const uint32_t arg[],
+static void translate_wtlb(DisasContext *dc, const OpcodeArg arg[],
const uint32_t par[])
{
#ifndef CONFIG_USER_ONLY
TCGv_i32 dtlb = tcg_const_i32(par[0]);
- gen_helper_wtlb(cpu_env, cpu_R[arg[0]], cpu_R[arg[1]], dtlb);
+ gen_helper_wtlb(cpu_env, arg[0].in, arg[1].in, dtlb);
tcg_temp_free(dtlb);
#endif
}
-static void translate_wer(DisasContext *dc, const uint32_t arg[],
+static void translate_wer(DisasContext *dc, const OpcodeArg arg[],
const uint32_t par[])
{
- gen_helper_wer(cpu_env, cpu_R[arg[0]], cpu_R[arg[1]]);
+ gen_helper_wer(cpu_env, arg[0].in, arg[1].in);
}
-static void translate_wrmsk_expstate(DisasContext *dc, const uint32_t arg[],
+static void translate_wrmsk_expstate(DisasContext *dc, const OpcodeArg arg[],
const uint32_t par[])
{
/* TODO: GPIO32 may be a part of coprocessor */
- tcg_gen_and_i32(cpu_UR[EXPSTATE], cpu_R[arg[0]], cpu_R[arg[1]]);
+ tcg_gen_and_i32(cpu_UR[EXPSTATE], arg[0].in, arg[1].in);
}
-static bool test_ill_wsr(DisasContext *dc, const uint32_t arg[],
+static bool test_ill_wsr(DisasContext *dc, const OpcodeArg arg[],
const uint32_t par[])
{
return !check_sr(dc, par[0], SR_W);
}
-static void translate_wsr(DisasContext *dc, const uint32_t arg[],
+static void translate_wsr(DisasContext *dc, const OpcodeArg arg[],
const uint32_t par[])
{
- gen_wsr(dc, par[0], cpu_R[arg[0]]);
+ gen_wsr(dc, par[0], arg[0].in);
}
-static void translate_wur(DisasContext *dc, const uint32_t arg[],
+static void translate_wur(DisasContext *dc, const OpcodeArg arg[],
const uint32_t par[])
{
if (uregnames[par[0]].name) {
- gen_wur(par[0], cpu_R[arg[0]]);
+ gen_wur(par[0], arg[0].in);
} else {
qemu_log_mask(LOG_UNIMP, "WUR %d not implemented\n", par[0]);
}
}
-static void translate_xor(DisasContext *dc, const uint32_t arg[],
+static void translate_xor(DisasContext *dc, const OpcodeArg arg[],
const uint32_t par[])
{
- tcg_gen_xor_i32(cpu_R[arg[0]], cpu_R[arg[1]], cpu_R[arg[2]]);
+ tcg_gen_xor_i32(arg[0].out, arg[1].in, arg[2].in);
}
-static bool test_ill_xsr(DisasContext *dc, const uint32_t arg[],
+static bool test_ill_xsr(DisasContext *dc, const OpcodeArg arg[],
const uint32_t par[])
{
return !check_sr(dc, par[0], SR_X);
}
-static void translate_xsr(DisasContext *dc, const uint32_t arg[],
+static void translate_xsr(DisasContext *dc, const OpcodeArg arg[],
const uint32_t par[])
{
TCGv_i32 tmp = tcg_temp_new_i32();
- tcg_gen_mov_i32(tmp, cpu_R[arg[0]]);
- gen_rsr(dc, cpu_R[arg[0]], par[0]);
+ tcg_gen_mov_i32(tmp, arg[0].in);
+ gen_rsr(dc, arg[0].out, par[0]);
gen_wsr(dc, par[0], tmp);
tcg_temp_free(tmp);
}
@@ -2435,42 +2826,33 @@
{
.name = "abs",
.translate = translate_abs,
- .windowed_register_op = 0x3,
}, {
- .name = "add",
+ .name = (const char * const[]) {
+ "add", "add.n", NULL,
+ },
.translate = translate_add,
- .windowed_register_op = 0x7,
+ .op_flags = XTENSA_OP_NAME_ARRAY,
}, {
- .name = "add.n",
- .translate = translate_add,
- .windowed_register_op = 0x7,
- }, {
- .name = "addi",
+ .name = (const char * const[]) {
+ "addi", "addi.n", NULL,
+ },
.translate = translate_addi,
- .windowed_register_op = 0x3,
- }, {
- .name = "addi.n",
- .translate = translate_addi,
- .windowed_register_op = 0x3,
+ .op_flags = XTENSA_OP_NAME_ARRAY,
}, {
.name = "addmi",
.translate = translate_addi,
- .windowed_register_op = 0x3,
}, {
.name = "addx2",
.translate = translate_addx,
.par = (const uint32_t[]){1},
- .windowed_register_op = 0x7,
}, {
.name = "addx4",
.translate = translate_addx,
.par = (const uint32_t[]){2},
- .windowed_register_op = 0x7,
}, {
.name = "addx8",
.translate = translate_addx,
.par = (const uint32_t[]){3},
- .windowed_register_op = 0x7,
}, {
.name = "all4",
.translate = translate_all,
@@ -2482,7 +2864,6 @@
}, {
.name = "and",
.translate = translate_and,
- .windowed_register_op = 0x7,
}, {
.name = "andb",
.translate = translate_boolean,
@@ -2500,139 +2881,177 @@
.translate = translate_all,
.par = (const uint32_t[]){false, 8},
}, {
- .name = "ball",
+ .name = (const char * const[]) {
+ "ball", "ball.w15", "ball.w18", NULL,
+ },
.translate = translate_ball,
.par = (const uint32_t[]){TCG_COND_EQ},
- .windowed_register_op = 0x3,
+ .op_flags = XTENSA_OP_NAME_ARRAY,
}, {
- .name = "bany",
+ .name = (const char * const[]) {
+ "bany", "bany.w15", "bany.w18", NULL,
+ },
.translate = translate_bany,
.par = (const uint32_t[]){TCG_COND_NE},
- .windowed_register_op = 0x3,
+ .op_flags = XTENSA_OP_NAME_ARRAY,
}, {
- .name = "bbc",
+ .name = (const char * const[]) {
+ "bbc", "bbc.w15", "bbc.w18", NULL,
+ },
.translate = translate_bb,
.par = (const uint32_t[]){TCG_COND_EQ},
- .windowed_register_op = 0x3,
+ .op_flags = XTENSA_OP_NAME_ARRAY,
}, {
- .name = "bbci",
+ .name = (const char * const[]) {
+ "bbci", "bbci.w15", "bbci.w18", NULL,
+ },
.translate = translate_bbi,
.par = (const uint32_t[]){TCG_COND_EQ},
- .windowed_register_op = 0x1,
+ .op_flags = XTENSA_OP_NAME_ARRAY,
}, {
- .name = "bbs",
+ .name = (const char * const[]) {
+ "bbs", "bbs.w15", "bbs.w18", NULL,
+ },
.translate = translate_bb,
.par = (const uint32_t[]){TCG_COND_NE},
- .windowed_register_op = 0x3,
+ .op_flags = XTENSA_OP_NAME_ARRAY,
}, {
- .name = "bbsi",
+ .name = (const char * const[]) {
+ "bbsi", "bbsi.w15", "bbsi.w18", NULL,
+ },
.translate = translate_bbi,
.par = (const uint32_t[]){TCG_COND_NE},
- .windowed_register_op = 0x1,
+ .op_flags = XTENSA_OP_NAME_ARRAY,
}, {
- .name = "beq",
+ .name = (const char * const[]) {
+ "beq", "beq.w15", "beq.w18", NULL,
+ },
.translate = translate_b,
.par = (const uint32_t[]){TCG_COND_EQ},
- .windowed_register_op = 0x3,
+ .op_flags = XTENSA_OP_NAME_ARRAY,
}, {
- .name = "beqi",
+ .name = (const char * const[]) {
+ "beqi", "beqi.w15", "beqi.w18", NULL,
+ },
.translate = translate_bi,
.par = (const uint32_t[]){TCG_COND_EQ},
- .windowed_register_op = 0x1,
+ .op_flags = XTENSA_OP_NAME_ARRAY,
}, {
- .name = "beqz",
+ .name = (const char * const[]) {
+ "beqz", "beqz.n", "beqz.w15", "beqz.w18", NULL,
+ },
.translate = translate_bz,
.par = (const uint32_t[]){TCG_COND_EQ},
- .windowed_register_op = 0x1,
- }, {
- .name = "beqz.n",
- .translate = translate_bz,
- .par = (const uint32_t[]){TCG_COND_EQ},
- .windowed_register_op = 0x1,
+ .op_flags = XTENSA_OP_NAME_ARRAY,
}, {
.name = "bf",
.translate = translate_bp,
.par = (const uint32_t[]){TCG_COND_EQ},
}, {
- .name = "bge",
+ .name = (const char * const[]) {
+ "bge", "bge.w15", "bge.w18", NULL,
+ },
.translate = translate_b,
.par = (const uint32_t[]){TCG_COND_GE},
- .windowed_register_op = 0x3,
+ .op_flags = XTENSA_OP_NAME_ARRAY,
}, {
- .name = "bgei",
+ .name = (const char * const[]) {
+ "bgei", "bgei.w15", "bgei.w18", NULL,
+ },
.translate = translate_bi,
.par = (const uint32_t[]){TCG_COND_GE},
- .windowed_register_op = 0x1,
+ .op_flags = XTENSA_OP_NAME_ARRAY,
}, {
- .name = "bgeu",
+ .name = (const char * const[]) {
+ "bgeu", "bgeu.w15", "bgeu.w18", NULL,
+ },
.translate = translate_b,
.par = (const uint32_t[]){TCG_COND_GEU},
- .windowed_register_op = 0x3,
+ .op_flags = XTENSA_OP_NAME_ARRAY,
}, {
- .name = "bgeui",
+ .name = (const char * const[]) {
+ "bgeui", "bgeui.w15", "bgeui.w18", NULL,
+ },
.translate = translate_bi,
.par = (const uint32_t[]){TCG_COND_GEU},
- .windowed_register_op = 0x1,
+ .op_flags = XTENSA_OP_NAME_ARRAY,
}, {
- .name = "bgez",
+ .name = (const char * const[]) {
+ "bgez", "bgez.w15", "bgez.w18", NULL,
+ },
.translate = translate_bz,
.par = (const uint32_t[]){TCG_COND_GE},
- .windowed_register_op = 0x1,
+ .op_flags = XTENSA_OP_NAME_ARRAY,
}, {
- .name = "blt",
+ .name = (const char * const[]) {
+ "blt", "blt.w15", "blt.w18", NULL,
+ },
.translate = translate_b,
.par = (const uint32_t[]){TCG_COND_LT},
- .windowed_register_op = 0x3,
+ .op_flags = XTENSA_OP_NAME_ARRAY,
}, {
- .name = "blti",
+ .name = (const char * const[]) {
+ "blti", "blti.w15", "blti.w18", NULL,
+ },
.translate = translate_bi,
.par = (const uint32_t[]){TCG_COND_LT},
- .windowed_register_op = 0x1,
+ .op_flags = XTENSA_OP_NAME_ARRAY,
}, {
- .name = "bltu",
+ .name = (const char * const[]) {
+ "bltu", "bltu.w15", "bltu.w18", NULL,
+ },
.translate = translate_b,
.par = (const uint32_t[]){TCG_COND_LTU},
- .windowed_register_op = 0x3,
+ .op_flags = XTENSA_OP_NAME_ARRAY,
}, {
- .name = "bltui",
+ .name = (const char * const[]) {
+ "bltui", "bltui.w15", "bltui.w18", NULL,
+ },
.translate = translate_bi,
.par = (const uint32_t[]){TCG_COND_LTU},
- .windowed_register_op = 0x1,
+ .op_flags = XTENSA_OP_NAME_ARRAY,
}, {
- .name = "bltz",
+ .name = (const char * const[]) {
+ "bltz", "bltz.w15", "bltz.w18", NULL,
+ },
.translate = translate_bz,
.par = (const uint32_t[]){TCG_COND_LT},
- .windowed_register_op = 0x1,
+ .op_flags = XTENSA_OP_NAME_ARRAY,
}, {
- .name = "bnall",
+ .name = (const char * const[]) {
+ "bnall", "bnall.w15", "bnall.w18", NULL,
+ },
.translate = translate_ball,
.par = (const uint32_t[]){TCG_COND_NE},
- .windowed_register_op = 0x3,
+ .op_flags = XTENSA_OP_NAME_ARRAY,
}, {
- .name = "bne",
+ .name = (const char * const[]) {
+ "bne", "bne.w15", "bne.w18", NULL,
+ },
.translate = translate_b,
.par = (const uint32_t[]){TCG_COND_NE},
- .windowed_register_op = 0x3,
+ .op_flags = XTENSA_OP_NAME_ARRAY,
}, {
- .name = "bnei",
+ .name = (const char * const[]) {
+ "bnei", "bnei.w15", "bnei.w18", NULL,
+ },
.translate = translate_bi,
.par = (const uint32_t[]){TCG_COND_NE},
- .windowed_register_op = 0x1,
+ .op_flags = XTENSA_OP_NAME_ARRAY,
}, {
- .name = "bnez",
+ .name = (const char * const[]) {
+ "bnez", "bnez.n", "bnez.w15", "bnez.w18", NULL,
+ },
.translate = translate_bz,
.par = (const uint32_t[]){TCG_COND_NE},
- .windowed_register_op = 0x1,
+ .op_flags = XTENSA_OP_NAME_ARRAY,
}, {
- .name = "bnez.n",
- .translate = translate_bz,
- .par = (const uint32_t[]){TCG_COND_NE},
- .windowed_register_op = 0x1,
- }, {
- .name = "bnone",
+ .name = (const char * const[]) {
+ "bnone", "bnone.w15", "bnone.w18", NULL,
+ },
.translate = translate_bany,
.par = (const uint32_t[]){TCG_COND_EQ},
- .windowed_register_op = 0x3,
+ .op_flags = XTENSA_OP_NAME_ARRAY,
}, {
.name = "break",
.translate = translate_nop,
@@ -2653,114 +3072,88 @@
}, {
.name = "call12",
.translate = translate_callw,
- .test_overflow = test_overflow_callw,
.par = (const uint32_t[]){3},
}, {
.name = "call4",
.translate = translate_callw,
- .test_overflow = test_overflow_callw,
.par = (const uint32_t[]){1},
}, {
.name = "call8",
.translate = translate_callw,
- .test_overflow = test_overflow_callw,
.par = (const uint32_t[]){2},
}, {
.name = "callx0",
.translate = translate_callx0,
- .windowed_register_op = 0x1,
}, {
.name = "callx12",
.translate = translate_callxw,
- .test_overflow = test_overflow_callw,
.par = (const uint32_t[]){3},
- .windowed_register_op = 0x1,
}, {
.name = "callx4",
.translate = translate_callxw,
- .test_overflow = test_overflow_callw,
.par = (const uint32_t[]){1},
- .windowed_register_op = 0x1,
}, {
.name = "callx8",
.translate = translate_callxw,
- .test_overflow = test_overflow_callw,
.par = (const uint32_t[]){2},
- .windowed_register_op = 0x1,
}, {
.name = "clamps",
.translate = translate_clamps,
- .windowed_register_op = 0x3,
}, {
.name = "clrb_expstate",
.translate = translate_clrb_expstate,
}, {
.name = "const16",
.translate = translate_const16,
- .windowed_register_op = 0x1,
}, {
.name = "depbits",
.translate = translate_depbits,
- .windowed_register_op = 0x3,
}, {
.name = "dhi",
.translate = translate_dcache,
.op_flags = XTENSA_OP_PRIVILEGED,
- .windowed_register_op = 0x1,
}, {
.name = "dhu",
.translate = translate_dcache,
.op_flags = XTENSA_OP_PRIVILEGED,
- .windowed_register_op = 0x1,
}, {
.name = "dhwb",
.translate = translate_dcache,
- .windowed_register_op = 0x1,
}, {
.name = "dhwbi",
.translate = translate_dcache,
- .windowed_register_op = 0x1,
}, {
.name = "dii",
.translate = translate_nop,
.op_flags = XTENSA_OP_PRIVILEGED,
- .windowed_register_op = 0x1,
}, {
.name = "diu",
.translate = translate_nop,
.op_flags = XTENSA_OP_PRIVILEGED,
- .windowed_register_op = 0x1,
}, {
.name = "diwb",
.translate = translate_nop,
.op_flags = XTENSA_OP_PRIVILEGED,
- .windowed_register_op = 0x1,
}, {
.name = "diwbi",
.translate = translate_nop,
.op_flags = XTENSA_OP_PRIVILEGED,
- .windowed_register_op = 0x1,
}, {
.name = "dpfl",
.translate = translate_dcache,
.op_flags = XTENSA_OP_PRIVILEGED,
- .windowed_register_op = 0x1,
}, {
.name = "dpfr",
.translate = translate_nop,
- .windowed_register_op = 0x1,
}, {
.name = "dpfro",
.translate = translate_nop,
- .windowed_register_op = 0x1,
}, {
.name = "dpfw",
.translate = translate_nop,
- .windowed_register_op = 0x1,
}, {
.name = "dpfwo",
.translate = translate_nop,
- .windowed_register_op = 0x1,
}, {
.name = "dsync",
.translate = translate_nop,
@@ -2769,7 +3162,8 @@
.translate = translate_entry,
.test_ill = test_ill_entry,
.test_overflow = test_overflow_entry,
- .op_flags = XTENSA_OP_EXIT_TB_M1,
+ .op_flags = XTENSA_OP_EXIT_TB_M1 |
+ XTENSA_OP_SYNC_REGISTER_WINDOW,
}, {
.name = "esync",
.translate = translate_nop,
@@ -2779,7 +3173,6 @@
}, {
.name = "extui",
.translate = translate_extui,
- .windowed_register_op = 0x3,
}, {
.name = "extw",
.translate = translate_memw,
@@ -2794,47 +3187,38 @@
.translate = translate_itlb,
.par = (const uint32_t[]){true},
.op_flags = XTENSA_OP_PRIVILEGED | XTENSA_OP_EXIT_TB_M1,
- .windowed_register_op = 0x1,
}, {
.name = "ihi",
.translate = translate_icache,
- .windowed_register_op = 0x1,
}, {
.name = "ihu",
.translate = translate_icache,
.op_flags = XTENSA_OP_PRIVILEGED,
- .windowed_register_op = 0x1,
}, {
.name = "iii",
.translate = translate_nop,
.op_flags = XTENSA_OP_PRIVILEGED,
- .windowed_register_op = 0x1,
}, {
.name = "iitlb",
.translate = translate_itlb,
.par = (const uint32_t[]){false},
.op_flags = XTENSA_OP_PRIVILEGED | XTENSA_OP_EXIT_TB_M1,
- .windowed_register_op = 0x1,
}, {
.name = "iiu",
.translate = translate_nop,
.op_flags = XTENSA_OP_PRIVILEGED,
- .windowed_register_op = 0x1,
}, {
- .name = "ill",
- .op_flags = XTENSA_OP_ILL,
- }, {
- .name = "ill.n",
- .op_flags = XTENSA_OP_ILL,
+ .name = (const char * const[]) {
+ "ill", "ill.n", NULL,
+ },
+ .op_flags = XTENSA_OP_ILL | XTENSA_OP_NAME_ARRAY,
}, {
.name = "ipf",
.translate = translate_nop,
- .windowed_register_op = 0x1,
}, {
.name = "ipfl",
.translate = translate_icache,
.op_flags = XTENSA_OP_PRIVILEGED,
- .windowed_register_op = 0x1,
}, {
.name = "isync",
.translate = translate_nop,
@@ -2844,498 +3228,423 @@
}, {
.name = "jx",
.translate = translate_jx,
- .windowed_register_op = 0x1,
}, {
.name = "l16si",
.translate = translate_ldst,
.par = (const uint32_t[]){MO_TESW, false, false},
- .windowed_register_op = 0x3,
+ .op_flags = XTENSA_OP_LOAD,
}, {
.name = "l16ui",
.translate = translate_ldst,
.par = (const uint32_t[]){MO_TEUW, false, false},
- .windowed_register_op = 0x3,
+ .op_flags = XTENSA_OP_LOAD,
}, {
.name = "l32ai",
.translate = translate_ldst,
.par = (const uint32_t[]){MO_TEUL, true, false},
- .windowed_register_op = 0x3,
+ .op_flags = XTENSA_OP_LOAD,
}, {
.name = "l32e",
.translate = translate_l32e,
- .op_flags = XTENSA_OP_PRIVILEGED,
- .windowed_register_op = 0x3,
+ .op_flags = XTENSA_OP_PRIVILEGED | XTENSA_OP_LOAD,
}, {
- .name = "l32i",
+ .name = (const char * const[]) {
+ "l32i", "l32i.n", NULL,
+ },
.translate = translate_ldst,
.par = (const uint32_t[]){MO_TEUL, false, false},
- .windowed_register_op = 0x3,
- }, {
- .name = "l32i.n",
- .translate = translate_ldst,
- .par = (const uint32_t[]){MO_TEUL, false, false},
- .windowed_register_op = 0x3,
+ .op_flags = XTENSA_OP_NAME_ARRAY | XTENSA_OP_LOAD,
}, {
.name = "l32r",
.translate = translate_l32r,
- .windowed_register_op = 0x1,
+ .op_flags = XTENSA_OP_LOAD,
}, {
.name = "l8ui",
.translate = translate_ldst,
.par = (const uint32_t[]){MO_UB, false, false},
- .windowed_register_op = 0x3,
+ .op_flags = XTENSA_OP_LOAD,
}, {
.name = "lddec",
.translate = translate_mac16,
- .par = (const uint32_t[]){MAC16_NONE, 0, 0, -4},
- .windowed_register_op = 0x2,
+ .par = (const uint32_t[]){MAC16_NONE, 0, -4},
+ .op_flags = XTENSA_OP_LOAD,
}, {
.name = "ldinc",
.translate = translate_mac16,
- .par = (const uint32_t[]){MAC16_NONE, 0, 0, 4},
- .windowed_register_op = 0x2,
+ .par = (const uint32_t[]){MAC16_NONE, 0, 4},
+ .op_flags = XTENSA_OP_LOAD,
}, {
.name = "ldpte",
.op_flags = XTENSA_OP_ILL,
}, {
- .name = "loop",
+ .name = (const char * const[]) {
+ "loop", "loop.w15", NULL,
+ },
.translate = translate_loop,
.par = (const uint32_t[]){TCG_COND_NEVER},
- .windowed_register_op = 0x1,
+ .op_flags = XTENSA_OP_NAME_ARRAY,
}, {
- .name = "loopgtz",
+ .name = (const char * const[]) {
+ "loopgtz", "loopgtz.w15", NULL,
+ },
.translate = translate_loop,
.par = (const uint32_t[]){TCG_COND_GT},
- .windowed_register_op = 0x1,
+ .op_flags = XTENSA_OP_NAME_ARRAY,
}, {
- .name = "loopnez",
+ .name = (const char * const[]) {
+ "loopnez", "loopnez.w15", NULL,
+ },
.translate = translate_loop,
.par = (const uint32_t[]){TCG_COND_NE},
- .windowed_register_op = 0x1,
+ .op_flags = XTENSA_OP_NAME_ARRAY,
}, {
.name = "max",
.translate = translate_smax,
- .windowed_register_op = 0x7,
}, {
.name = "maxu",
.translate = translate_umax,
- .windowed_register_op = 0x7,
}, {
.name = "memw",
.translate = translate_memw,
}, {
.name = "min",
.translate = translate_smin,
- .windowed_register_op = 0x7,
}, {
.name = "minu",
.translate = translate_umin,
- .windowed_register_op = 0x7,
}, {
- .name = "mov",
+ .name = (const char * const[]) {
+ "mov", "mov.n", NULL,
+ },
.translate = translate_mov,
- .windowed_register_op = 0x3,
- }, {
- .name = "mov.n",
- .translate = translate_mov,
- .windowed_register_op = 0x3,
+ .op_flags = XTENSA_OP_NAME_ARRAY,
}, {
.name = "moveqz",
.translate = translate_movcond,
.par = (const uint32_t[]){TCG_COND_EQ},
- .windowed_register_op = 0x7,
}, {
.name = "movf",
.translate = translate_movp,
.par = (const uint32_t[]){TCG_COND_EQ},
- .windowed_register_op = 0x3,
}, {
.name = "movgez",
.translate = translate_movcond,
.par = (const uint32_t[]){TCG_COND_GE},
- .windowed_register_op = 0x7,
}, {
.name = "movi",
.translate = translate_movi,
- .windowed_register_op = 0x1,
}, {
.name = "movi.n",
.translate = translate_movi,
- .windowed_register_op = 0x1,
}, {
.name = "movltz",
.translate = translate_movcond,
.par = (const uint32_t[]){TCG_COND_LT},
- .windowed_register_op = 0x7,
}, {
.name = "movnez",
.translate = translate_movcond,
.par = (const uint32_t[]){TCG_COND_NE},
- .windowed_register_op = 0x7,
}, {
.name = "movsp",
.translate = translate_movsp,
- .windowed_register_op = 0x3,
.op_flags = XTENSA_OP_ALLOCA,
}, {
.name = "movt",
.translate = translate_movp,
.par = (const uint32_t[]){TCG_COND_NE},
- .windowed_register_op = 0x3,
}, {
.name = "mul.aa.hh",
.translate = translate_mac16,
- .par = (const uint32_t[]){MAC16_MUL, MAC16_AA, MAC16_HH, 0},
- .windowed_register_op = 0x3,
+ .par = (const uint32_t[]){MAC16_MUL, MAC16_HH, 0},
}, {
.name = "mul.aa.hl",
.translate = translate_mac16,
- .par = (const uint32_t[]){MAC16_MUL, MAC16_AA, MAC16_HL, 0},
- .windowed_register_op = 0x3,
+ .par = (const uint32_t[]){MAC16_MUL, MAC16_HL, 0},
}, {
.name = "mul.aa.lh",
.translate = translate_mac16,
- .par = (const uint32_t[]){MAC16_MUL, MAC16_AA, MAC16_LH, 0},
- .windowed_register_op = 0x3,
+ .par = (const uint32_t[]){MAC16_MUL, MAC16_LH, 0},
}, {
.name = "mul.aa.ll",
.translate = translate_mac16,
- .par = (const uint32_t[]){MAC16_MUL, MAC16_AA, MAC16_LL, 0},
- .windowed_register_op = 0x3,
+ .par = (const uint32_t[]){MAC16_MUL, MAC16_LL, 0},
}, {
.name = "mul.ad.hh",
.translate = translate_mac16,
- .par = (const uint32_t[]){MAC16_MUL, MAC16_AD, MAC16_HH, 0},
- .windowed_register_op = 0x1,
+ .par = (const uint32_t[]){MAC16_MUL, MAC16_HH, 0},
}, {
.name = "mul.ad.hl",
.translate = translate_mac16,
- .par = (const uint32_t[]){MAC16_MUL, MAC16_AD, MAC16_HL, 0},
- .windowed_register_op = 0x1,
+ .par = (const uint32_t[]){MAC16_MUL, MAC16_HL, 0},
}, {
.name = "mul.ad.lh",
.translate = translate_mac16,
- .par = (const uint32_t[]){MAC16_MUL, MAC16_AD, MAC16_LH, 0},
- .windowed_register_op = 0x1,
+ .par = (const uint32_t[]){MAC16_MUL, MAC16_LH, 0},
}, {
.name = "mul.ad.ll",
.translate = translate_mac16,
- .par = (const uint32_t[]){MAC16_MUL, MAC16_AD, MAC16_LL, 0},
- .windowed_register_op = 0x1,
+ .par = (const uint32_t[]){MAC16_MUL, MAC16_LL, 0},
}, {
.name = "mul.da.hh",
.translate = translate_mac16,
- .par = (const uint32_t[]){MAC16_MUL, MAC16_DA, MAC16_HH, 0},
- .windowed_register_op = 0x2,
+ .par = (const uint32_t[]){MAC16_MUL, MAC16_HH, 0},
}, {
.name = "mul.da.hl",
.translate = translate_mac16,
- .par = (const uint32_t[]){MAC16_MUL, MAC16_DA, MAC16_HL, 0},
- .windowed_register_op = 0x2,
+ .par = (const uint32_t[]){MAC16_MUL, MAC16_HL, 0},
}, {
.name = "mul.da.lh",
.translate = translate_mac16,
- .par = (const uint32_t[]){MAC16_MUL, MAC16_DA, MAC16_LH, 0},
- .windowed_register_op = 0x2,
+ .par = (const uint32_t[]){MAC16_MUL, MAC16_LH, 0},
}, {
.name = "mul.da.ll",
.translate = translate_mac16,
- .par = (const uint32_t[]){MAC16_MUL, MAC16_DA, MAC16_LL, 0},
- .windowed_register_op = 0x2,
+ .par = (const uint32_t[]){MAC16_MUL, MAC16_LL, 0},
}, {
.name = "mul.dd.hh",
.translate = translate_mac16,
- .par = (const uint32_t[]){MAC16_MUL, MAC16_DD, MAC16_HH, 0},
+ .par = (const uint32_t[]){MAC16_MUL, MAC16_HH, 0},
}, {
.name = "mul.dd.hl",
.translate = translate_mac16,
- .par = (const uint32_t[]){MAC16_MUL, MAC16_DD, MAC16_HL, 0},
+ .par = (const uint32_t[]){MAC16_MUL, MAC16_HL, 0},
}, {
.name = "mul.dd.lh",
.translate = translate_mac16,
- .par = (const uint32_t[]){MAC16_MUL, MAC16_DD, MAC16_LH, 0},
+ .par = (const uint32_t[]){MAC16_MUL, MAC16_LH, 0},
}, {
.name = "mul.dd.ll",
.translate = translate_mac16,
- .par = (const uint32_t[]){MAC16_MUL, MAC16_DD, MAC16_LL, 0},
+ .par = (const uint32_t[]){MAC16_MUL, MAC16_LL, 0},
}, {
.name = "mul16s",
.translate = translate_mul16,
.par = (const uint32_t[]){true},
- .windowed_register_op = 0x7,
}, {
.name = "mul16u",
.translate = translate_mul16,
.par = (const uint32_t[]){false},
- .windowed_register_op = 0x7,
}, {
.name = "mula.aa.hh",
.translate = translate_mac16,
- .par = (const uint32_t[]){MAC16_MULA, MAC16_AA, MAC16_HH, 0},
- .windowed_register_op = 0x3,
+ .par = (const uint32_t[]){MAC16_MULA, MAC16_HH, 0},
}, {
.name = "mula.aa.hl",
.translate = translate_mac16,
- .par = (const uint32_t[]){MAC16_MULA, MAC16_AA, MAC16_HL, 0},
- .windowed_register_op = 0x3,
+ .par = (const uint32_t[]){MAC16_MULA, MAC16_HL, 0},
}, {
.name = "mula.aa.lh",
.translate = translate_mac16,
- .par = (const uint32_t[]){MAC16_MULA, MAC16_AA, MAC16_LH, 0},
- .windowed_register_op = 0x3,
+ .par = (const uint32_t[]){MAC16_MULA, MAC16_LH, 0},
}, {
.name = "mula.aa.ll",
.translate = translate_mac16,
- .par = (const uint32_t[]){MAC16_MULA, MAC16_AA, MAC16_LL, 0},
- .windowed_register_op = 0x3,
+ .par = (const uint32_t[]){MAC16_MULA, MAC16_LL, 0},
}, {
.name = "mula.ad.hh",
.translate = translate_mac16,
- .par = (const uint32_t[]){MAC16_MULA, MAC16_AD, MAC16_HH, 0},
- .windowed_register_op = 0x1,
+ .par = (const uint32_t[]){MAC16_MULA, MAC16_HH, 0},
}, {
.name = "mula.ad.hl",
.translate = translate_mac16,
- .par = (const uint32_t[]){MAC16_MULA, MAC16_AD, MAC16_HL, 0},
- .windowed_register_op = 0x1,
+ .par = (const uint32_t[]){MAC16_MULA, MAC16_HL, 0},
}, {
.name = "mula.ad.lh",
.translate = translate_mac16,
- .par = (const uint32_t[]){MAC16_MULA, MAC16_AD, MAC16_LH, 0},
- .windowed_register_op = 0x1,
+ .par = (const uint32_t[]){MAC16_MULA, MAC16_LH, 0},
}, {
.name = "mula.ad.ll",
.translate = translate_mac16,
- .par = (const uint32_t[]){MAC16_MULA, MAC16_AD, MAC16_LL, 0},
- .windowed_register_op = 0x1,
+ .par = (const uint32_t[]){MAC16_MULA, MAC16_LL, 0},
}, {
.name = "mula.da.hh",
.translate = translate_mac16,
- .par = (const uint32_t[]){MAC16_MULA, MAC16_DA, MAC16_HH, 0},
- .windowed_register_op = 0x2,
+ .par = (const uint32_t[]){MAC16_MULA, MAC16_HH, 0},
}, {
.name = "mula.da.hh.lddec",
.translate = translate_mac16,
- .par = (const uint32_t[]){MAC16_MULA, MAC16_DA, MAC16_HH, -4},
- .windowed_register_op = 0xa,
+ .par = (const uint32_t[]){MAC16_MULA, MAC16_HH, -4},
}, {
.name = "mula.da.hh.ldinc",
.translate = translate_mac16,
- .par = (const uint32_t[]){MAC16_MULA, MAC16_DA, MAC16_HH, 4},
- .windowed_register_op = 0xa,
+ .par = (const uint32_t[]){MAC16_MULA, MAC16_HH, 4},
}, {
.name = "mula.da.hl",
.translate = translate_mac16,
- .par = (const uint32_t[]){MAC16_MULA, MAC16_DA, MAC16_HL, 0},
- .windowed_register_op = 0x2,
+ .par = (const uint32_t[]){MAC16_MULA, MAC16_HL, 0},
}, {
.name = "mula.da.hl.lddec",
.translate = translate_mac16,
- .par = (const uint32_t[]){MAC16_MULA, MAC16_DA, MAC16_HL, -4},
- .windowed_register_op = 0xa,
+ .par = (const uint32_t[]){MAC16_MULA, MAC16_HL, -4},
}, {
.name = "mula.da.hl.ldinc",
.translate = translate_mac16,
- .par = (const uint32_t[]){MAC16_MULA, MAC16_DA, MAC16_HL, 4},
- .windowed_register_op = 0xa,
+ .par = (const uint32_t[]){MAC16_MULA, MAC16_HL, 4},
}, {
.name = "mula.da.lh",
.translate = translate_mac16,
- .par = (const uint32_t[]){MAC16_MULA, MAC16_DA, MAC16_LH, 0},
- .windowed_register_op = 0x2,
+ .par = (const uint32_t[]){MAC16_MULA, MAC16_LH, 0},
}, {
.name = "mula.da.lh.lddec",
.translate = translate_mac16,
- .par = (const uint32_t[]){MAC16_MULA, MAC16_DA, MAC16_LH, -4},
- .windowed_register_op = 0xa,
+ .par = (const uint32_t[]){MAC16_MULA, MAC16_LH, -4},
}, {
.name = "mula.da.lh.ldinc",
.translate = translate_mac16,
- .par = (const uint32_t[]){MAC16_MULA, MAC16_DA, MAC16_LH, 4},
- .windowed_register_op = 0xa,
+ .par = (const uint32_t[]){MAC16_MULA, MAC16_LH, 4},
}, {
.name = "mula.da.ll",
.translate = translate_mac16,
- .par = (const uint32_t[]){MAC16_MULA, MAC16_DA, MAC16_LL, 0},
- .windowed_register_op = 0x2,
+ .par = (const uint32_t[]){MAC16_MULA, MAC16_LL, 0},
}, {
.name = "mula.da.ll.lddec",
.translate = translate_mac16,
- .par = (const uint32_t[]){MAC16_MULA, MAC16_DA, MAC16_LL, -4},
- .windowed_register_op = 0xa,
+ .par = (const uint32_t[]){MAC16_MULA, MAC16_LL, -4},
}, {
.name = "mula.da.ll.ldinc",
.translate = translate_mac16,
- .par = (const uint32_t[]){MAC16_MULA, MAC16_DA, MAC16_LL, 4},
- .windowed_register_op = 0xa,
+ .par = (const uint32_t[]){MAC16_MULA, MAC16_LL, 4},
}, {
.name = "mula.dd.hh",
.translate = translate_mac16,
- .par = (const uint32_t[]){MAC16_MULA, MAC16_DD, MAC16_HH, 0},
+ .par = (const uint32_t[]){MAC16_MULA, MAC16_HH, 0},
}, {
.name = "mula.dd.hh.lddec",
.translate = translate_mac16,
- .par = (const uint32_t[]){MAC16_MULA, MAC16_DD, MAC16_HH, -4},
- .windowed_register_op = 0x2,
+ .par = (const uint32_t[]){MAC16_MULA, MAC16_HH, -4},
}, {
.name = "mula.dd.hh.ldinc",
.translate = translate_mac16,
- .par = (const uint32_t[]){MAC16_MULA, MAC16_DD, MAC16_HH, 4},
- .windowed_register_op = 0x2,
+ .par = (const uint32_t[]){MAC16_MULA, MAC16_HH, 4},
}, {
.name = "mula.dd.hl",
.translate = translate_mac16,
- .par = (const uint32_t[]){MAC16_MULA, MAC16_DD, MAC16_HL, 0},
+ .par = (const uint32_t[]){MAC16_MULA, MAC16_HL, 0},
}, {
.name = "mula.dd.hl.lddec",
.translate = translate_mac16,
- .par = (const uint32_t[]){MAC16_MULA, MAC16_DD, MAC16_HL, -4},
- .windowed_register_op = 0x2,
+ .par = (const uint32_t[]){MAC16_MULA, MAC16_HL, -4},
}, {
.name = "mula.dd.hl.ldinc",
.translate = translate_mac16,
- .par = (const uint32_t[]){MAC16_MULA, MAC16_DD, MAC16_HL, 4},
- .windowed_register_op = 0x2,
+ .par = (const uint32_t[]){MAC16_MULA, MAC16_HL, 4},
}, {
.name = "mula.dd.lh",
.translate = translate_mac16,
- .par = (const uint32_t[]){MAC16_MULA, MAC16_DD, MAC16_LH, 0},
+ .par = (const uint32_t[]){MAC16_MULA, MAC16_LH, 0},
}, {
.name = "mula.dd.lh.lddec",
.translate = translate_mac16,
- .par = (const uint32_t[]){MAC16_MULA, MAC16_DD, MAC16_LH, -4},
- .windowed_register_op = 0x2,
+ .par = (const uint32_t[]){MAC16_MULA, MAC16_LH, -4},
}, {
.name = "mula.dd.lh.ldinc",
.translate = translate_mac16,
- .par = (const uint32_t[]){MAC16_MULA, MAC16_DD, MAC16_LH, 4},
- .windowed_register_op = 0x2,
+ .par = (const uint32_t[]){MAC16_MULA, MAC16_LH, 4},
}, {
.name = "mula.dd.ll",
.translate = translate_mac16,
- .par = (const uint32_t[]){MAC16_MULA, MAC16_DD, MAC16_LL, 0},
+ .par = (const uint32_t[]){MAC16_MULA, MAC16_LL, 0},
}, {
.name = "mula.dd.ll.lddec",
.translate = translate_mac16,
- .par = (const uint32_t[]){MAC16_MULA, MAC16_DD, MAC16_LL, -4},
- .windowed_register_op = 0x2,
+ .par = (const uint32_t[]){MAC16_MULA, MAC16_LL, -4},
}, {
.name = "mula.dd.ll.ldinc",
.translate = translate_mac16,
- .par = (const uint32_t[]){MAC16_MULA, MAC16_DD, MAC16_LL, 4},
- .windowed_register_op = 0x2,
+ .par = (const uint32_t[]){MAC16_MULA, MAC16_LL, 4},
}, {
.name = "mull",
.translate = translate_mull,
- .windowed_register_op = 0x7,
}, {
.name = "muls.aa.hh",
.translate = translate_mac16,
- .par = (const uint32_t[]){MAC16_MULS, MAC16_AA, MAC16_HH, 0},
- .windowed_register_op = 0x3,
+ .par = (const uint32_t[]){MAC16_MULS, MAC16_HH, 0},
}, {
.name = "muls.aa.hl",
.translate = translate_mac16,
- .par = (const uint32_t[]){MAC16_MULS, MAC16_AA, MAC16_HL, 0},
- .windowed_register_op = 0x3,
+ .par = (const uint32_t[]){MAC16_MULS, MAC16_HL, 0},
}, {
.name = "muls.aa.lh",
.translate = translate_mac16,
- .par = (const uint32_t[]){MAC16_MULS, MAC16_AA, MAC16_LH, 0},
- .windowed_register_op = 0x3,
+ .par = (const uint32_t[]){MAC16_MULS, MAC16_LH, 0},
}, {
.name = "muls.aa.ll",
.translate = translate_mac16,
- .par = (const uint32_t[]){MAC16_MULS, MAC16_AA, MAC16_LL, 0},
- .windowed_register_op = 0x3,
+ .par = (const uint32_t[]){MAC16_MULS, MAC16_LL, 0},
}, {
.name = "muls.ad.hh",
.translate = translate_mac16,
- .par = (const uint32_t[]){MAC16_MULS, MAC16_AD, MAC16_HH, 0},
- .windowed_register_op = 0x1,
+ .par = (const uint32_t[]){MAC16_MULS, MAC16_HH, 0},
}, {
.name = "muls.ad.hl",
.translate = translate_mac16,
- .par = (const uint32_t[]){MAC16_MULS, MAC16_AD, MAC16_HL, 0},
- .windowed_register_op = 0x1,
+ .par = (const uint32_t[]){MAC16_MULS, MAC16_HL, 0},
}, {
.name = "muls.ad.lh",
.translate = translate_mac16,
- .par = (const uint32_t[]){MAC16_MULS, MAC16_AD, MAC16_LH, 0},
- .windowed_register_op = 0x1,
+ .par = (const uint32_t[]){MAC16_MULS, MAC16_LH, 0},
}, {
.name = "muls.ad.ll",
.translate = translate_mac16,
- .par = (const uint32_t[]){MAC16_MULS, MAC16_AD, MAC16_LL, 0},
- .windowed_register_op = 0x1,
+ .par = (const uint32_t[]){MAC16_MULS, MAC16_LL, 0},
}, {
.name = "muls.da.hh",
.translate = translate_mac16,
- .par = (const uint32_t[]){MAC16_MULS, MAC16_DA, MAC16_HH, 0},
- .windowed_register_op = 0x2,
+ .par = (const uint32_t[]){MAC16_MULS, MAC16_HH, 0},
}, {
.name = "muls.da.hl",
.translate = translate_mac16,
- .par = (const uint32_t[]){MAC16_MULS, MAC16_DA, MAC16_HL, 0},
- .windowed_register_op = 0x2,
+ .par = (const uint32_t[]){MAC16_MULS, MAC16_HL, 0},
}, {
.name = "muls.da.lh",
.translate = translate_mac16,
- .par = (const uint32_t[]){MAC16_MULS, MAC16_DA, MAC16_LH, 0},
- .windowed_register_op = 0x2,
+ .par = (const uint32_t[]){MAC16_MULS, MAC16_LH, 0},
}, {
.name = "muls.da.ll",
.translate = translate_mac16,
- .par = (const uint32_t[]){MAC16_MULS, MAC16_DA, MAC16_LL, 0},
- .windowed_register_op = 0x2,
+ .par = (const uint32_t[]){MAC16_MULS, MAC16_LL, 0},
}, {
.name = "muls.dd.hh",
.translate = translate_mac16,
- .par = (const uint32_t[]){MAC16_MULS, MAC16_DD, MAC16_HH, 0},
+ .par = (const uint32_t[]){MAC16_MULS, MAC16_HH, 0},
}, {
.name = "muls.dd.hl",
.translate = translate_mac16,
- .par = (const uint32_t[]){MAC16_MULS, MAC16_DD, MAC16_HL, 0},
+ .par = (const uint32_t[]){MAC16_MULS, MAC16_HL, 0},
}, {
.name = "muls.dd.lh",
.translate = translate_mac16,
- .par = (const uint32_t[]){MAC16_MULS, MAC16_DD, MAC16_LH, 0},
+ .par = (const uint32_t[]){MAC16_MULS, MAC16_LH, 0},
}, {
.name = "muls.dd.ll",
.translate = translate_mac16,
- .par = (const uint32_t[]){MAC16_MULS, MAC16_DD, MAC16_LL, 0},
+ .par = (const uint32_t[]){MAC16_MULS, MAC16_LL, 0},
}, {
.name = "mulsh",
.translate = translate_mulh,
.par = (const uint32_t[]){true},
- .windowed_register_op = 0x7,
}, {
.name = "muluh",
.translate = translate_mulh,
.par = (const uint32_t[]){false},
- .windowed_register_op = 0x7,
}, {
.name = "neg",
.translate = translate_neg,
- .windowed_register_op = 0x3,
}, {
- .name = "nop",
+ .name = (const char * const[]) {
+ "nop", "nop.n", NULL,
+ },
.translate = translate_nop,
- }, {
- .name = "nop.n",
- .translate = translate_nop,
+ .op_flags = XTENSA_OP_NAME_ARRAY,
}, {
.name = "nsa",
.translate = translate_nsa,
- .windowed_register_op = 0x3,
}, {
.name = "nsau",
.translate = translate_nsau,
- .windowed_register_op = 0x3,
}, {
.name = "or",
.translate = translate_or,
- .windowed_register_op = 0x7,
}, {
.name = "orb",
.translate = translate_boolean,
@@ -3349,72 +3658,59 @@
.translate = translate_ptlb,
.par = (const uint32_t[]){true},
.op_flags = XTENSA_OP_PRIVILEGED,
- .windowed_register_op = 0x3,
}, {
.name = "pitlb",
.translate = translate_ptlb,
.par = (const uint32_t[]){false},
.op_flags = XTENSA_OP_PRIVILEGED,
- .windowed_register_op = 0x3,
}, {
.name = "quos",
.translate = translate_quos,
.par = (const uint32_t[]){true},
.op_flags = XTENSA_OP_DIVIDE_BY_ZERO,
- .windowed_register_op = 0x7,
}, {
.name = "quou",
.translate = translate_quou,
.op_flags = XTENSA_OP_DIVIDE_BY_ZERO,
- .windowed_register_op = 0x7,
}, {
.name = "rdtlb0",
.translate = translate_rtlb,
.par = (const uint32_t[]){true, 0},
.op_flags = XTENSA_OP_PRIVILEGED,
- .windowed_register_op = 0x3,
}, {
.name = "rdtlb1",
.translate = translate_rtlb,
.par = (const uint32_t[]){true, 1},
.op_flags = XTENSA_OP_PRIVILEGED,
- .windowed_register_op = 0x3,
}, {
.name = "read_impwire",
.translate = translate_read_impwire,
- .windowed_register_op = 0x1,
}, {
.name = "rems",
.translate = translate_quos,
.par = (const uint32_t[]){false},
.op_flags = XTENSA_OP_DIVIDE_BY_ZERO,
- .windowed_register_op = 0x7,
}, {
.name = "remu",
.translate = translate_remu,
.op_flags = XTENSA_OP_DIVIDE_BY_ZERO,
- .windowed_register_op = 0x7,
}, {
.name = "rer",
.translate = translate_rer,
.op_flags = XTENSA_OP_PRIVILEGED,
- .windowed_register_op = 0x3,
}, {
- .name = "ret",
+ .name = (const char * const[]) {
+ "ret", "ret.n", NULL,
+ },
.translate = translate_ret,
+ .op_flags = XTENSA_OP_NAME_ARRAY,
}, {
- .name = "ret.n",
- .translate = translate_ret,
- }, {
- .name = "retw",
+ .name = (const char * const[]) {
+ "retw", "retw.n", NULL,
+ },
.translate = translate_retw,
.test_ill = test_ill_retw,
- .op_flags = XTENSA_OP_UNDERFLOW,
- }, {
- .name = "retw.n",
- .translate = translate_retw,
- .test_ill = test_ill_retw,
- .op_flags = XTENSA_OP_UNDERFLOW,
+ .op_flags = XTENSA_OP_UNDERFLOW | XTENSA_OP_NAME_ARRAY,
}, {
.name = "rfdd",
.op_flags = XTENSA_OP_ILL,
@@ -3448,17 +3744,17 @@
.translate = translate_rtlb,
.par = (const uint32_t[]){false, 0},
.op_flags = XTENSA_OP_PRIVILEGED,
- .windowed_register_op = 0x3,
}, {
.name = "ritlb1",
.translate = translate_rtlb,
.par = (const uint32_t[]){false, 1},
.op_flags = XTENSA_OP_PRIVILEGED,
- .windowed_register_op = 0x3,
}, {
.name = "rotw",
.translate = translate_rotw,
- .op_flags = XTENSA_OP_PRIVILEGED | XTENSA_OP_EXIT_TB_M1,
+ .op_flags = XTENSA_OP_PRIVILEGED |
+ XTENSA_OP_EXIT_TB_M1 |
+ XTENSA_OP_SYNC_REGISTER_WINDOW,
}, {
.name = "rsil",
.translate = translate_rsil,
@@ -3466,526 +3762,454 @@
XTENSA_OP_PRIVILEGED |
XTENSA_OP_EXIT_TB_0 |
XTENSA_OP_CHECK_INTERRUPTS,
- .windowed_register_op = 0x1,
}, {
.name = "rsr.176",
.translate = translate_rsr,
.test_ill = test_ill_rsr,
.par = (const uint32_t[]){176},
.op_flags = XTENSA_OP_PRIVILEGED,
- .windowed_register_op = 0x1,
}, {
.name = "rsr.208",
.translate = translate_rsr,
.test_ill = test_ill_rsr,
.par = (const uint32_t[]){208},
.op_flags = XTENSA_OP_PRIVILEGED,
- .windowed_register_op = 0x1,
}, {
.name = "rsr.acchi",
.translate = translate_rsr,
.test_ill = test_ill_rsr,
.par = (const uint32_t[]){ACCHI},
- .windowed_register_op = 0x1,
}, {
.name = "rsr.acclo",
.translate = translate_rsr,
.test_ill = test_ill_rsr,
.par = (const uint32_t[]){ACCLO},
- .windowed_register_op = 0x1,
}, {
.name = "rsr.atomctl",
.translate = translate_rsr,
.test_ill = test_ill_rsr,
.par = (const uint32_t[]){ATOMCTL},
.op_flags = XTENSA_OP_PRIVILEGED,
- .windowed_register_op = 0x1,
}, {
.name = "rsr.br",
.translate = translate_rsr,
.test_ill = test_ill_rsr,
.par = (const uint32_t[]){BR},
- .windowed_register_op = 0x1,
}, {
.name = "rsr.cacheattr",
.translate = translate_rsr,
.test_ill = test_ill_rsr,
.par = (const uint32_t[]){CACHEATTR},
.op_flags = XTENSA_OP_PRIVILEGED,
- .windowed_register_op = 0x1,
}, {
.name = "rsr.ccompare0",
.translate = translate_rsr,
.test_ill = test_ill_rsr,
.par = (const uint32_t[]){CCOMPARE},
.op_flags = XTENSA_OP_PRIVILEGED,
- .windowed_register_op = 0x1,
}, {
.name = "rsr.ccompare1",
.translate = translate_rsr,
.test_ill = test_ill_rsr,
.par = (const uint32_t[]){CCOMPARE + 1},
.op_flags = XTENSA_OP_PRIVILEGED,
- .windowed_register_op = 0x1,
}, {
.name = "rsr.ccompare2",
.translate = translate_rsr,
.test_ill = test_ill_rsr,
.par = (const uint32_t[]){CCOMPARE + 2},
.op_flags = XTENSA_OP_PRIVILEGED,
- .windowed_register_op = 0x1,
}, {
.name = "rsr.ccount",
.translate = translate_rsr,
.test_ill = test_ill_rsr,
.par = (const uint32_t[]){CCOUNT},
.op_flags = XTENSA_OP_PRIVILEGED | XTENSA_OP_EXIT_TB_0,
- .windowed_register_op = 0x1,
}, {
.name = "rsr.configid0",
.translate = translate_rsr,
.test_ill = test_ill_rsr,
.par = (const uint32_t[]){CONFIGID0},
.op_flags = XTENSA_OP_PRIVILEGED,
- .windowed_register_op = 0x1,
}, {
.name = "rsr.configid1",
.translate = translate_rsr,
.test_ill = test_ill_rsr,
.par = (const uint32_t[]){CONFIGID1},
.op_flags = XTENSA_OP_PRIVILEGED,
- .windowed_register_op = 0x1,
}, {
.name = "rsr.cpenable",
.translate = translate_rsr,
.test_ill = test_ill_rsr,
.par = (const uint32_t[]){CPENABLE},
.op_flags = XTENSA_OP_PRIVILEGED,
- .windowed_register_op = 0x1,
}, {
.name = "rsr.dbreaka0",
.translate = translate_rsr,
.test_ill = test_ill_rsr,
.par = (const uint32_t[]){DBREAKA},
.op_flags = XTENSA_OP_PRIVILEGED,
- .windowed_register_op = 0x1,
}, {
.name = "rsr.dbreaka1",
.translate = translate_rsr,
.test_ill = test_ill_rsr,
.par = (const uint32_t[]){DBREAKA + 1},
.op_flags = XTENSA_OP_PRIVILEGED,
- .windowed_register_op = 0x1,
}, {
.name = "rsr.dbreakc0",
.translate = translate_rsr,
.test_ill = test_ill_rsr,
.par = (const uint32_t[]){DBREAKC},
.op_flags = XTENSA_OP_PRIVILEGED,
- .windowed_register_op = 0x1,
}, {
.name = "rsr.dbreakc1",
.translate = translate_rsr,
.test_ill = test_ill_rsr,
.par = (const uint32_t[]){DBREAKC + 1},
.op_flags = XTENSA_OP_PRIVILEGED,
- .windowed_register_op = 0x1,
}, {
.name = "rsr.ddr",
.translate = translate_rsr,
.test_ill = test_ill_rsr,
.par = (const uint32_t[]){DDR},
.op_flags = XTENSA_OP_PRIVILEGED,
- .windowed_register_op = 0x1,
}, {
.name = "rsr.debugcause",
.translate = translate_rsr,
.test_ill = test_ill_rsr,
.par = (const uint32_t[]){DEBUGCAUSE},
.op_flags = XTENSA_OP_PRIVILEGED,
- .windowed_register_op = 0x1,
}, {
.name = "rsr.depc",
.translate = translate_rsr,
.test_ill = test_ill_rsr,
.par = (const uint32_t[]){DEPC},
.op_flags = XTENSA_OP_PRIVILEGED,
- .windowed_register_op = 0x1,
}, {
.name = "rsr.dtlbcfg",
.translate = translate_rsr,
.test_ill = test_ill_rsr,
.par = (const uint32_t[]){DTLBCFG},
.op_flags = XTENSA_OP_PRIVILEGED,
- .windowed_register_op = 0x1,
}, {
.name = "rsr.epc1",
.translate = translate_rsr,
.test_ill = test_ill_rsr,
.par = (const uint32_t[]){EPC1},
.op_flags = XTENSA_OP_PRIVILEGED,
- .windowed_register_op = 0x1,
}, {
.name = "rsr.epc2",
.translate = translate_rsr,
.test_ill = test_ill_rsr,
.par = (const uint32_t[]){EPC1 + 1},
.op_flags = XTENSA_OP_PRIVILEGED,
- .windowed_register_op = 0x1,
}, {
.name = "rsr.epc3",
.translate = translate_rsr,
.test_ill = test_ill_rsr,
.par = (const uint32_t[]){EPC1 + 2},
.op_flags = XTENSA_OP_PRIVILEGED,
- .windowed_register_op = 0x1,
}, {
.name = "rsr.epc4",
.translate = translate_rsr,
.test_ill = test_ill_rsr,
.par = (const uint32_t[]){EPC1 + 3},
.op_flags = XTENSA_OP_PRIVILEGED,
- .windowed_register_op = 0x1,
}, {
.name = "rsr.epc5",
.translate = translate_rsr,
.test_ill = test_ill_rsr,
.par = (const uint32_t[]){EPC1 + 4},
.op_flags = XTENSA_OP_PRIVILEGED,
- .windowed_register_op = 0x1,
}, {
.name = "rsr.epc6",
.translate = translate_rsr,
.test_ill = test_ill_rsr,
.par = (const uint32_t[]){EPC1 + 5},
.op_flags = XTENSA_OP_PRIVILEGED,
- .windowed_register_op = 0x1,
}, {
.name = "rsr.epc7",
.translate = translate_rsr,
.test_ill = test_ill_rsr,
.par = (const uint32_t[]){EPC1 + 6},
.op_flags = XTENSA_OP_PRIVILEGED,
- .windowed_register_op = 0x1,
}, {
.name = "rsr.eps2",
.translate = translate_rsr,
.test_ill = test_ill_rsr,
.par = (const uint32_t[]){EPS2},
.op_flags = XTENSA_OP_PRIVILEGED,
- .windowed_register_op = 0x1,
}, {
.name = "rsr.eps3",
.translate = translate_rsr,
.test_ill = test_ill_rsr,
.par = (const uint32_t[]){EPS2 + 1},
.op_flags = XTENSA_OP_PRIVILEGED,
- .windowed_register_op = 0x1,
}, {
.name = "rsr.eps4",
.translate = translate_rsr,
.test_ill = test_ill_rsr,
.par = (const uint32_t[]){EPS2 + 2},
.op_flags = XTENSA_OP_PRIVILEGED,
- .windowed_register_op = 0x1,
}, {
.name = "rsr.eps5",
.translate = translate_rsr,
.test_ill = test_ill_rsr,
.par = (const uint32_t[]){EPS2 + 3},
.op_flags = XTENSA_OP_PRIVILEGED,
- .windowed_register_op = 0x1,
}, {
.name = "rsr.eps6",
.translate = translate_rsr,
.test_ill = test_ill_rsr,
.par = (const uint32_t[]){EPS2 + 4},
.op_flags = XTENSA_OP_PRIVILEGED,
- .windowed_register_op = 0x1,
}, {
.name = "rsr.eps7",
.translate = translate_rsr,
.test_ill = test_ill_rsr,
.par = (const uint32_t[]){EPS2 + 5},
.op_flags = XTENSA_OP_PRIVILEGED,
- .windowed_register_op = 0x1,
}, {
.name = "rsr.exccause",
.translate = translate_rsr,
.test_ill = test_ill_rsr,
.par = (const uint32_t[]){EXCCAUSE},
.op_flags = XTENSA_OP_PRIVILEGED,
- .windowed_register_op = 0x1,
}, {
.name = "rsr.excsave1",
.translate = translate_rsr,
.test_ill = test_ill_rsr,
.par = (const uint32_t[]){EXCSAVE1},
.op_flags = XTENSA_OP_PRIVILEGED,
- .windowed_register_op = 0x1,
}, {
.name = "rsr.excsave2",
.translate = translate_rsr,
.test_ill = test_ill_rsr,
.par = (const uint32_t[]){EXCSAVE1 + 1},
.op_flags = XTENSA_OP_PRIVILEGED,
- .windowed_register_op = 0x1,
}, {
.name = "rsr.excsave3",
.translate = translate_rsr,
.test_ill = test_ill_rsr,
.par = (const uint32_t[]){EXCSAVE1 + 2},
.op_flags = XTENSA_OP_PRIVILEGED,
- .windowed_register_op = 0x1,
}, {
.name = "rsr.excsave4",
.translate = translate_rsr,
.test_ill = test_ill_rsr,
.par = (const uint32_t[]){EXCSAVE1 + 3},
.op_flags = XTENSA_OP_PRIVILEGED,
- .windowed_register_op = 0x1,
}, {
.name = "rsr.excsave5",
.translate = translate_rsr,
.test_ill = test_ill_rsr,
.par = (const uint32_t[]){EXCSAVE1 + 4},
.op_flags = XTENSA_OP_PRIVILEGED,
- .windowed_register_op = 0x1,
}, {
.name = "rsr.excsave6",
.translate = translate_rsr,
.test_ill = test_ill_rsr,
.par = (const uint32_t[]){EXCSAVE1 + 5},
.op_flags = XTENSA_OP_PRIVILEGED,
- .windowed_register_op = 0x1,
}, {
.name = "rsr.excsave7",
.translate = translate_rsr,
.test_ill = test_ill_rsr,
.par = (const uint32_t[]){EXCSAVE1 + 6},
.op_flags = XTENSA_OP_PRIVILEGED,
- .windowed_register_op = 0x1,
}, {
.name = "rsr.excvaddr",
.translate = translate_rsr,
.test_ill = test_ill_rsr,
.par = (const uint32_t[]){EXCVADDR},
.op_flags = XTENSA_OP_PRIVILEGED,
- .windowed_register_op = 0x1,
}, {
.name = "rsr.ibreaka0",
.translate = translate_rsr,
.test_ill = test_ill_rsr,
.par = (const uint32_t[]){IBREAKA},
.op_flags = XTENSA_OP_PRIVILEGED,
- .windowed_register_op = 0x1,
}, {
.name = "rsr.ibreaka1",
.translate = translate_rsr,
.test_ill = test_ill_rsr,
.par = (const uint32_t[]){IBREAKA + 1},
.op_flags = XTENSA_OP_PRIVILEGED,
- .windowed_register_op = 0x1,
}, {
.name = "rsr.ibreakenable",
.translate = translate_rsr,
.test_ill = test_ill_rsr,
.par = (const uint32_t[]){IBREAKENABLE},
.op_flags = XTENSA_OP_PRIVILEGED,
- .windowed_register_op = 0x1,
}, {
.name = "rsr.icount",
.translate = translate_rsr,
.test_ill = test_ill_rsr,
.par = (const uint32_t[]){ICOUNT},
.op_flags = XTENSA_OP_PRIVILEGED,
- .windowed_register_op = 0x1,
}, {
.name = "rsr.icountlevel",
.translate = translate_rsr,
.test_ill = test_ill_rsr,
.par = (const uint32_t[]){ICOUNTLEVEL},
.op_flags = XTENSA_OP_PRIVILEGED,
- .windowed_register_op = 0x1,
}, {
.name = "rsr.intclear",
.translate = translate_rsr,
.test_ill = test_ill_rsr,
.par = (const uint32_t[]){INTCLEAR},
.op_flags = XTENSA_OP_PRIVILEGED,
- .windowed_register_op = 0x1,
}, {
.name = "rsr.intenable",
.translate = translate_rsr,
.test_ill = test_ill_rsr,
.par = (const uint32_t[]){INTENABLE},
.op_flags = XTENSA_OP_PRIVILEGED,
- .windowed_register_op = 0x1,
}, {
.name = "rsr.interrupt",
.translate = translate_rsr,
.test_ill = test_ill_rsr,
.par = (const uint32_t[]){INTSET},
.op_flags = XTENSA_OP_PRIVILEGED | XTENSA_OP_EXIT_TB_0,
- .windowed_register_op = 0x1,
}, {
.name = "rsr.intset",
.translate = translate_rsr,
.test_ill = test_ill_rsr,
.par = (const uint32_t[]){INTSET},
.op_flags = XTENSA_OP_PRIVILEGED | XTENSA_OP_EXIT_TB_0,
- .windowed_register_op = 0x1,
}, {
.name = "rsr.itlbcfg",
.translate = translate_rsr,
.test_ill = test_ill_rsr,
.par = (const uint32_t[]){ITLBCFG},
.op_flags = XTENSA_OP_PRIVILEGED,
- .windowed_register_op = 0x1,
}, {
.name = "rsr.lbeg",
.translate = translate_rsr,
.test_ill = test_ill_rsr,
.par = (const uint32_t[]){LBEG},
- .windowed_register_op = 0x1,
}, {
.name = "rsr.lcount",
.translate = translate_rsr,
.test_ill = test_ill_rsr,
.par = (const uint32_t[]){LCOUNT},
- .windowed_register_op = 0x1,
}, {
.name = "rsr.lend",
.translate = translate_rsr,
.test_ill = test_ill_rsr,
.par = (const uint32_t[]){LEND},
- .windowed_register_op = 0x1,
}, {
.name = "rsr.litbase",
.translate = translate_rsr,
.test_ill = test_ill_rsr,
.par = (const uint32_t[]){LITBASE},
- .windowed_register_op = 0x1,
}, {
.name = "rsr.m0",
.translate = translate_rsr,
.test_ill = test_ill_rsr,
.par = (const uint32_t[]){MR},
- .windowed_register_op = 0x1,
}, {
.name = "rsr.m1",
.translate = translate_rsr,
.test_ill = test_ill_rsr,
.par = (const uint32_t[]){MR + 1},
- .windowed_register_op = 0x1,
}, {
.name = "rsr.m2",
.translate = translate_rsr,
.test_ill = test_ill_rsr,
.par = (const uint32_t[]){MR + 2},
- .windowed_register_op = 0x1,
}, {
.name = "rsr.m3",
.translate = translate_rsr,
.test_ill = test_ill_rsr,
.par = (const uint32_t[]){MR + 3},
- .windowed_register_op = 0x1,
}, {
.name = "rsr.memctl",
.translate = translate_rsr,
.test_ill = test_ill_rsr,
.par = (const uint32_t[]){MEMCTL},
.op_flags = XTENSA_OP_PRIVILEGED,
- .windowed_register_op = 0x1,
}, {
.name = "rsr.misc0",
.translate = translate_rsr,
.test_ill = test_ill_rsr,
.par = (const uint32_t[]){MISC},
.op_flags = XTENSA_OP_PRIVILEGED,
- .windowed_register_op = 0x1,
}, {
.name = "rsr.misc1",
.translate = translate_rsr,
.test_ill = test_ill_rsr,
.par = (const uint32_t[]){MISC + 1},
.op_flags = XTENSA_OP_PRIVILEGED,
- .windowed_register_op = 0x1,
}, {
.name = "rsr.misc2",
.translate = translate_rsr,
.test_ill = test_ill_rsr,
.par = (const uint32_t[]){MISC + 2},
.op_flags = XTENSA_OP_PRIVILEGED,
- .windowed_register_op = 0x1,
}, {
.name = "rsr.misc3",
.translate = translate_rsr,
.test_ill = test_ill_rsr,
.par = (const uint32_t[]){MISC + 3},
.op_flags = XTENSA_OP_PRIVILEGED,
- .windowed_register_op = 0x1,
+ }, {
+ .name = "rsr.prefctl",
+ .translate = translate_rsr,
+ .test_ill = test_ill_rsr,
+ .par = (const uint32_t[]){PREFCTL},
}, {
.name = "rsr.prid",
.translate = translate_rsr,
.test_ill = test_ill_rsr,
.par = (const uint32_t[]){PRID},
.op_flags = XTENSA_OP_PRIVILEGED,
- .windowed_register_op = 0x1,
}, {
.name = "rsr.ps",
.translate = translate_rsr,
.test_ill = test_ill_rsr,
.par = (const uint32_t[]){PS},
.op_flags = XTENSA_OP_PRIVILEGED,
- .windowed_register_op = 0x1,
}, {
.name = "rsr.ptevaddr",
.translate = translate_rsr,
.test_ill = test_ill_rsr,
.par = (const uint32_t[]){PTEVADDR},
.op_flags = XTENSA_OP_PRIVILEGED,
- .windowed_register_op = 0x1,
}, {
.name = "rsr.rasid",
.translate = translate_rsr,
.test_ill = test_ill_rsr,
.par = (const uint32_t[]){RASID},
.op_flags = XTENSA_OP_PRIVILEGED,
- .windowed_register_op = 0x1,
}, {
.name = "rsr.sar",
.translate = translate_rsr,
.test_ill = test_ill_rsr,
.par = (const uint32_t[]){SAR},
- .windowed_register_op = 0x1,
}, {
.name = "rsr.scompare1",
.translate = translate_rsr,
.test_ill = test_ill_rsr,
.par = (const uint32_t[]){SCOMPARE1},
- .windowed_register_op = 0x1,
}, {
.name = "rsr.vecbase",
.translate = translate_rsr,
.test_ill = test_ill_rsr,
.par = (const uint32_t[]){VECBASE},
.op_flags = XTENSA_OP_PRIVILEGED,
- .windowed_register_op = 0x1,
}, {
.name = "rsr.windowbase",
.translate = translate_rsr,
.test_ill = test_ill_rsr,
.par = (const uint32_t[]){WINDOW_BASE},
.op_flags = XTENSA_OP_PRIVILEGED,
- .windowed_register_op = 0x1,
}, {
.name = "rsr.windowstart",
.translate = translate_rsr,
.test_ill = test_ill_rsr,
.par = (const uint32_t[]){WINDOW_START},
.op_flags = XTENSA_OP_PRIVILEGED,
- .windowed_register_op = 0x1,
}, {
.name = "rsync",
.translate = translate_nop,
@@ -3993,80 +4217,64 @@
.name = "rur.expstate",
.translate = translate_rur,
.par = (const uint32_t[]){EXPSTATE},
- .windowed_register_op = 0x1,
}, {
.name = "rur.fcr",
.translate = translate_rur,
.par = (const uint32_t[]){FCR},
- .windowed_register_op = 0x1,
.coprocessor = 0x1,
}, {
.name = "rur.fsr",
.translate = translate_rur,
.par = (const uint32_t[]){FSR},
- .windowed_register_op = 0x1,
.coprocessor = 0x1,
}, {
.name = "rur.threadptr",
.translate = translate_rur,
.par = (const uint32_t[]){THREADPTR},
- .windowed_register_op = 0x1,
}, {
.name = "s16i",
.translate = translate_ldst,
.par = (const uint32_t[]){MO_TEUW, false, true},
- .windowed_register_op = 0x3,
+ .op_flags = XTENSA_OP_STORE,
}, {
.name = "s32c1i",
.translate = translate_s32c1i,
- .windowed_register_op = 0x3,
+ .op_flags = XTENSA_OP_LOAD | XTENSA_OP_STORE,
}, {
.name = "s32e",
.translate = translate_s32e,
- .op_flags = XTENSA_OP_PRIVILEGED,
- .windowed_register_op = 0x3,
+ .op_flags = XTENSA_OP_PRIVILEGED | XTENSA_OP_STORE,
}, {
- .name = "s32i",
+ .name = (const char * const[]) {
+ "s32i", "s32i.n", "s32nb", NULL,
+ },
.translate = translate_ldst,
.par = (const uint32_t[]){MO_TEUL, false, true},
- .windowed_register_op = 0x3,
- }, {
- .name = "s32i.n",
- .translate = translate_ldst,
- .par = (const uint32_t[]){MO_TEUL, false, true},
- .windowed_register_op = 0x3,
- }, {
- .name = "s32nb",
- .translate = translate_ldst,
- .par = (const uint32_t[]){MO_TEUL, false, true},
- .windowed_register_op = 0x3,
+ .op_flags = XTENSA_OP_NAME_ARRAY | XTENSA_OP_STORE,
}, {
.name = "s32ri",
.translate = translate_ldst,
.par = (const uint32_t[]){MO_TEUL, true, true},
- .windowed_register_op = 0x3,
+ .op_flags = XTENSA_OP_STORE,
}, {
.name = "s8i",
.translate = translate_ldst,
.par = (const uint32_t[]){MO_UB, false, true},
- .windowed_register_op = 0x3,
+ .op_flags = XTENSA_OP_STORE,
}, {
.name = "salt",
.translate = translate_salt,
.par = (const uint32_t[]){TCG_COND_LT},
- .windowed_register_op = 0x7,
}, {
.name = "saltu",
.translate = translate_salt,
.par = (const uint32_t[]){TCG_COND_LTU},
- .windowed_register_op = 0x7,
}, {
.name = "setb_expstate",
.translate = translate_setb_expstate,
}, {
.name = "sext",
.translate = translate_sext,
- .windowed_register_op = 0x3,
}, {
.name = "simcall",
.translate = translate_simcall,
@@ -4075,92 +4283,73 @@
}, {
.name = "sll",
.translate = translate_sll,
- .windowed_register_op = 0x3,
}, {
.name = "slli",
.translate = translate_slli,
- .windowed_register_op = 0x3,
}, {
.name = "sra",
.translate = translate_sra,
- .windowed_register_op = 0x3,
}, {
.name = "srai",
.translate = translate_srai,
- .windowed_register_op = 0x3,
}, {
.name = "src",
.translate = translate_src,
- .windowed_register_op = 0x7,
}, {
.name = "srl",
.translate = translate_srl,
- .windowed_register_op = 0x3,
}, {
.name = "srli",
.translate = translate_srli,
- .windowed_register_op = 0x3,
}, {
.name = "ssa8b",
.translate = translate_ssa8b,
- .windowed_register_op = 0x1,
}, {
.name = "ssa8l",
.translate = translate_ssa8l,
- .windowed_register_op = 0x1,
}, {
.name = "ssai",
.translate = translate_ssai,
}, {
.name = "ssl",
.translate = translate_ssl,
- .windowed_register_op = 0x1,
}, {
.name = "ssr",
.translate = translate_ssr,
- .windowed_register_op = 0x1,
}, {
.name = "sub",
.translate = translate_sub,
- .windowed_register_op = 0x7,
}, {
.name = "subx2",
.translate = translate_subx,
.par = (const uint32_t[]){1},
- .windowed_register_op = 0x7,
}, {
.name = "subx4",
.translate = translate_subx,
.par = (const uint32_t[]){2},
- .windowed_register_op = 0x7,
}, {
.name = "subx8",
.translate = translate_subx,
.par = (const uint32_t[]){3},
- .windowed_register_op = 0x7,
}, {
.name = "syscall",
.op_flags = XTENSA_OP_SYSCALL,
}, {
.name = "umul.aa.hh",
.translate = translate_mac16,
- .par = (const uint32_t[]){MAC16_UMUL, MAC16_AA, MAC16_HH, 0},
- .windowed_register_op = 0x3,
+ .par = (const uint32_t[]){MAC16_UMUL, MAC16_HH, 0},
}, {
.name = "umul.aa.hl",
.translate = translate_mac16,
- .par = (const uint32_t[]){MAC16_UMUL, MAC16_AA, MAC16_HL, 0},
- .windowed_register_op = 0x3,
+ .par = (const uint32_t[]){MAC16_UMUL, MAC16_HL, 0},
}, {
.name = "umul.aa.lh",
.translate = translate_mac16,
- .par = (const uint32_t[]){MAC16_UMUL, MAC16_AA, MAC16_LH, 0},
- .windowed_register_op = 0x3,
+ .par = (const uint32_t[]){MAC16_UMUL, MAC16_LH, 0},
}, {
.name = "umul.aa.ll",
.translate = translate_mac16,
- .par = (const uint32_t[]){MAC16_UMUL, MAC16_AA, MAC16_LL, 0},
- .windowed_register_op = 0x3,
+ .par = (const uint32_t[]){MAC16_UMUL, MAC16_LL, 0},
}, {
.name = "waiti",
.translate = translate_waiti,
@@ -4170,362 +4359,309 @@
.translate = translate_wtlb,
.par = (const uint32_t[]){true},
.op_flags = XTENSA_OP_PRIVILEGED | XTENSA_OP_EXIT_TB_M1,
- .windowed_register_op = 0x3,
}, {
.name = "wer",
.translate = translate_wer,
.op_flags = XTENSA_OP_PRIVILEGED,
- .windowed_register_op = 0x3,
}, {
.name = "witlb",
.translate = translate_wtlb,
.par = (const uint32_t[]){false},
.op_flags = XTENSA_OP_PRIVILEGED | XTENSA_OP_EXIT_TB_M1,
- .windowed_register_op = 0x3,
}, {
.name = "wrmsk_expstate",
.translate = translate_wrmsk_expstate,
- .windowed_register_op = 0x3,
}, {
.name = "wsr.176",
.translate = translate_wsr,
.test_ill = test_ill_wsr,
.par = (const uint32_t[]){176},
.op_flags = XTENSA_OP_PRIVILEGED,
- .windowed_register_op = 0x1,
}, {
.name = "wsr.208",
.translate = translate_wsr,
.test_ill = test_ill_wsr,
.par = (const uint32_t[]){208},
.op_flags = XTENSA_OP_PRIVILEGED,
- .windowed_register_op = 0x1,
}, {
.name = "wsr.acchi",
.translate = translate_wsr,
.test_ill = test_ill_wsr,
.par = (const uint32_t[]){ACCHI},
- .windowed_register_op = 0x1,
}, {
.name = "wsr.acclo",
.translate = translate_wsr,
.test_ill = test_ill_wsr,
.par = (const uint32_t[]){ACCLO},
- .windowed_register_op = 0x1,
}, {
.name = "wsr.atomctl",
.translate = translate_wsr,
.test_ill = test_ill_wsr,
.par = (const uint32_t[]){ATOMCTL},
.op_flags = XTENSA_OP_PRIVILEGED,
- .windowed_register_op = 0x1,
}, {
.name = "wsr.br",
.translate = translate_wsr,
.test_ill = test_ill_wsr,
.par = (const uint32_t[]){BR},
- .windowed_register_op = 0x1,
}, {
.name = "wsr.cacheattr",
.translate = translate_wsr,
.test_ill = test_ill_wsr,
.par = (const uint32_t[]){CACHEATTR},
.op_flags = XTENSA_OP_PRIVILEGED,
- .windowed_register_op = 0x1,
}, {
.name = "wsr.ccompare0",
.translate = translate_wsr,
.test_ill = test_ill_wsr,
.par = (const uint32_t[]){CCOMPARE},
.op_flags = XTENSA_OP_PRIVILEGED | XTENSA_OP_EXIT_TB_0,
- .windowed_register_op = 0x1,
}, {
.name = "wsr.ccompare1",
.translate = translate_wsr,
.test_ill = test_ill_wsr,
.par = (const uint32_t[]){CCOMPARE + 1},
.op_flags = XTENSA_OP_PRIVILEGED | XTENSA_OP_EXIT_TB_0,
- .windowed_register_op = 0x1,
}, {
.name = "wsr.ccompare2",
.translate = translate_wsr,
.test_ill = test_ill_wsr,
.par = (const uint32_t[]){CCOMPARE + 2},
.op_flags = XTENSA_OP_PRIVILEGED | XTENSA_OP_EXIT_TB_0,
- .windowed_register_op = 0x1,
}, {
.name = "wsr.ccount",
.translate = translate_wsr,
.test_ill = test_ill_wsr,
.par = (const uint32_t[]){CCOUNT},
.op_flags = XTENSA_OP_PRIVILEGED | XTENSA_OP_EXIT_TB_0,
- .windowed_register_op = 0x1,
}, {
.name = "wsr.configid0",
.translate = translate_wsr,
.test_ill = test_ill_wsr,
.par = (const uint32_t[]){CONFIGID0},
.op_flags = XTENSA_OP_PRIVILEGED,
- .windowed_register_op = 0x1,
}, {
.name = "wsr.configid1",
.translate = translate_wsr,
.test_ill = test_ill_wsr,
.par = (const uint32_t[]){CONFIGID1},
.op_flags = XTENSA_OP_PRIVILEGED,
- .windowed_register_op = 0x1,
}, {
.name = "wsr.cpenable",
.translate = translate_wsr,
.test_ill = test_ill_wsr,
.par = (const uint32_t[]){CPENABLE},
.op_flags = XTENSA_OP_PRIVILEGED | XTENSA_OP_EXIT_TB_M1,
- .windowed_register_op = 0x1,
}, {
.name = "wsr.dbreaka0",
.translate = translate_wsr,
.test_ill = test_ill_wsr,
.par = (const uint32_t[]){DBREAKA},
.op_flags = XTENSA_OP_PRIVILEGED,
- .windowed_register_op = 0x1,
}, {
.name = "wsr.dbreaka1",
.translate = translate_wsr,
.test_ill = test_ill_wsr,
.par = (const uint32_t[]){DBREAKA + 1},
.op_flags = XTENSA_OP_PRIVILEGED,
- .windowed_register_op = 0x1,
}, {
.name = "wsr.dbreakc0",
.translate = translate_wsr,
.test_ill = test_ill_wsr,
.par = (const uint32_t[]){DBREAKC},
.op_flags = XTENSA_OP_PRIVILEGED,
- .windowed_register_op = 0x1,
}, {
.name = "wsr.dbreakc1",
.translate = translate_wsr,
.test_ill = test_ill_wsr,
.par = (const uint32_t[]){DBREAKC + 1},
.op_flags = XTENSA_OP_PRIVILEGED,
- .windowed_register_op = 0x1,
}, {
.name = "wsr.ddr",
.translate = translate_wsr,
.test_ill = test_ill_wsr,
.par = (const uint32_t[]){DDR},
.op_flags = XTENSA_OP_PRIVILEGED,
- .windowed_register_op = 0x1,
}, {
.name = "wsr.debugcause",
.translate = translate_wsr,
.test_ill = test_ill_wsr,
.par = (const uint32_t[]){DEBUGCAUSE},
.op_flags = XTENSA_OP_PRIVILEGED,
- .windowed_register_op = 0x1,
}, {
.name = "wsr.depc",
.translate = translate_wsr,
.test_ill = test_ill_wsr,
.par = (const uint32_t[]){DEPC},
.op_flags = XTENSA_OP_PRIVILEGED,
- .windowed_register_op = 0x1,
}, {
.name = "wsr.dtlbcfg",
.translate = translate_wsr,
.test_ill = test_ill_wsr,
.par = (const uint32_t[]){DTLBCFG},
.op_flags = XTENSA_OP_PRIVILEGED,
- .windowed_register_op = 0x1,
}, {
.name = "wsr.epc1",
.translate = translate_wsr,
.test_ill = test_ill_wsr,
.par = (const uint32_t[]){EPC1},
.op_flags = XTENSA_OP_PRIVILEGED,
- .windowed_register_op = 0x1,
}, {
.name = "wsr.epc2",
.translate = translate_wsr,
.test_ill = test_ill_wsr,
.par = (const uint32_t[]){EPC1 + 1},
.op_flags = XTENSA_OP_PRIVILEGED,
- .windowed_register_op = 0x1,
}, {
.name = "wsr.epc3",
.translate = translate_wsr,
.test_ill = test_ill_wsr,
.par = (const uint32_t[]){EPC1 + 2},
.op_flags = XTENSA_OP_PRIVILEGED,
- .windowed_register_op = 0x1,
}, {
.name = "wsr.epc4",
.translate = translate_wsr,
.test_ill = test_ill_wsr,
.par = (const uint32_t[]){EPC1 + 3},
.op_flags = XTENSA_OP_PRIVILEGED,
- .windowed_register_op = 0x1,
}, {
.name = "wsr.epc5",
.translate = translate_wsr,
.test_ill = test_ill_wsr,
.par = (const uint32_t[]){EPC1 + 4},
.op_flags = XTENSA_OP_PRIVILEGED,
- .windowed_register_op = 0x1,
}, {
.name = "wsr.epc6",
.translate = translate_wsr,
.test_ill = test_ill_wsr,
.par = (const uint32_t[]){EPC1 + 5},
.op_flags = XTENSA_OP_PRIVILEGED,
- .windowed_register_op = 0x1,
}, {
.name = "wsr.epc7",
.translate = translate_wsr,
.test_ill = test_ill_wsr,
.par = (const uint32_t[]){EPC1 + 6},
.op_flags = XTENSA_OP_PRIVILEGED,
- .windowed_register_op = 0x1,
}, {
.name = "wsr.eps2",
.translate = translate_wsr,
.test_ill = test_ill_wsr,
.par = (const uint32_t[]){EPS2},
.op_flags = XTENSA_OP_PRIVILEGED,
- .windowed_register_op = 0x1,
}, {
.name = "wsr.eps3",
.translate = translate_wsr,
.test_ill = test_ill_wsr,
.par = (const uint32_t[]){EPS2 + 1},
.op_flags = XTENSA_OP_PRIVILEGED,
- .windowed_register_op = 0x1,
}, {
.name = "wsr.eps4",
.translate = translate_wsr,
.test_ill = test_ill_wsr,
.par = (const uint32_t[]){EPS2 + 2},
.op_flags = XTENSA_OP_PRIVILEGED,
- .windowed_register_op = 0x1,
}, {
.name = "wsr.eps5",
.translate = translate_wsr,
.test_ill = test_ill_wsr,
.par = (const uint32_t[]){EPS2 + 3},
.op_flags = XTENSA_OP_PRIVILEGED,
- .windowed_register_op = 0x1,
}, {
.name = "wsr.eps6",
.translate = translate_wsr,
.test_ill = test_ill_wsr,
.par = (const uint32_t[]){EPS2 + 4},
.op_flags = XTENSA_OP_PRIVILEGED,
- .windowed_register_op = 0x1,
}, {
.name = "wsr.eps7",
.translate = translate_wsr,
.test_ill = test_ill_wsr,
.par = (const uint32_t[]){EPS2 + 5},
.op_flags = XTENSA_OP_PRIVILEGED,
- .windowed_register_op = 0x1,
}, {
.name = "wsr.exccause",
.translate = translate_wsr,
.test_ill = test_ill_wsr,
.par = (const uint32_t[]){EXCCAUSE},
.op_flags = XTENSA_OP_PRIVILEGED,
- .windowed_register_op = 0x1,
}, {
.name = "wsr.excsave1",
.translate = translate_wsr,
.test_ill = test_ill_wsr,
.par = (const uint32_t[]){EXCSAVE1},
.op_flags = XTENSA_OP_PRIVILEGED,
- .windowed_register_op = 0x1,
}, {
.name = "wsr.excsave2",
.translate = translate_wsr,
.test_ill = test_ill_wsr,
.par = (const uint32_t[]){EXCSAVE1 + 1},
.op_flags = XTENSA_OP_PRIVILEGED,
- .windowed_register_op = 0x1,
}, {
.name = "wsr.excsave3",
.translate = translate_wsr,
.test_ill = test_ill_wsr,
.par = (const uint32_t[]){EXCSAVE1 + 2},
.op_flags = XTENSA_OP_PRIVILEGED,
- .windowed_register_op = 0x1,
}, {
.name = "wsr.excsave4",
.translate = translate_wsr,
.test_ill = test_ill_wsr,
.par = (const uint32_t[]){EXCSAVE1 + 3},
.op_flags = XTENSA_OP_PRIVILEGED,
- .windowed_register_op = 0x1,
}, {
.name = "wsr.excsave5",
.translate = translate_wsr,
.test_ill = test_ill_wsr,
.par = (const uint32_t[]){EXCSAVE1 + 4},
.op_flags = XTENSA_OP_PRIVILEGED,
- .windowed_register_op = 0x1,
}, {
.name = "wsr.excsave6",
.translate = translate_wsr,
.test_ill = test_ill_wsr,
.par = (const uint32_t[]){EXCSAVE1 + 5},
.op_flags = XTENSA_OP_PRIVILEGED,
- .windowed_register_op = 0x1,
}, {
.name = "wsr.excsave7",
.translate = translate_wsr,
.test_ill = test_ill_wsr,
.par = (const uint32_t[]){EXCSAVE1 + 6},
.op_flags = XTENSA_OP_PRIVILEGED,
- .windowed_register_op = 0x1,
}, {
.name = "wsr.excvaddr",
.translate = translate_wsr,
.test_ill = test_ill_wsr,
.par = (const uint32_t[]){EXCVADDR},
.op_flags = XTENSA_OP_PRIVILEGED,
- .windowed_register_op = 0x1,
}, {
.name = "wsr.ibreaka0",
.translate = translate_wsr,
.test_ill = test_ill_wsr,
.par = (const uint32_t[]){IBREAKA},
.op_flags = XTENSA_OP_PRIVILEGED | XTENSA_OP_EXIT_TB_0,
- .windowed_register_op = 0x1,
}, {
.name = "wsr.ibreaka1",
.translate = translate_wsr,
.test_ill = test_ill_wsr,
.par = (const uint32_t[]){IBREAKA + 1},
.op_flags = XTENSA_OP_PRIVILEGED | XTENSA_OP_EXIT_TB_0,
- .windowed_register_op = 0x1,
}, {
.name = "wsr.ibreakenable",
.translate = translate_wsr,
.test_ill = test_ill_wsr,
.par = (const uint32_t[]){IBREAKENABLE},
.op_flags = XTENSA_OP_PRIVILEGED | XTENSA_OP_EXIT_TB_0,
- .windowed_register_op = 0x1,
}, {
.name = "wsr.icount",
.translate = translate_wsr,
.test_ill = test_ill_wsr,
.par = (const uint32_t[]){ICOUNT},
.op_flags = XTENSA_OP_PRIVILEGED,
- .windowed_register_op = 0x1,
}, {
.name = "wsr.icountlevel",
.translate = translate_wsr,
.test_ill = test_ill_wsr,
.par = (const uint32_t[]){ICOUNTLEVEL},
.op_flags = XTENSA_OP_PRIVILEGED | XTENSA_OP_EXIT_TB_M1,
- .windowed_register_op = 0x1,
}, {
.name = "wsr.intclear",
.translate = translate_wsr,
@@ -4535,7 +4671,6 @@
XTENSA_OP_PRIVILEGED |
XTENSA_OP_EXIT_TB_0 |
XTENSA_OP_CHECK_INTERRUPTS,
- .windowed_register_op = 0x1,
}, {
.name = "wsr.intenable",
.translate = translate_wsr,
@@ -4545,7 +4680,6 @@
XTENSA_OP_PRIVILEGED |
XTENSA_OP_EXIT_TB_0 |
XTENSA_OP_CHECK_INTERRUPTS,
- .windowed_register_op = 0x1,
}, {
.name = "wsr.interrupt",
.translate = translate_wsr,
@@ -4555,7 +4689,6 @@
XTENSA_OP_PRIVILEGED |
XTENSA_OP_EXIT_TB_0 |
XTENSA_OP_CHECK_INTERRUPTS,
- .windowed_register_op = 0x1,
}, {
.name = "wsr.intset",
.translate = translate_wsr,
@@ -4565,114 +4698,102 @@
XTENSA_OP_PRIVILEGED |
XTENSA_OP_EXIT_TB_0 |
XTENSA_OP_CHECK_INTERRUPTS,
- .windowed_register_op = 0x1,
}, {
.name = "wsr.itlbcfg",
.translate = translate_wsr,
.test_ill = test_ill_wsr,
.par = (const uint32_t[]){ITLBCFG},
.op_flags = XTENSA_OP_PRIVILEGED,
- .windowed_register_op = 0x1,
}, {
.name = "wsr.lbeg",
.translate = translate_wsr,
.test_ill = test_ill_wsr,
.par = (const uint32_t[]){LBEG},
.op_flags = XTENSA_OP_EXIT_TB_M1,
- .windowed_register_op = 0x1,
}, {
.name = "wsr.lcount",
.translate = translate_wsr,
.test_ill = test_ill_wsr,
.par = (const uint32_t[]){LCOUNT},
- .windowed_register_op = 0x1,
}, {
.name = "wsr.lend",
.translate = translate_wsr,
.test_ill = test_ill_wsr,
.par = (const uint32_t[]){LEND},
.op_flags = XTENSA_OP_EXIT_TB_M1,
- .windowed_register_op = 0x1,
}, {
.name = "wsr.litbase",
.translate = translate_wsr,
.test_ill = test_ill_wsr,
.par = (const uint32_t[]){LITBASE},
.op_flags = XTENSA_OP_EXIT_TB_M1,
- .windowed_register_op = 0x1,
}, {
.name = "wsr.m0",
.translate = translate_wsr,
.test_ill = test_ill_wsr,
.par = (const uint32_t[]){MR},
- .windowed_register_op = 0x1,
}, {
.name = "wsr.m1",
.translate = translate_wsr,
.test_ill = test_ill_wsr,
.par = (const uint32_t[]){MR + 1},
- .windowed_register_op = 0x1,
}, {
.name = "wsr.m2",
.translate = translate_wsr,
.test_ill = test_ill_wsr,
.par = (const uint32_t[]){MR + 2},
- .windowed_register_op = 0x1,
}, {
.name = "wsr.m3",
.translate = translate_wsr,
.test_ill = test_ill_wsr,
.par = (const uint32_t[]){MR + 3},
- .windowed_register_op = 0x1,
}, {
.name = "wsr.memctl",
.translate = translate_wsr,
.test_ill = test_ill_wsr,
.par = (const uint32_t[]){MEMCTL},
.op_flags = XTENSA_OP_PRIVILEGED,
- .windowed_register_op = 0x1,
}, {
.name = "wsr.misc0",
.translate = translate_wsr,
.test_ill = test_ill_wsr,
.par = (const uint32_t[]){MISC},
.op_flags = XTENSA_OP_PRIVILEGED,
- .windowed_register_op = 0x1,
}, {
.name = "wsr.misc1",
.translate = translate_wsr,
.test_ill = test_ill_wsr,
.par = (const uint32_t[]){MISC + 1},
.op_flags = XTENSA_OP_PRIVILEGED,
- .windowed_register_op = 0x1,
}, {
.name = "wsr.misc2",
.translate = translate_wsr,
.test_ill = test_ill_wsr,
.par = (const uint32_t[]){MISC + 2},
.op_flags = XTENSA_OP_PRIVILEGED,
- .windowed_register_op = 0x1,
}, {
.name = "wsr.misc3",
.translate = translate_wsr,
.test_ill = test_ill_wsr,
.par = (const uint32_t[]){MISC + 3},
.op_flags = XTENSA_OP_PRIVILEGED,
- .windowed_register_op = 0x1,
}, {
.name = "wsr.mmid",
.translate = translate_wsr,
.test_ill = test_ill_wsr,
.par = (const uint32_t[]){MMID},
.op_flags = XTENSA_OP_PRIVILEGED,
- .windowed_register_op = 0x1,
+ }, {
+ .name = "wsr.prefctl",
+ .translate = translate_wsr,
+ .test_ill = test_ill_wsr,
+ .par = (const uint32_t[]){PREFCTL},
}, {
.name = "wsr.prid",
.translate = translate_wsr,
.test_ill = test_ill_wsr,
.par = (const uint32_t[]){PRID},
.op_flags = XTENSA_OP_PRIVILEGED,
- .windowed_register_op = 0x1,
}, {
.name = "wsr.ps",
.translate = translate_wsr,
@@ -4682,80 +4803,69 @@
XTENSA_OP_PRIVILEGED |
XTENSA_OP_EXIT_TB_M1 |
XTENSA_OP_CHECK_INTERRUPTS,
- .windowed_register_op = 0x1,
}, {
.name = "wsr.ptevaddr",
.translate = translate_wsr,
.test_ill = test_ill_wsr,
.par = (const uint32_t[]){PTEVADDR},
.op_flags = XTENSA_OP_PRIVILEGED,
- .windowed_register_op = 0x1,
}, {
.name = "wsr.rasid",
.translate = translate_wsr,
.test_ill = test_ill_wsr,
.par = (const uint32_t[]){RASID},
.op_flags = XTENSA_OP_PRIVILEGED | XTENSA_OP_EXIT_TB_M1,
- .windowed_register_op = 0x1,
}, {
.name = "wsr.sar",
.translate = translate_wsr,
.test_ill = test_ill_wsr,
.par = (const uint32_t[]){SAR},
- .windowed_register_op = 0x1,
}, {
.name = "wsr.scompare1",
.translate = translate_wsr,
.test_ill = test_ill_wsr,
.par = (const uint32_t[]){SCOMPARE1},
- .windowed_register_op = 0x1,
}, {
.name = "wsr.vecbase",
.translate = translate_wsr,
.test_ill = test_ill_wsr,
.par = (const uint32_t[]){VECBASE},
.op_flags = XTENSA_OP_PRIVILEGED,
- .windowed_register_op = 0x1,
}, {
.name = "wsr.windowbase",
.translate = translate_wsr,
.test_ill = test_ill_wsr,
.par = (const uint32_t[]){WINDOW_BASE},
- .op_flags = XTENSA_OP_PRIVILEGED | XTENSA_OP_EXIT_TB_M1,
- .windowed_register_op = 0x1,
+ .op_flags = XTENSA_OP_PRIVILEGED |
+ XTENSA_OP_EXIT_TB_M1 |
+ XTENSA_OP_SYNC_REGISTER_WINDOW,
}, {
.name = "wsr.windowstart",
.translate = translate_wsr,
.test_ill = test_ill_wsr,
.par = (const uint32_t[]){WINDOW_START},
.op_flags = XTENSA_OP_PRIVILEGED | XTENSA_OP_EXIT_TB_M1,
- .windowed_register_op = 0x1,
}, {
.name = "wur.expstate",
.translate = translate_wur,
.par = (const uint32_t[]){EXPSTATE},
- .windowed_register_op = 0x1,
}, {
.name = "wur.fcr",
.translate = translate_wur,
.par = (const uint32_t[]){FCR},
- .windowed_register_op = 0x1,
.coprocessor = 0x1,
}, {
.name = "wur.fsr",
.translate = translate_wur,
.par = (const uint32_t[]){FSR},
- .windowed_register_op = 0x1,
.coprocessor = 0x1,
}, {
.name = "wur.threadptr",
.translate = translate_wur,
.par = (const uint32_t[]){THREADPTR},
- .windowed_register_op = 0x1,
}, {
.name = "xor",
.translate = translate_xor,
- .windowed_register_op = 0x7,
}, {
.name = "xorb",
.translate = translate_boolean,
@@ -4766,340 +4876,291 @@
.test_ill = test_ill_xsr,
.par = (const uint32_t[]){176},
.op_flags = XTENSA_OP_PRIVILEGED,
- .windowed_register_op = 0x1,
}, {
.name = "xsr.208",
.translate = translate_xsr,
.test_ill = test_ill_xsr,
.par = (const uint32_t[]){208},
.op_flags = XTENSA_OP_PRIVILEGED,
- .windowed_register_op = 0x1,
}, {
.name = "xsr.acchi",
.translate = translate_xsr,
.test_ill = test_ill_xsr,
.par = (const uint32_t[]){ACCHI},
- .windowed_register_op = 0x1,
}, {
.name = "xsr.acclo",
.translate = translate_xsr,
.test_ill = test_ill_xsr,
.par = (const uint32_t[]){ACCLO},
- .windowed_register_op = 0x1,
}, {
.name = "xsr.atomctl",
.translate = translate_xsr,
.test_ill = test_ill_xsr,
.par = (const uint32_t[]){ATOMCTL},
.op_flags = XTENSA_OP_PRIVILEGED,
- .windowed_register_op = 0x1,
}, {
.name = "xsr.br",
.translate = translate_xsr,
.test_ill = test_ill_xsr,
.par = (const uint32_t[]){BR},
- .windowed_register_op = 0x1,
}, {
.name = "xsr.cacheattr",
.translate = translate_xsr,
.test_ill = test_ill_xsr,
.par = (const uint32_t[]){CACHEATTR},
.op_flags = XTENSA_OP_PRIVILEGED,
- .windowed_register_op = 0x1,
}, {
.name = "xsr.ccompare0",
.translate = translate_xsr,
.test_ill = test_ill_xsr,
.par = (const uint32_t[]){CCOMPARE},
.op_flags = XTENSA_OP_PRIVILEGED | XTENSA_OP_EXIT_TB_0,
- .windowed_register_op = 0x1,
}, {
.name = "xsr.ccompare1",
.translate = translate_xsr,
.test_ill = test_ill_xsr,
.par = (const uint32_t[]){CCOMPARE + 1},
.op_flags = XTENSA_OP_PRIVILEGED | XTENSA_OP_EXIT_TB_0,
- .windowed_register_op = 0x1,
}, {
.name = "xsr.ccompare2",
.translate = translate_xsr,
.test_ill = test_ill_xsr,
.par = (const uint32_t[]){CCOMPARE + 2},
.op_flags = XTENSA_OP_PRIVILEGED | XTENSA_OP_EXIT_TB_0,
- .windowed_register_op = 0x1,
}, {
.name = "xsr.ccount",
.translate = translate_xsr,
.test_ill = test_ill_xsr,
.par = (const uint32_t[]){CCOUNT},
.op_flags = XTENSA_OP_PRIVILEGED | XTENSA_OP_EXIT_TB_0,
- .windowed_register_op = 0x1,
}, {
.name = "xsr.configid0",
.translate = translate_xsr,
.test_ill = test_ill_xsr,
.par = (const uint32_t[]){CONFIGID0},
.op_flags = XTENSA_OP_PRIVILEGED,
- .windowed_register_op = 0x1,
}, {
.name = "xsr.configid1",
.translate = translate_xsr,
.test_ill = test_ill_xsr,
.par = (const uint32_t[]){CONFIGID1},
.op_flags = XTENSA_OP_PRIVILEGED,
- .windowed_register_op = 0x1,
}, {
.name = "xsr.cpenable",
.translate = translate_xsr,
.test_ill = test_ill_xsr,
.par = (const uint32_t[]){CPENABLE},
.op_flags = XTENSA_OP_PRIVILEGED | XTENSA_OP_EXIT_TB_M1,
- .windowed_register_op = 0x1,
}, {
.name = "xsr.dbreaka0",
.translate = translate_xsr,
.test_ill = test_ill_xsr,
.par = (const uint32_t[]){DBREAKA},
.op_flags = XTENSA_OP_PRIVILEGED,
- .windowed_register_op = 0x1,
}, {
.name = "xsr.dbreaka1",
.translate = translate_xsr,
.test_ill = test_ill_xsr,
.par = (const uint32_t[]){DBREAKA + 1},
.op_flags = XTENSA_OP_PRIVILEGED,
- .windowed_register_op = 0x1,
}, {
.name = "xsr.dbreakc0",
.translate = translate_xsr,
.test_ill = test_ill_xsr,
.par = (const uint32_t[]){DBREAKC},
.op_flags = XTENSA_OP_PRIVILEGED,
- .windowed_register_op = 0x1,
}, {
.name = "xsr.dbreakc1",
.translate = translate_xsr,
.test_ill = test_ill_xsr,
.par = (const uint32_t[]){DBREAKC + 1},
.op_flags = XTENSA_OP_PRIVILEGED,
- .windowed_register_op = 0x1,
}, {
.name = "xsr.ddr",
.translate = translate_xsr,
.test_ill = test_ill_xsr,
.par = (const uint32_t[]){DDR},
.op_flags = XTENSA_OP_PRIVILEGED,
- .windowed_register_op = 0x1,
}, {
.name = "xsr.debugcause",
.translate = translate_xsr,
.test_ill = test_ill_xsr,
.par = (const uint32_t[]){DEBUGCAUSE},
.op_flags = XTENSA_OP_PRIVILEGED,
- .windowed_register_op = 0x1,
}, {
.name = "xsr.depc",
.translate = translate_xsr,
.test_ill = test_ill_xsr,
.par = (const uint32_t[]){DEPC},
.op_flags = XTENSA_OP_PRIVILEGED,
- .windowed_register_op = 0x1,
}, {
.name = "xsr.dtlbcfg",
.translate = translate_xsr,
.test_ill = test_ill_xsr,
.par = (const uint32_t[]){DTLBCFG},
.op_flags = XTENSA_OP_PRIVILEGED,
- .windowed_register_op = 0x1,
}, {
.name = "xsr.epc1",
.translate = translate_xsr,
.test_ill = test_ill_xsr,
.par = (const uint32_t[]){EPC1},
.op_flags = XTENSA_OP_PRIVILEGED,
- .windowed_register_op = 0x1,
}, {
.name = "xsr.epc2",
.translate = translate_xsr,
.test_ill = test_ill_xsr,
.par = (const uint32_t[]){EPC1 + 1},
.op_flags = XTENSA_OP_PRIVILEGED,
- .windowed_register_op = 0x1,
}, {
.name = "xsr.epc3",
.translate = translate_xsr,
.test_ill = test_ill_xsr,
.par = (const uint32_t[]){EPC1 + 2},
.op_flags = XTENSA_OP_PRIVILEGED,
- .windowed_register_op = 0x1,
}, {
.name = "xsr.epc4",
.translate = translate_xsr,
.test_ill = test_ill_xsr,
.par = (const uint32_t[]){EPC1 + 3},
.op_flags = XTENSA_OP_PRIVILEGED,
- .windowed_register_op = 0x1,
}, {
.name = "xsr.epc5",
.translate = translate_xsr,
.test_ill = test_ill_xsr,
.par = (const uint32_t[]){EPC1 + 4},
.op_flags = XTENSA_OP_PRIVILEGED,
- .windowed_register_op = 0x1,
}, {
.name = "xsr.epc6",
.translate = translate_xsr,
.test_ill = test_ill_xsr,
.par = (const uint32_t[]){EPC1 + 5},
.op_flags = XTENSA_OP_PRIVILEGED,
- .windowed_register_op = 0x1,
}, {
.name = "xsr.epc7",
.translate = translate_xsr,
.test_ill = test_ill_xsr,
.par = (const uint32_t[]){EPC1 + 6},
.op_flags = XTENSA_OP_PRIVILEGED,
- .windowed_register_op = 0x1,
}, {
.name = "xsr.eps2",
.translate = translate_xsr,
.test_ill = test_ill_xsr,
.par = (const uint32_t[]){EPS2},
.op_flags = XTENSA_OP_PRIVILEGED,
- .windowed_register_op = 0x1,
}, {
.name = "xsr.eps3",
.translate = translate_xsr,
.test_ill = test_ill_xsr,
.par = (const uint32_t[]){EPS2 + 1},
.op_flags = XTENSA_OP_PRIVILEGED,
- .windowed_register_op = 0x1,
}, {
.name = "xsr.eps4",
.translate = translate_xsr,
.test_ill = test_ill_xsr,
.par = (const uint32_t[]){EPS2 + 2},
.op_flags = XTENSA_OP_PRIVILEGED,
- .windowed_register_op = 0x1,
}, {
.name = "xsr.eps5",
.translate = translate_xsr,
.test_ill = test_ill_xsr,
.par = (const uint32_t[]){EPS2 + 3},
.op_flags = XTENSA_OP_PRIVILEGED,
- .windowed_register_op = 0x1,
}, {
.name = "xsr.eps6",
.translate = translate_xsr,
.test_ill = test_ill_xsr,
.par = (const uint32_t[]){EPS2 + 4},
.op_flags = XTENSA_OP_PRIVILEGED,
- .windowed_register_op = 0x1,
}, {
.name = "xsr.eps7",
.translate = translate_xsr,
.test_ill = test_ill_xsr,
.par = (const uint32_t[]){EPS2 + 5},
.op_flags = XTENSA_OP_PRIVILEGED,
- .windowed_register_op = 0x1,
}, {
.name = "xsr.exccause",
.translate = translate_xsr,
.test_ill = test_ill_xsr,
.par = (const uint32_t[]){EXCCAUSE},
.op_flags = XTENSA_OP_PRIVILEGED,
- .windowed_register_op = 0x1,
}, {
.name = "xsr.excsave1",
.translate = translate_xsr,
.test_ill = test_ill_xsr,
.par = (const uint32_t[]){EXCSAVE1},
.op_flags = XTENSA_OP_PRIVILEGED,
- .windowed_register_op = 0x1,
}, {
.name = "xsr.excsave2",
.translate = translate_xsr,
.test_ill = test_ill_xsr,
.par = (const uint32_t[]){EXCSAVE1 + 1},
.op_flags = XTENSA_OP_PRIVILEGED,
- .windowed_register_op = 0x1,
}, {
.name = "xsr.excsave3",
.translate = translate_xsr,
.test_ill = test_ill_xsr,
.par = (const uint32_t[]){EXCSAVE1 + 2},
.op_flags = XTENSA_OP_PRIVILEGED,
- .windowed_register_op = 0x1,
}, {
.name = "xsr.excsave4",
.translate = translate_xsr,
.test_ill = test_ill_xsr,
.par = (const uint32_t[]){EXCSAVE1 + 3},
.op_flags = XTENSA_OP_PRIVILEGED,
- .windowed_register_op = 0x1,
}, {
.name = "xsr.excsave5",
.translate = translate_xsr,
.test_ill = test_ill_xsr,
.par = (const uint32_t[]){EXCSAVE1 + 4},
.op_flags = XTENSA_OP_PRIVILEGED,
- .windowed_register_op = 0x1,
}, {
.name = "xsr.excsave6",
.translate = translate_xsr,
.test_ill = test_ill_xsr,
.par = (const uint32_t[]){EXCSAVE1 + 5},
.op_flags = XTENSA_OP_PRIVILEGED,
- .windowed_register_op = 0x1,
}, {
.name = "xsr.excsave7",
.translate = translate_xsr,
.test_ill = test_ill_xsr,
.par = (const uint32_t[]){EXCSAVE1 + 6},
.op_flags = XTENSA_OP_PRIVILEGED,
- .windowed_register_op = 0x1,
}, {
.name = "xsr.excvaddr",
.translate = translate_xsr,
.test_ill = test_ill_xsr,
.par = (const uint32_t[]){EXCVADDR},
.op_flags = XTENSA_OP_PRIVILEGED,
- .windowed_register_op = 0x1,
}, {
.name = "xsr.ibreaka0",
.translate = translate_xsr,
.test_ill = test_ill_xsr,
.par = (const uint32_t[]){IBREAKA},
.op_flags = XTENSA_OP_PRIVILEGED | XTENSA_OP_EXIT_TB_0,
- .windowed_register_op = 0x1,
}, {
.name = "xsr.ibreaka1",
.translate = translate_xsr,
.test_ill = test_ill_xsr,
.par = (const uint32_t[]){IBREAKA + 1},
.op_flags = XTENSA_OP_PRIVILEGED | XTENSA_OP_EXIT_TB_0,
- .windowed_register_op = 0x1,
}, {
.name = "xsr.ibreakenable",
.translate = translate_xsr,
.test_ill = test_ill_xsr,
.par = (const uint32_t[]){IBREAKENABLE},
.op_flags = XTENSA_OP_PRIVILEGED | XTENSA_OP_EXIT_TB_0,
- .windowed_register_op = 0x1,
}, {
.name = "xsr.icount",
.translate = translate_xsr,
.test_ill = test_ill_xsr,
.par = (const uint32_t[]){ICOUNT},
.op_flags = XTENSA_OP_PRIVILEGED,
- .windowed_register_op = 0x1,
}, {
.name = "xsr.icountlevel",
.translate = translate_xsr,
.test_ill = test_ill_xsr,
.par = (const uint32_t[]){ICOUNTLEVEL},
.op_flags = XTENSA_OP_PRIVILEGED | XTENSA_OP_EXIT_TB_M1,
- .windowed_register_op = 0x1,
}, {
.name = "xsr.intclear",
.translate = translate_xsr,
@@ -5109,7 +5170,6 @@
XTENSA_OP_PRIVILEGED |
XTENSA_OP_EXIT_TB_0 |
XTENSA_OP_CHECK_INTERRUPTS,
- .windowed_register_op = 0x1,
}, {
.name = "xsr.intenable",
.translate = translate_xsr,
@@ -5119,7 +5179,6 @@
XTENSA_OP_PRIVILEGED |
XTENSA_OP_EXIT_TB_0 |
XTENSA_OP_CHECK_INTERRUPTS,
- .windowed_register_op = 0x1,
}, {
.name = "xsr.interrupt",
.translate = translate_xsr,
@@ -5129,7 +5188,6 @@
XTENSA_OP_PRIVILEGED |
XTENSA_OP_EXIT_TB_0 |
XTENSA_OP_CHECK_INTERRUPTS,
- .windowed_register_op = 0x1,
}, {
.name = "xsr.intset",
.translate = translate_xsr,
@@ -5139,107 +5197,96 @@
XTENSA_OP_PRIVILEGED |
XTENSA_OP_EXIT_TB_0 |
XTENSA_OP_CHECK_INTERRUPTS,
- .windowed_register_op = 0x1,
}, {
.name = "xsr.itlbcfg",
.translate = translate_xsr,
.test_ill = test_ill_xsr,
.par = (const uint32_t[]){ITLBCFG},
.op_flags = XTENSA_OP_PRIVILEGED,
- .windowed_register_op = 0x1,
}, {
.name = "xsr.lbeg",
.translate = translate_xsr,
.test_ill = test_ill_xsr,
.par = (const uint32_t[]){LBEG},
.op_flags = XTENSA_OP_EXIT_TB_M1,
- .windowed_register_op = 0x1,
}, {
.name = "xsr.lcount",
.translate = translate_xsr,
.test_ill = test_ill_xsr,
.par = (const uint32_t[]){LCOUNT},
- .windowed_register_op = 0x1,
}, {
.name = "xsr.lend",
.translate = translate_xsr,
.test_ill = test_ill_xsr,
.par = (const uint32_t[]){LEND},
.op_flags = XTENSA_OP_EXIT_TB_M1,
- .windowed_register_op = 0x1,
}, {
.name = "xsr.litbase",
.translate = translate_xsr,
.test_ill = test_ill_xsr,
.par = (const uint32_t[]){LITBASE},
.op_flags = XTENSA_OP_EXIT_TB_M1,
- .windowed_register_op = 0x1,
}, {
.name = "xsr.m0",
.translate = translate_xsr,
.test_ill = test_ill_xsr,
.par = (const uint32_t[]){MR},
- .windowed_register_op = 0x1,
}, {
.name = "xsr.m1",
.translate = translate_xsr,
.test_ill = test_ill_xsr,
.par = (const uint32_t[]){MR + 1},
- .windowed_register_op = 0x1,
}, {
.name = "xsr.m2",
.translate = translate_xsr,
.test_ill = test_ill_xsr,
.par = (const uint32_t[]){MR + 2},
- .windowed_register_op = 0x1,
}, {
.name = "xsr.m3",
.translate = translate_xsr,
.test_ill = test_ill_xsr,
.par = (const uint32_t[]){MR + 3},
- .windowed_register_op = 0x1,
}, {
.name = "xsr.memctl",
.translate = translate_xsr,
.test_ill = test_ill_xsr,
.par = (const uint32_t[]){MEMCTL},
.op_flags = XTENSA_OP_PRIVILEGED,
- .windowed_register_op = 0x1,
}, {
.name = "xsr.misc0",
.translate = translate_xsr,
.test_ill = test_ill_xsr,
.par = (const uint32_t[]){MISC},
.op_flags = XTENSA_OP_PRIVILEGED,
- .windowed_register_op = 0x1,
}, {
.name = "xsr.misc1",
.translate = translate_xsr,
.test_ill = test_ill_xsr,
.par = (const uint32_t[]){MISC + 1},
.op_flags = XTENSA_OP_PRIVILEGED,
- .windowed_register_op = 0x1,
}, {
.name = "xsr.misc2",
.translate = translate_xsr,
.test_ill = test_ill_xsr,
.par = (const uint32_t[]){MISC + 2},
.op_flags = XTENSA_OP_PRIVILEGED,
- .windowed_register_op = 0x1,
}, {
.name = "xsr.misc3",
.translate = translate_xsr,
.test_ill = test_ill_xsr,
.par = (const uint32_t[]){MISC + 3},
.op_flags = XTENSA_OP_PRIVILEGED,
- .windowed_register_op = 0x1,
+ }, {
+ .name = "xsr.prefctl",
+ .translate = translate_xsr,
+ .test_ill = test_ill_xsr,
+ .par = (const uint32_t[]){PREFCTL},
}, {
.name = "xsr.prid",
.translate = translate_xsr,
.test_ill = test_ill_xsr,
.par = (const uint32_t[]){PRID},
.op_flags = XTENSA_OP_PRIVILEGED,
- .windowed_register_op = 0x1,
}, {
.name = "xsr.ps",
.translate = translate_xsr,
@@ -5249,54 +5296,48 @@
XTENSA_OP_PRIVILEGED |
XTENSA_OP_EXIT_TB_M1 |
XTENSA_OP_CHECK_INTERRUPTS,
- .windowed_register_op = 0x1,
}, {
.name = "xsr.ptevaddr",
.translate = translate_xsr,
.test_ill = test_ill_xsr,
.par = (const uint32_t[]){PTEVADDR},
.op_flags = XTENSA_OP_PRIVILEGED,
- .windowed_register_op = 0x1,
}, {
.name = "xsr.rasid",
.translate = translate_xsr,
.test_ill = test_ill_xsr,
.par = (const uint32_t[]){RASID},
.op_flags = XTENSA_OP_PRIVILEGED | XTENSA_OP_EXIT_TB_M1,
- .windowed_register_op = 0x1,
}, {
.name = "xsr.sar",
.translate = translate_xsr,
.test_ill = test_ill_xsr,
.par = (const uint32_t[]){SAR},
- .windowed_register_op = 0x1,
}, {
.name = "xsr.scompare1",
.translate = translate_xsr,
.test_ill = test_ill_xsr,
.par = (const uint32_t[]){SCOMPARE1},
- .windowed_register_op = 0x1,
}, {
.name = "xsr.vecbase",
.translate = translate_xsr,
.test_ill = test_ill_xsr,
.par = (const uint32_t[]){VECBASE},
.op_flags = XTENSA_OP_PRIVILEGED,
- .windowed_register_op = 0x1,
}, {
.name = "xsr.windowbase",
.translate = translate_xsr,
.test_ill = test_ill_xsr,
.par = (const uint32_t[]){WINDOW_BASE},
- .op_flags = XTENSA_OP_PRIVILEGED | XTENSA_OP_EXIT_TB_M1,
- .windowed_register_op = 0x1,
+ .op_flags = XTENSA_OP_PRIVILEGED |
+ XTENSA_OP_EXIT_TB_M1 |
+ XTENSA_OP_SYNC_REGISTER_WINDOW,
}, {
.name = "xsr.windowstart",
.translate = translate_xsr,
.test_ill = test_ill_xsr,
.par = (const uint32_t[]){WINDOW_START},
.op_flags = XTENSA_OP_PRIVILEGED | XTENSA_OP_EXIT_TB_M1,
- .windowed_register_op = 0x1,
},
};
@@ -5306,17 +5347,17 @@
};
-static void translate_abs_s(DisasContext *dc, const uint32_t arg[],
+static void translate_abs_s(DisasContext *dc, const OpcodeArg arg[],
const uint32_t par[])
{
- gen_helper_abs_s(cpu_FR[arg[0]], cpu_FR[arg[1]]);
+ gen_helper_abs_s(arg[0].out, arg[1].in);
}
-static void translate_add_s(DisasContext *dc, const uint32_t arg[],
+static void translate_add_s(DisasContext *dc, const OpcodeArg arg[],
const uint32_t par[])
{
- gen_helper_add_s(cpu_FR[arg[0]], cpu_env,
- cpu_FR[arg[1]], cpu_FR[arg[2]]);
+ gen_helper_add_s(arg[0].out, cpu_env,
+ arg[1].in, arg[2].in);
}
enum {
@@ -5329,7 +5370,7 @@
COMPARE_ULE,
};
-static void translate_compare_s(DisasContext *dc, const uint32_t arg[],
+static void translate_compare_s(DisasContext *dc, const OpcodeArg arg[],
const uint32_t par[])
{
static void (* const helper[])(TCGv_env env, TCGv_i32 bit,
@@ -5342,153 +5383,153 @@
[COMPARE_OLE] = gen_helper_ole_s,
[COMPARE_ULE] = gen_helper_ule_s,
};
- TCGv_i32 bit = tcg_const_i32(1 << arg[0]);
+ TCGv_i32 bit = tcg_const_i32(1 << arg[0].imm);
- helper[par[0]](cpu_env, bit, cpu_FR[arg[1]], cpu_FR[arg[2]]);
+ helper[par[0]](cpu_env, bit, arg[1].in, arg[2].in);
tcg_temp_free(bit);
}
-static void translate_float_s(DisasContext *dc, const uint32_t arg[],
+static void translate_float_s(DisasContext *dc, const OpcodeArg arg[],
const uint32_t par[])
{
- TCGv_i32 scale = tcg_const_i32(-arg[2]);
+ TCGv_i32 scale = tcg_const_i32(-arg[2].imm);
if (par[0]) {
- gen_helper_uitof(cpu_FR[arg[0]], cpu_env, cpu_R[arg[1]], scale);
+ gen_helper_uitof(arg[0].out, cpu_env, arg[1].in, scale);
} else {
- gen_helper_itof(cpu_FR[arg[0]], cpu_env, cpu_R[arg[1]], scale);
+ gen_helper_itof(arg[0].out, cpu_env, arg[1].in, scale);
}
tcg_temp_free(scale);
}
-static void translate_ftoi_s(DisasContext *dc, const uint32_t arg[],
+static void translate_ftoi_s(DisasContext *dc, const OpcodeArg arg[],
const uint32_t par[])
{
TCGv_i32 rounding_mode = tcg_const_i32(par[0]);
- TCGv_i32 scale = tcg_const_i32(arg[2]);
+ TCGv_i32 scale = tcg_const_i32(arg[2].imm);
if (par[1]) {
- gen_helper_ftoui(cpu_R[arg[0]], cpu_FR[arg[1]],
+ gen_helper_ftoui(arg[0].out, arg[1].in,
rounding_mode, scale);
} else {
- gen_helper_ftoi(cpu_R[arg[0]], cpu_FR[arg[1]],
+ gen_helper_ftoi(arg[0].out, arg[1].in,
rounding_mode, scale);
}
tcg_temp_free(rounding_mode);
tcg_temp_free(scale);
}
-static void translate_ldsti(DisasContext *dc, const uint32_t arg[],
+static void translate_ldsti(DisasContext *dc, const OpcodeArg arg[],
const uint32_t par[])
{
TCGv_i32 addr = tcg_temp_new_i32();
- tcg_gen_addi_i32(addr, cpu_R[arg[1]], arg[2]);
+ tcg_gen_addi_i32(addr, arg[1].in, arg[2].imm);
gen_load_store_alignment(dc, 2, addr, false);
if (par[0]) {
- tcg_gen_qemu_st32(cpu_FR[arg[0]], addr, dc->cring);
+ tcg_gen_qemu_st32(arg[0].in, addr, dc->cring);
} else {
- tcg_gen_qemu_ld32u(cpu_FR[arg[0]], addr, dc->cring);
+ tcg_gen_qemu_ld32u(arg[0].out, addr, dc->cring);
}
if (par[1]) {
- tcg_gen_mov_i32(cpu_R[arg[1]], addr);
+ tcg_gen_mov_i32(arg[1].out, addr);
}
tcg_temp_free(addr);
}
-static void translate_ldstx(DisasContext *dc, const uint32_t arg[],
+static void translate_ldstx(DisasContext *dc, const OpcodeArg arg[],
const uint32_t par[])
{
TCGv_i32 addr = tcg_temp_new_i32();
- tcg_gen_add_i32(addr, cpu_R[arg[1]], cpu_R[arg[2]]);
+ tcg_gen_add_i32(addr, arg[1].in, arg[2].in);
gen_load_store_alignment(dc, 2, addr, false);
if (par[0]) {
- tcg_gen_qemu_st32(cpu_FR[arg[0]], addr, dc->cring);
+ tcg_gen_qemu_st32(arg[0].in, addr, dc->cring);
} else {
- tcg_gen_qemu_ld32u(cpu_FR[arg[0]], addr, dc->cring);
+ tcg_gen_qemu_ld32u(arg[0].out, addr, dc->cring);
}
if (par[1]) {
- tcg_gen_mov_i32(cpu_R[arg[1]], addr);
+ tcg_gen_mov_i32(arg[1].out, addr);
}
tcg_temp_free(addr);
}
-static void translate_madd_s(DisasContext *dc, const uint32_t arg[],
+static void translate_madd_s(DisasContext *dc, const OpcodeArg arg[],
const uint32_t par[])
{
- gen_helper_madd_s(cpu_FR[arg[0]], cpu_env,
- cpu_FR[arg[0]], cpu_FR[arg[1]], cpu_FR[arg[2]]);
+ gen_helper_madd_s(arg[0].out, cpu_env,
+ arg[0].in, arg[1].in, arg[2].in);
}
-static void translate_mov_s(DisasContext *dc, const uint32_t arg[],
+static void translate_mov_s(DisasContext *dc, const OpcodeArg arg[],
const uint32_t par[])
{
- tcg_gen_mov_i32(cpu_FR[arg[0]], cpu_FR[arg[1]]);
+ tcg_gen_mov_i32(arg[0].out, arg[1].in);
}
-static void translate_movcond_s(DisasContext *dc, const uint32_t arg[],
+static void translate_movcond_s(DisasContext *dc, const OpcodeArg arg[],
const uint32_t par[])
{
TCGv_i32 zero = tcg_const_i32(0);
- tcg_gen_movcond_i32(par[0], cpu_FR[arg[0]],
- cpu_R[arg[2]], zero,
- cpu_FR[arg[1]], cpu_FR[arg[0]]);
+ tcg_gen_movcond_i32(par[0], arg[0].out,
+ arg[2].in, zero,
+ arg[1].in, arg[0].in);
tcg_temp_free(zero);
}
-static void translate_movp_s(DisasContext *dc, const uint32_t arg[],
+static void translate_movp_s(DisasContext *dc, const OpcodeArg arg[],
const uint32_t par[])
{
TCGv_i32 zero = tcg_const_i32(0);
TCGv_i32 tmp = tcg_temp_new_i32();
- tcg_gen_andi_i32(tmp, cpu_SR[BR], 1 << arg[2]);
+ tcg_gen_andi_i32(tmp, arg[2].in, 1 << arg[2].imm);
tcg_gen_movcond_i32(par[0],
- cpu_FR[arg[0]], tmp, zero,
- cpu_FR[arg[1]], cpu_FR[arg[0]]);
+ arg[0].out, tmp, zero,
+ arg[1].in, arg[0].in);
tcg_temp_free(tmp);
tcg_temp_free(zero);
}
-static void translate_mul_s(DisasContext *dc, const uint32_t arg[],
+static void translate_mul_s(DisasContext *dc, const OpcodeArg arg[],
const uint32_t par[])
{
- gen_helper_mul_s(cpu_FR[arg[0]], cpu_env,
- cpu_FR[arg[1]], cpu_FR[arg[2]]);
+ gen_helper_mul_s(arg[0].out, cpu_env,
+ arg[1].in, arg[2].in);
}
-static void translate_msub_s(DisasContext *dc, const uint32_t arg[],
+static void translate_msub_s(DisasContext *dc, const OpcodeArg arg[],
const uint32_t par[])
{
- gen_helper_msub_s(cpu_FR[arg[0]], cpu_env,
- cpu_FR[arg[0]], cpu_FR[arg[1]], cpu_FR[arg[2]]);
+ gen_helper_msub_s(arg[0].out, cpu_env,
+ arg[0].in, arg[1].in, arg[2].in);
}
-static void translate_neg_s(DisasContext *dc, const uint32_t arg[],
+static void translate_neg_s(DisasContext *dc, const OpcodeArg arg[],
const uint32_t par[])
{
- gen_helper_neg_s(cpu_FR[arg[0]], cpu_FR[arg[1]]);
+ gen_helper_neg_s(arg[0].out, arg[1].in);
}
-static void translate_rfr_s(DisasContext *dc, const uint32_t arg[],
+static void translate_rfr_s(DisasContext *dc, const OpcodeArg arg[],
const uint32_t par[])
{
- tcg_gen_mov_i32(cpu_R[arg[0]], cpu_FR[arg[1]]);
+ tcg_gen_mov_i32(arg[0].out, arg[1].in);
}
-static void translate_sub_s(DisasContext *dc, const uint32_t arg[],
+static void translate_sub_s(DisasContext *dc, const OpcodeArg arg[],
const uint32_t par[])
{
- gen_helper_sub_s(cpu_FR[arg[0]], cpu_env,
- cpu_FR[arg[1]], cpu_FR[arg[2]]);
+ gen_helper_sub_s(arg[0].out, cpu_env,
+ arg[1].in, arg[2].in);
}
-static void translate_wfr_s(DisasContext *dc, const uint32_t arg[],
+static void translate_wfr_s(DisasContext *dc, const OpcodeArg arg[],
const uint32_t par[])
{
- tcg_gen_mov_i32(cpu_FR[arg[0]], cpu_R[arg[1]]);
+ tcg_gen_mov_i32(arg[0].out, arg[1].in);
}
static const XtensaOpcodeOps fpu2000_ops[] = {
@@ -5504,43 +5545,40 @@
.name = "ceil.s",
.translate = translate_ftoi_s,
.par = (const uint32_t[]){float_round_up, false},
- .windowed_register_op = 0x1,
.coprocessor = 0x1,
}, {
.name = "float.s",
.translate = translate_float_s,
.par = (const uint32_t[]){false},
- .windowed_register_op = 0x2,
.coprocessor = 0x1,
}, {
.name = "floor.s",
.translate = translate_ftoi_s,
.par = (const uint32_t[]){float_round_down, false},
- .windowed_register_op = 0x1,
.coprocessor = 0x1,
}, {
.name = "lsi",
.translate = translate_ldsti,
.par = (const uint32_t[]){false, false},
- .windowed_register_op = 0x2,
+ .op_flags = XTENSA_OP_LOAD,
.coprocessor = 0x1,
}, {
.name = "lsiu",
.translate = translate_ldsti,
.par = (const uint32_t[]){false, true},
- .windowed_register_op = 0x2,
+ .op_flags = XTENSA_OP_LOAD,
.coprocessor = 0x1,
}, {
.name = "lsx",
.translate = translate_ldstx,
.par = (const uint32_t[]){false, false},
- .windowed_register_op = 0x6,
+ .op_flags = XTENSA_OP_LOAD,
.coprocessor = 0x1,
}, {
.name = "lsxu",
.translate = translate_ldstx,
.par = (const uint32_t[]){false, true},
- .windowed_register_op = 0x6,
+ .op_flags = XTENSA_OP_LOAD,
.coprocessor = 0x1,
}, {
.name = "madd.s",
@@ -5554,7 +5592,6 @@
.name = "moveqz.s",
.translate = translate_movcond_s,
.par = (const uint32_t[]){TCG_COND_EQ},
- .windowed_register_op = 0x4,
.coprocessor = 0x1,
}, {
.name = "movf.s",
@@ -5565,19 +5602,16 @@
.name = "movgez.s",
.translate = translate_movcond_s,
.par = (const uint32_t[]){TCG_COND_GE},
- .windowed_register_op = 0x4,
.coprocessor = 0x1,
}, {
.name = "movltz.s",
.translate = translate_movcond_s,
.par = (const uint32_t[]){TCG_COND_LT},
- .windowed_register_op = 0x4,
.coprocessor = 0x1,
}, {
.name = "movnez.s",
.translate = translate_movcond_s,
.par = (const uint32_t[]){TCG_COND_NE},
- .windowed_register_op = 0x4,
.coprocessor = 0x1,
}, {
.name = "movt.s",
@@ -5614,37 +5648,35 @@
}, {
.name = "rfr",
.translate = translate_rfr_s,
- .windowed_register_op = 0x1,
.coprocessor = 0x1,
}, {
.name = "round.s",
.translate = translate_ftoi_s,
.par = (const uint32_t[]){float_round_nearest_even, false},
- .windowed_register_op = 0x1,
.coprocessor = 0x1,
}, {
.name = "ssi",
.translate = translate_ldsti,
.par = (const uint32_t[]){true, false},
- .windowed_register_op = 0x2,
+ .op_flags = XTENSA_OP_STORE,
.coprocessor = 0x1,
}, {
.name = "ssiu",
.translate = translate_ldsti,
.par = (const uint32_t[]){true, true},
- .windowed_register_op = 0x2,
+ .op_flags = XTENSA_OP_STORE,
.coprocessor = 0x1,
}, {
.name = "ssx",
.translate = translate_ldstx,
.par = (const uint32_t[]){true, false},
- .windowed_register_op = 0x6,
+ .op_flags = XTENSA_OP_STORE,
.coprocessor = 0x1,
}, {
.name = "ssxu",
.translate = translate_ldstx,
.par = (const uint32_t[]){true, true},
- .windowed_register_op = 0x6,
+ .op_flags = XTENSA_OP_STORE,
.coprocessor = 0x1,
}, {
.name = "sub.s",
@@ -5654,7 +5686,6 @@
.name = "trunc.s",
.translate = translate_ftoi_s,
.par = (const uint32_t[]){float_round_to_zero, false},
- .windowed_register_op = 0x1,
.coprocessor = 0x1,
}, {
.name = "ueq.s",
@@ -5665,7 +5696,6 @@
.name = "ufloat.s",
.translate = translate_float_s,
.par = (const uint32_t[]){true},
- .windowed_register_op = 0x2,
.coprocessor = 0x1,
}, {
.name = "ule.s",
@@ -5686,12 +5716,10 @@
.name = "utrunc.s",
.translate = translate_ftoi_s,
.par = (const uint32_t[]){float_round_to_zero, true},
- .windowed_register_op = 0x1,
.coprocessor = 0x1,
}, {
.name = "wfr",
.translate = translate_wfr_s,
- .windowed_register_op = 0x2,
.coprocessor = 0x1,
},
};
diff --git a/target/xtensa/win_helper.c b/target/xtensa/win_helper.c
index 7d793d4..f6f96a6 100644
--- a/target/xtensa/win_helper.c
+++ b/target/xtensa/win_helper.c
@@ -96,9 +96,9 @@
xtensa_rotate_window_abs(env, env->sregs[WINDOW_BASE] + delta);
}
-void HELPER(wsr_windowbase)(CPUXtensaState *env, uint32_t v)
+void HELPER(sync_windowbase)(CPUXtensaState *env)
{
- xtensa_rotate_window_abs(env, v);
+ xtensa_rotate_window_abs(env, env->windowbase_next);
}
void HELPER(entry)(CPUXtensaState *env, uint32_t pc, uint32_t s, uint32_t imm)
@@ -106,9 +106,8 @@
int callinc = (env->sregs[PS] & PS_CALLINC) >> PS_CALLINC_SHIFT;
env->regs[(callinc << 2) | (s & 3)] = env->regs[s] - imm;
- xtensa_rotate_window(env, callinc);
- env->sregs[WINDOW_START] |=
- windowstart_bit(env->sregs[WINDOW_BASE], env);
+ env->windowbase_next = env->sregs[WINDOW_BASE] + callinc;
+ env->sregs[WINDOW_START] |= windowstart_bit(env->windowbase_next, env);
}
void HELPER(window_check)(CPUXtensaState *env, uint32_t pc, uint32_t w)
@@ -185,20 +184,11 @@
}
}
-uint32_t HELPER(retw)(CPUXtensaState *env, uint32_t pc)
+void HELPER(retw)(CPUXtensaState *env, uint32_t a0)
{
- int n = (env->regs[0] >> 30) & 0x3;
- uint32_t windowbase = windowbase_bound(env->sregs[WINDOW_BASE], env);
- uint32_t ret_pc = (pc & 0xc0000000) | (env->regs[0] & 0x3fffffff);
+ int n = (a0 >> 30) & 0x3;
xtensa_rotate_window(env, -n);
- env->sregs[WINDOW_START] &= ~windowstart_bit(windowbase, env);
- return ret_pc;
-}
-
-void HELPER(rotw)(CPUXtensaState *env, uint32_t imm4)
-{
- xtensa_rotate_window(env, imm4);
}
void xtensa_restore_owb(CPUXtensaState *env)
diff --git a/tests/.gitignore b/tests/.gitignore
index 72c18aa..c88f8f2 100644
--- a/tests/.gitignore
+++ b/tests/.gitignore
@@ -5,15 +5,24 @@
check-*
!check-*.c
!check-*.sh
+fp/*.out
qht-bench
rcutorture
test-*
!test-*.c
!docker/test-*
test-qapi-commands.[ch]
+include/test-qapi-commands-sub-module.[ch]
+test-qapi-commands-sub-sub-module.[ch]
test-qapi-events.[ch]
+include/test-qapi-events-sub-module.[ch]
+test-qapi-events-sub-sub-module.[ch]
test-qapi-types.[ch]
+include/test-qapi-types-sub-module.[ch]
+test-qapi-types-sub-sub-module.[ch]
test-qapi-visit.[ch]
+include/test-qapi-visit-sub-module.[ch]
+test-qapi-visit-sub-sub-module.[ch]
test-qapi-introspect.[ch]
*-test
qapi-schema/*.test.*
diff --git a/tests/Makefile.include b/tests/Makefile.include
index b39e989..97e1cb9 100644
--- a/tests/Makefile.include
+++ b/tests/Makefile.include
@@ -70,6 +70,7 @@
check-unit-y += tests/test-thread-pool$(EXESUF)
check-unit-y += tests/test-hbitmap$(EXESUF)
check-unit-y += tests/test-bdrv-drain$(EXESUF)
+check-unit-y += tests/test-bdrv-graph-mod$(EXESUF)
check-unit-y += tests/test-blockjob$(EXESUF)
check-unit-y += tests/test-blockjob-txn$(EXESUF)
check-unit-y += tests/test-block-backend$(EXESUF)
@@ -111,10 +112,15 @@
check-unit-$(CONFIG_GNUTLS) += tests/test-crypto-tlscredsx509$(EXESUF)
check-unit-$(CONFIG_GNUTLS) += tests/test-crypto-tlssession$(EXESUF)
ifneq (,$(findstring qemu-ga,$(TOOLS)))
-check-unit-$(land,$(CONFIG_LINUX),$(CONFIG_VIRTIO_SERIAL)) += tests/test-qga$(EXESUF)
+check-unit-$(call land,$(CONFIG_LINUX),$(CONFIG_VIRTIO_SERIAL)) += tests/test-qga$(EXESUF)
endif
check-unit-y += tests/test-timed-average$(EXESUF)
+check-unit-$(CONFIG_INOTIFY1) += tests/test-util-filemonitor$(EXESUF)
check-unit-y += tests/test-util-sockets$(EXESUF)
+check-unit-y += tests/test-authz-simple$(EXESUF)
+check-unit-y += tests/test-authz-list$(EXESUF)
+check-unit-y += tests/test-authz-listfile$(EXESUF)
+check-unit-$(CONFIG_AUTH_PAM) += tests/test-authz-pam$(EXESUF)
check-unit-y += tests/test-io-task$(EXESUF)
check-unit-y += tests/test-io-channel-socket$(EXESUF)
check-unit-y += tests/test-io-channel-file$(EXESUF)
@@ -192,6 +198,7 @@
# check-qtest-i386-$(CONFIG_ISA_IPMI_BT) += tests/ipmi-bt-test$(EXESUF)
check-qtest-i386-y += tests/i440fx-test$(EXESUF)
check-qtest-i386-y += tests/fw_cfg-test$(EXESUF)
+check-qtest-i386-y += tests/device-plug-test$(EXESUF)
check-qtest-i386-y += tests/drive_del-test$(EXESUF)
check-qtest-i386-$(CONFIG_WDT_IB700) += tests/wdt_ib700-test$(EXESUF)
check-qtest-i386-y += tests/tco-test$(EXESUF)
@@ -209,10 +216,7 @@
check-qtest-i386-y += tests/cpu-plug-test$(EXESUF)
check-qtest-i386-y += tests/q35-test$(EXESUF)
check-qtest-i386-y += tests/vmgenid-test$(EXESUF)
-check-qtest-i386-$(CONFIG_VHOST_USER_NET_TEST_i386) += tests/vhost-user-test$(EXESUF)
-ifeq ($(CONFIG_VHOST_USER_NET_TEST_i386),)
-check-qtest-x86_64-$(CONFIG_VHOST_USER_NET_TEST_x86_64) += tests/vhost-user-test$(EXESUF)
-endif
+check-qtest-i386-$(CONFIG_VHOST_NET_USER) += tests/vhost-user-test$(EXESUF)
check-qtest-i386-$(CONFIG_TPM_CRB) += tests/tpm-crb-swtpm-test$(EXESUF)
check-qtest-i386-$(CONFIG_TPM_CRB) += tests/tpm-crb-test$(EXESUF)
check-qtest-i386-$(CONFIG_TPM_TIS) += tests/tpm-tis-swtpm-test$(EXESUF)
@@ -221,6 +225,7 @@
check-qtest-i386-$(CONFIG_POSIX) += tests/test-filter-mirror$(EXESUF)
check-qtest-i386-$(CONFIG_RTL8139_PCI) += tests/test-filter-redirector$(EXESUF)
check-qtest-i386-y += tests/migration-test$(EXESUF)
+check-qtest-i386-y += tests/test-announce-self$(EXESUF)
check-qtest-i386-y += tests/test-x86-cpuid-compat$(EXESUF)
check-qtest-i386-y += tests/numa-test$(EXESUF)
check-qtest-x86_64-y += $(check-qtest-i386-y)
@@ -256,8 +261,10 @@
check-qtest-ppc64-y += $(check-qtest-ppc-y)
check-qtest-ppc64-$(CONFIG_PSERIES) += tests/spapr-phb-test$(EXESUF)
+check-qtest-ppc64-$(CONFIG_PSERIES) += tests/device-plug-test$(EXESUF)
check-qtest-ppc64-$(CONFIG_POWERNV) += tests/pnv-xscom-test$(EXESUF)
check-qtest-ppc64-y += tests/migration-test$(EXESUF)
+check-qtest-ppc64-y += tests/test-announce-self$(EXESUF)
check-qtest-ppc64-$(CONFIG_PSERIES) += tests/rtas-test$(EXESUF)
check-qtest-ppc64-$(CONFIG_SLIRP) += tests/pxe-test$(EXESUF)
check-qtest-ppc64-$(CONFIG_USB_OHCI) += tests/usb-hcd-ohci-test$(EXESUF)
@@ -310,6 +317,7 @@
check-qtest-s390x-$(CONFIG_POSIX) += tests/test-filter-mirror$(EXESUF)
check-qtest-s390x-$(CONFIG_POSIX) += tests/test-filter-redirector$(EXESUF)
check-qtest-s390x-y += tests/drive_del-test$(EXESUF)
+check-qtest-s390x-y += tests/device-plug-test$(EXESUF)
check-qtest-s390x-y += tests/virtio-ccw-test$(EXESUF)
check-qtest-s390x-y += tests/cpu-plug-test$(EXESUF)
check-qtest-s390x-y += tests/migration-test$(EXESUF)
@@ -433,7 +441,6 @@
qapi-schema += include-nested-err.json
qapi-schema += include-no-file.json
qapi-schema += include-non-file.json
-qapi-schema += include-relpath.json
qapi-schema += include-repetition.json
qapi-schema += include-self-cycle.json
qapi-schema += include-simple.json
@@ -500,8 +507,18 @@
check-qapi-schema-y := $(addprefix tests/qapi-schema/, $(qapi-schema))
-GENERATED_FILES += tests/test-qapi-types.h tests/test-qapi-visit.h \
- tests/test-qapi-commands.h tests/test-qapi-events.h \
+GENERATED_FILES += tests/test-qapi-types.h \
+ tests/include/test-qapi-types-sub-module.h \
+ tests/test-qapi-types-sub-sub-module.h \
+ tests/test-qapi-visit.h \
+ tests/include/test-qapi-visit-sub-module.h \
+ tests/test-qapi-visit-sub-sub-module.h \
+ tests/test-qapi-commands.h \
+ tests/include/test-qapi-commands-sub-module.h \
+ tests/test-qapi-commands-sub-sub-module.h \
+ tests/test-qapi-events.h \
+ tests/include/test-qapi-events-sub-module.h \
+ tests/test-qapi-events-sub-sub-module.h \
tests/test-qapi-introspect.h
test-obj-y = tests/check-qnum.o tests/check-qstring.o tests/check-qdict.o \
@@ -529,12 +546,18 @@
# Deps that are common to various different sets of tests below
test-util-obj-y = libqemuutil.a
test-qom-obj-y = $(qom-obj-y) $(test-util-obj-y)
-test-qapi-obj-y = tests/test-qapi-visit.o tests/test-qapi-types.o \
+test-qapi-obj-y = tests/test-qapi-types.o \
+ tests/include/test-qapi-types-sub-module.o \
+ tests/test-qapi-types-sub-sub-module.o \
+ tests/test-qapi-visit.o \
+ tests/include/test-qapi-visit-sub-module.o \
+ tests/test-qapi-visit-sub-sub-module.o \
tests/test-qapi-introspect.o \
$(test-qom-obj-y)
-benchmark-crypto-obj-y = $(crypto-obj-y) $(test-qom-obj-y)
-test-crypto-obj-y = $(crypto-obj-y) $(test-qom-obj-y)
+benchmark-crypto-obj-y = $(authz-obj-y) $(crypto-obj-y) $(test-qom-obj-y)
+test-crypto-obj-y = $(authz-obj-y) $(crypto-obj-y) $(test-qom-obj-y)
test-io-obj-y = $(io-obj-y) $(test-crypto-obj-y)
+test-authz-obj-y = $(test-qom-obj-y) $(authz-obj-y)
test-block-obj-y = $(block-obj-y) $(test-io-obj-y) tests/iothread.o
tests/check-qnum$(EXESUF): tests/check-qnum.o $(test-util-obj-y)
@@ -555,6 +578,7 @@
tests/test-aio-multithread$(EXESUF): tests/test-aio-multithread.o $(test-block-obj-y)
tests/test-throttle$(EXESUF): tests/test-throttle.o $(test-block-obj-y)
tests/test-bdrv-drain$(EXESUF): tests/test-bdrv-drain.o $(test-block-obj-y) $(test-util-obj-y)
+tests/test-bdrv-graph-mod$(EXESUF): tests/test-bdrv-graph-mod.o $(test-block-obj-y) $(test-util-obj-y)
tests/test-blockjob$(EXESUF): tests/test-blockjob.o $(test-block-obj-y) $(test-util-obj-y)
tests/test-blockjob-txn$(EXESUF): tests/test-blockjob-txn.o $(test-block-obj-y) $(test-util-obj-y)
tests/test-block-backend$(EXESUF): tests/test-block-backend.o $(test-block-obj-y) $(test-util-obj-y)
@@ -603,12 +627,32 @@
$(test-block-obj-y)
tests/test-qapi-types.c tests/test-qapi-types.h \
+tests/include/test-qapi-types-sub-module.c \
+tests/include/test-qapi-types-sub-module.h \
+tests/test-qapi-types-sub-sub-module.c \
+tests/test-qapi-types-sub-sub-module.h \
tests/test-qapi-visit.c tests/test-qapi-visit.h \
+tests/include/test-qapi-visit-sub-module.c \
+tests/include/test-qapi-visit-sub-module.h \
+tests/test-qapi-visit-sub-sub-module.c \
+tests/test-qapi-visit-sub-sub-module.h \
tests/test-qapi-commands.h tests/test-qapi-commands.c \
+tests/include/test-qapi-commands-sub-module.h \
+tests/include/test-qapi-commands-sub-module.c \
+tests/test-qapi-commands-sub-sub-module.h \
+tests/test-qapi-commands-sub-sub-module.c \
tests/test-qapi-events.c tests/test-qapi-events.h \
+tests/include/test-qapi-events-sub-module.c \
+tests/include/test-qapi-events-sub-module.h \
+tests/test-qapi-events-sub-sub-module.c \
+tests/test-qapi-events-sub-sub-module.h \
tests/test-qapi-introspect.c tests/test-qapi-introspect.h: \
tests/test-qapi-gen-timestamp ;
-tests/test-qapi-gen-timestamp: $(SRC_PATH)/tests/qapi-schema/qapi-schema-test.json $(qapi-py)
+tests/test-qapi-gen-timestamp: \
+ $(SRC_PATH)/tests/qapi-schema/qapi-schema-test.json \
+ $(SRC_PATH)/tests/qapi-schema/include/sub-module.json \
+ $(SRC_PATH)/tests/qapi-schema/sub-sub-module.json \
+ $(qapi-py)
$(call quiet-command,$(PYTHON) $(SRC_PATH)/scripts/qapi-gen.py \
-o tests -p "test-" $<, \
"GEN","$(@:%-timestamp=%)")
@@ -657,8 +701,14 @@
tests/crypto-tls-x509-helpers.o tests/pkix_asn1_tab.o \
tests/crypto-tls-psk-helpers.o \
$(test-crypto-obj-y)
+tests/test-util-filemonitor$(EXESUF): tests/test-util-filemonitor.o \
+ $(test-util-obj-y)
tests/test-util-sockets$(EXESUF): tests/test-util-sockets.o \
tests/socket-helpers.o $(test-util-obj-y)
+tests/test-authz-simple$(EXESUF): tests/test-authz-simple.o $(test-authz-obj-y)
+tests/test-authz-list$(EXESUF): tests/test-authz-list.o $(test-authz-obj-y)
+tests/test-authz-listfile$(EXESUF): tests/test-authz-listfile.o $(test-authz-obj-y)
+tests/test-authz-pam$(EXESUF): tests/test-authz-pam.o $(test-authz-obj-y)
tests/test-io-task$(EXESUF): tests/test-io-task.o $(test-io-obj-y)
tests/test-io-channel-socket$(EXESUF): tests/test-io-channel-socket.o \
tests/io-channel-helpers.o tests/socket-helpers.o $(test-io-obj-y)
@@ -750,6 +800,7 @@
tests/qom-test$(EXESUF): tests/qom-test.o
tests/test-hmp$(EXESUF): tests/test-hmp.o
tests/machine-none-test$(EXESUF): tests/machine-none-test.o
+tests/device-plug-test$(EXESUF): tests/device-plug-test.o
tests/drive_del-test$(EXESUF): tests/drive_del-test.o $(libqos-virtio-obj-y)
tests/nvme-test$(EXESUF): tests/nvme-test.o $(libqos-pc-obj-y)
tests/pvpanic-test$(EXESUF): tests/pvpanic-test.o
@@ -764,6 +815,7 @@
tests/usb-hcd-xhci-test$(EXESUF): tests/usb-hcd-xhci-test.o $(libqos-usb-obj-y)
tests/cpu-plug-test$(EXESUF): tests/cpu-plug-test.o
tests/migration-test$(EXESUF): tests/migration-test.o
+tests/test-announce-self$(EXESUF): tests/test-announce-self.o
tests/vhost-user-test$(EXESUF): tests/vhost-user-test.o $(test-util-obj-y) \
$(qtest-obj-y) $(test-io-obj-y) $(libqos-virtio-obj-y) $(libqos-pc-obj-y) \
$(chardev-obj-y)
@@ -896,23 +948,20 @@
"BUILD", "$(notdir $@)")
# The full test suite can take a bit of time, default to a quick run
-ifeq ($(SPEED), quick)
-FP_TL=-l 1
-else
-FP_TL=-l 2 -r all
-endif
+# "-l 2 -r all" can take more than a day for some operations and is best
+# run manually
+FP_TL=-l 1 -r all
-# $1 = tests, $2 = description
+# $1 = tests, $2 = description, $3 = test flags
test-softfloat = $(call quiet-command, \
cd $(BUILD_DIR)/tests/fp && \
- ./fp-test -s $(FP_TL) $1 > $2.out 2>&1 || \
+ ./fp-test -s $(if $3,$3,$(FP_TL)) $1 > $2.out 2>&1 || \
(cat $2.out && exit 1;), \
"FLOAT TEST", $2)
# Conversion Routines:
# FIXME: i32_to_extF80 (broken), i64_to_extF80 (broken)
-# ui32_to_f128 (not implemented), f128_to_ui32 (not implemented)
-# extF80_roundToInt (broken)
+# ui32_to_f128 (not implemented), extF80_roundToInt (broken)
#
check-softfloat-conv: $(FP_TEST_BIN)
$(call test-softfloat, \
@@ -941,9 +990,11 @@
f16_to_ui32 f16_to_ui32_r_minMag \
f32_to_ui32 f32_to_ui32_r_minMag \
f64_to_ui32 f64_to_ui32_r_minMag \
+ f128_to_ui32 f128_to_ui32_r_minMag \
f16_to_ui64 f16_to_ui64_r_minMag \
f32_to_ui64 f32_to_ui64_r_minMag \
- f64_to_ui64 f64_to_ui64_r_minMag, \
+ f64_to_ui64 f64_to_ui64_r_minMag \
+ f128_to_ui64 f128_to_ui64_r_minMag, \
float-to-uint)
$(call test-softfloat, \
f16_roundToInt f32_roundToInt \
@@ -985,7 +1036,7 @@
check-softfloat-mulAdd: $(FP_TEST_BIN)
$(call test-softfloat, \
f16_mulAdd f32_mulAdd f64_mulAdd f128_mulAdd, \
- mulAdd)
+ mulAdd,-l 1)
# FIXME: extF80_rem (broken)
check-softfloat-rem: $(FP_TEST_BIN)
diff --git a/tests/cdrom-test.c b/tests/cdrom-test.c
index 14bd981..05611da 100644
--- a/tests/cdrom-test.c
+++ b/tests/cdrom-test.c
@@ -132,8 +132,14 @@
qtest_add_data_func("cdrom/boot/virtio-scsi",
"-device virtio-scsi -device scsi-cd,drive=cdr "
"-blockdev file,node-name=cdr,filename=", test_cdboot);
- qtest_add_data_func("cdrom/boot/isapc", "-M isapc "
- "-drive if=ide,media=cdrom,file=", test_cdboot);
+ /*
+ * Unstable CI test under load
+ * See https://lists.gnu.org/archive/html/qemu-devel/2019-02/msg05509.html
+ */
+ if (g_test_slow()) {
+ qtest_add_data_func("cdrom/boot/isapc", "-M isapc "
+ "-drive if=ide,media=cdrom,file=", test_cdboot);
+ }
qtest_add_data_func("cdrom/boot/am53c974",
"-device am53c974 -device scsi-cd,drive=cd1 "
"-drive if=none,id=cd1,format=raw,file=", test_cdboot);
diff --git a/tests/data/uefi-boot-images/bios-tables-test.aarch64.iso.qcow2 b/tests/data/uefi-boot-images/bios-tables-test.aarch64.iso.qcow2
new file mode 100644
index 0000000..ac0b7b1
--- /dev/null
+++ b/tests/data/uefi-boot-images/bios-tables-test.aarch64.iso.qcow2
Binary files differ
diff --git a/tests/data/uefi-boot-images/bios-tables-test.arm.iso.qcow2 b/tests/data/uefi-boot-images/bios-tables-test.arm.iso.qcow2
new file mode 100644
index 0000000..d20fa7c
--- /dev/null
+++ b/tests/data/uefi-boot-images/bios-tables-test.arm.iso.qcow2
Binary files differ
diff --git a/tests/data/uefi-boot-images/bios-tables-test.i386.iso.qcow2 b/tests/data/uefi-boot-images/bios-tables-test.i386.iso.qcow2
new file mode 100644
index 0000000..26c882b
--- /dev/null
+++ b/tests/data/uefi-boot-images/bios-tables-test.i386.iso.qcow2
Binary files differ
diff --git a/tests/data/uefi-boot-images/bios-tables-test.x86_64.iso.qcow2 b/tests/data/uefi-boot-images/bios-tables-test.x86_64.iso.qcow2
new file mode 100644
index 0000000..9ec3c1f
--- /dev/null
+++ b/tests/data/uefi-boot-images/bios-tables-test.x86_64.iso.qcow2
Binary files differ
diff --git a/tests/device-plug-test.c b/tests/device-plug-test.c
new file mode 100644
index 0000000..318e422
--- /dev/null
+++ b/tests/device-plug-test.c
@@ -0,0 +1,178 @@
+/*
+ * QEMU device plug/unplug handling
+ *
+ * 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 "libqtest.h"
+#include "qapi/qmp/qdict.h"
+#include "qapi/qmp/qstring.h"
+
+static void device_del_start(QTestState *qtest, const char *id)
+{
+ qtest_qmp_send(qtest,
+ "{'execute': 'device_del', 'arguments': { 'id': %s } }", id);
+}
+
+static void device_del_finish(QTestState *qtest)
+{
+ QDict *resp = qtest_qmp_receive(qtest);
+
+ g_assert(qdict_haskey(resp, "return"));
+ qobject_unref(resp);
+}
+
+static void device_del_request(QTestState *qtest, const char *id)
+{
+ device_del_start(qtest, id);
+ device_del_finish(qtest);
+}
+
+static void system_reset(QTestState *qtest)
+{
+ QDict *resp;
+
+ resp = qtest_qmp(qtest, "{'execute': 'system_reset'}");
+ g_assert(qdict_haskey(resp, "return"));
+ qobject_unref(resp);
+}
+
+static void wait_device_deleted_event(QTestState *qtest, const char *id)
+{
+ QDict *resp, *data;
+ QString *qstr;
+
+ /*
+ * Other devices might get removed along with the removed device. Skip
+ * these. The device of interest will be the last one.
+ */
+ for (;;) {
+ resp = qtest_qmp_eventwait_ref(qtest, "DEVICE_DELETED");
+ data = qdict_get_qdict(resp, "data");
+ if (!data || !qdict_get(data, "device")) {
+ qobject_unref(resp);
+ continue;
+ }
+ qstr = qobject_to(QString, qdict_get(data, "device"));
+ g_assert(qstr);
+ if (!strcmp(qstring_get_str(qstr), id)) {
+ qobject_unref(resp);
+ break;
+ }
+ qobject_unref(resp);
+ }
+}
+
+static void test_pci_unplug_request(void)
+{
+ QTestState *qtest = qtest_initf("-device virtio-mouse-pci,id=dev0");
+
+ /*
+ * Request device removal. As the guest is not running, the request won't
+ * be processed. However during system reset, the removal will be
+ * handled, removing the device.
+ */
+ device_del_request(qtest, "dev0");
+ system_reset(qtest);
+ wait_device_deleted_event(qtest, "dev0");
+
+ qtest_quit(qtest);
+}
+
+static void test_ccw_unplug(void)
+{
+ QTestState *qtest = qtest_initf("-device virtio-balloon-ccw,id=dev0");
+
+ /*
+ * The DEVICE_DELETED events will be sent before the command
+ * completes.
+ */
+ device_del_start(qtest, "dev0");
+ wait_device_deleted_event(qtest, "dev0");
+ device_del_finish(qtest);
+
+ qtest_quit(qtest);
+}
+
+static void test_spapr_cpu_unplug_request(void)
+{
+ QTestState *qtest;
+
+ qtest = qtest_initf("-cpu power9_v2.0 -smp 1,maxcpus=2 "
+ "-device power9_v2.0-spapr-cpu-core,core-id=1,id=dev0");
+
+ /* similar to test_pci_unplug_request */
+ device_del_request(qtest, "dev0");
+ system_reset(qtest);
+ wait_device_deleted_event(qtest, "dev0");
+
+ qtest_quit(qtest);
+}
+
+static void test_spapr_memory_unplug_request(void)
+{
+ QTestState *qtest;
+
+ qtest = qtest_initf("-m 256M,slots=1,maxmem=768M "
+ "-object memory-backend-ram,id=mem0,size=512M "
+ "-device pc-dimm,id=dev0,memdev=mem0");
+
+ /* similar to test_pci_unplug_request */
+ device_del_request(qtest, "dev0");
+ system_reset(qtest);
+ wait_device_deleted_event(qtest, "dev0");
+
+ qtest_quit(qtest);
+}
+
+static void test_spapr_phb_unplug_request(void)
+{
+ QTestState *qtest;
+
+ qtest = qtest_initf("-device spapr-pci-host-bridge,index=1,id=dev0");
+
+ /* similar to test_pci_unplug_request */
+ device_del_request(qtest, "dev0");
+ system_reset(qtest);
+ wait_device_deleted_event(qtest, "dev0");
+
+ qtest_quit(qtest);
+}
+
+int main(int argc, char **argv)
+{
+ const char *arch = qtest_get_arch();
+
+ g_test_init(&argc, &argv, NULL);
+
+ /*
+ * We need a system that will process unplug requests during system resets
+ * and does not do PCI surprise removal. This holds for x86 ACPI,
+ * s390x and spapr.
+ */
+ qtest_add_func("/device-plug/pci-unplug-request",
+ test_pci_unplug_request);
+
+ if (!strcmp(arch, "s390x")) {
+ qtest_add_func("/device-plug/ccw-unplug",
+ test_ccw_unplug);
+ }
+
+ if (!strcmp(arch, "ppc64")) {
+ qtest_add_func("/device-plug/spapr-cpu-unplug-request",
+ test_spapr_cpu_unplug_request);
+ qtest_add_func("/device-plug/spapr-memory-unplug-request",
+ test_spapr_memory_unplug_request);
+ qtest_add_func("/device-plug/spapr-phb-unplug-request",
+ test_spapr_phb_unplug_request);
+ }
+
+ return g_test_run();
+}
diff --git a/tests/docker/dockerfiles/debian-amd64.docker b/tests/docker/dockerfiles/debian-amd64.docker
index 954fcf9..d770a11 100644
--- a/tests/docker/dockerfiles/debian-amd64.docker
+++ b/tests/docker/dockerfiles/debian-amd64.docker
@@ -33,6 +33,7 @@
apt-get install -y --no-install-recommends \
linux-headers-amd64
RUN git clone https://github.com/luigirizzo/netmap.git /usr/src/netmap
+RUN cd /usr/src/netmap && git checkout v11.3
RUN cd /usr/src/netmap/LINUX && ./configure --no-drivers --no-apps --kernel-dir=$(ls -d /usr/src/linux-headers-*-amd64) && make install
ENV QEMU_CONFIGURE_OPTS --enable-netmap
diff --git a/tests/docker/dockerfiles/debian9.docker b/tests/docker/dockerfiles/debian9.docker
index 154ae2a..5f23a35 100644
--- a/tests/docker/dockerfiles/debian9.docker
+++ b/tests/docker/dockerfiles/debian9.docker
@@ -13,8 +13,8 @@
RUN cat /etc/apt/sources.list | sed "s/^deb\ /deb-src /" >> /etc/apt/sources.list
# Install common build utilities
-RUN apt update
-RUN DEBIAN_FRONTEND=noninteractive apt install -yy eatmydata
+RUN apt-get update && \
+ DEBIAN_FRONTEND=noninteractive apt install -yy eatmydata
RUN DEBIAN_FRONTEND=noninteractive eatmydata \
apt install -y --no-install-recommends \
bison \
diff --git a/tests/fdc-test.c b/tests/fdc-test.c
index 88f1abf..31cd329 100644
--- a/tests/fdc-test.c
+++ b/tests/fdc-test.c
@@ -548,16 +548,9 @@
int main(int argc, char **argv)
{
- const char *arch = qtest_get_arch();
int fd;
int ret;
- /* Check architecture */
- if (strcmp(arch, "i386") && strcmp(arch, "x86_64")) {
- g_test_message("Skipping test for non-x86\n");
- return 0;
- }
-
/* Create a temporary raw image */
fd = mkstemp(test_image);
g_assert(fd >= 0);
diff --git a/tests/fp/fp-test.c b/tests/fp/fp-test.c
index 2a35ef6..7d0faf2 100644
--- a/tests/fp/fp-test.c
+++ b/tests/fp/fp-test.c
@@ -125,17 +125,42 @@
static bool blacklisted(unsigned op, int rmode)
{
- /* odd has only been implemented for a few 128-bit ops */
+ /* odd has not been implemented for any 80-bit ops */
if (rmode == softfloat_round_odd) {
switch (op) {
- case F128_ADD:
- case F128_SUB:
- case F128_MUL:
- case F128_DIV:
- case F128_TO_F64:
- case F128_SQRT:
- return false;
- default:
+ case EXTF80_TO_UI32:
+ case EXTF80_TO_UI64:
+ case EXTF80_TO_I32:
+ case EXTF80_TO_I64:
+ case EXTF80_TO_UI32_R_MINMAG:
+ case EXTF80_TO_UI64_R_MINMAG:
+ case EXTF80_TO_I32_R_MINMAG:
+ case EXTF80_TO_I64_R_MINMAG:
+ case EXTF80_TO_F16:
+ case EXTF80_TO_F32:
+ case EXTF80_TO_F64:
+ case EXTF80_TO_F128:
+ case EXTF80_ROUNDTOINT:
+ case EXTF80_ADD:
+ case EXTF80_SUB:
+ case EXTF80_MUL:
+ case EXTF80_DIV:
+ case EXTF80_REM:
+ case EXTF80_SQRT:
+ case EXTF80_EQ:
+ case EXTF80_LE:
+ case EXTF80_LT:
+ case EXTF80_EQ_SIGNALING:
+ case EXTF80_LE_QUIET:
+ case EXTF80_LT_QUIET:
+ case UI32_TO_EXTF80:
+ case UI64_TO_EXTF80:
+ case I32_TO_EXTF80:
+ case I64_TO_EXTF80:
+ case F16_TO_EXTF80:
+ case F32_TO_EXTF80:
+ case F64_TO_EXTF80:
+ case F128_TO_EXTF80:
return true;
}
}
@@ -622,7 +647,8 @@
test_ab_extF80_z_bool(true_ab_extF80M_z_bool, subj_ab_extF80M_z_bool);
break;
case F128_TO_UI32:
- not_implemented();
+ test_a_f128_z_ui32_rx(slow_f128M_to_ui32, qemu_f128M_to_ui32, rmode,
+ exact);
break;
case F128_TO_UI64:
test_a_f128_z_ui64_rx(slow_f128M_to_ui64, qemu_f128M_to_ui64, rmode,
diff --git a/tests/fp/wrap.inc.c b/tests/fp/wrap.inc.c
index d3bf600..0cbd200 100644
--- a/tests/fp/wrap.inc.c
+++ b/tests/fp/wrap.inc.c
@@ -367,6 +367,7 @@
WRAP_128_TO_INT(qemu_f128M_to_i32, float128_to_int32, int_fast32_t)
WRAP_128_TO_INT(qemu_f128M_to_i64, float128_to_int64, int_fast64_t)
+WRAP_128_TO_INT(qemu_f128M_to_ui32, float128_to_uint32, uint_fast32_t)
WRAP_128_TO_INT(qemu_f128M_to_ui64, float128_to_uint64, uint_fast64_t)
#undef WRAP_128_TO_INT
diff --git a/tests/ide-test.c b/tests/ide-test.c
index f0280e6..300d64e 100644
--- a/tests/ide-test.c
+++ b/tests/ide-test.c
@@ -1009,16 +1009,9 @@
int main(int argc, char **argv)
{
- const char *arch = qtest_get_arch();
int fd;
int ret;
- /* Check architecture */
- if (strcmp(arch, "i386") && strcmp(arch, "x86_64")) {
- g_test_message("Skipping test for non-x86\n");
- return 0;
- }
-
/* Create temporary blkdebug instructions */
fd = mkstemp(debug_path);
g_assert(fd >= 0);
diff --git a/tests/ipmi-bt-test.c b/tests/ipmi-bt-test.c
index f4a81b5..fc4c83b 100644
--- a/tests/ipmi-bt-test.c
+++ b/tests/ipmi-bt-test.c
@@ -400,15 +400,8 @@
int main(int argc, char **argv)
{
- const char *arch = qtest_get_arch();
int ret;
- /* Check architecture */
- if (strcmp(arch, "i386") && strcmp(arch, "x86_64")) {
- g_test_message("Skipping test for non-x86\n");
- return 0;
- }
-
open_socket();
/* Run the tests */
diff --git a/tests/ipmi-kcs-test.c b/tests/ipmi-kcs-test.c
index 178ffc1..a2354c1 100644
--- a/tests/ipmi-kcs-test.c
+++ b/tests/ipmi-kcs-test.c
@@ -263,16 +263,9 @@
int main(int argc, char **argv)
{
- const char *arch = qtest_get_arch();
char *cmdline;
int ret;
- /* Check architecture */
- if (strcmp(arch, "i386") && strcmp(arch, "x86_64")) {
- g_test_message("Skipping test for non-x86\n");
- return 0;
- }
-
/* Run the tests */
g_test_init(&argc, &argv, NULL);
diff --git a/tests/migration-test.c b/tests/migration-test.c
index 8352612..e3617ce 100644
--- a/tests/migration-test.c
+++ b/tests/migration-test.c
@@ -20,6 +20,9 @@
#include "qemu/sockets.h"
#include "chardev/char.h"
#include "sysemu/sysemu.h"
+#include "qapi/qapi-visit-sockets.h"
+#include "qapi/qobject-input-visitor.h"
+#include "qapi/qobject-output-visitor.h"
#include "migration/migration-test.h"
@@ -215,10 +218,10 @@
* events suddenly appearing confuse the qmp()/hmp() responses.
*/
-static uint64_t get_migration_pass(QTestState *who)
+static int64_t read_ram_property_int(QTestState *who, const char *property)
{
QDict *rsp_return, *rsp_ram;
- uint64_t result;
+ int64_t result;
rsp_return = migrate_query(who);
if (!qdict_haskey(rsp_return, "ram")) {
@@ -226,12 +229,17 @@
result = 0;
} else {
rsp_ram = qdict_get_qdict(rsp_return, "ram");
- result = qdict_get_try_int(rsp_ram, "dirty-sync-count", 0);
+ result = qdict_get_try_int(rsp_ram, property, 0);
}
qobject_unref(rsp_return);
return result;
}
+static uint64_t get_migration_pass(QTestState *who)
+{
+ return read_ram_property_int(who, "dirty-sync-count");
+}
+
static void read_blocktime(QTestState *who)
{
QDict *rsp_return;
@@ -332,15 +340,75 @@
g_free(path);
}
+static char *get_shmem_opts(const char *mem_size, const char *shmem_path)
+{
+ return g_strdup_printf("-object memory-backend-file,id=mem0,size=%s"
+ ",mem-path=%s,share=on -numa node,memdev=mem0",
+ mem_size, shmem_path);
+}
+
+static char *SocketAddress_to_str(SocketAddress *addr)
+{
+ switch (addr->type) {
+ case SOCKET_ADDRESS_TYPE_INET:
+ return g_strdup_printf("tcp:%s:%s",
+ addr->u.inet.host,
+ addr->u.inet.port);
+ case SOCKET_ADDRESS_TYPE_UNIX:
+ return g_strdup_printf("unix:%s",
+ addr->u.q_unix.path);
+ case SOCKET_ADDRESS_TYPE_FD:
+ return g_strdup_printf("fd:%s", addr->u.fd.str);
+ case SOCKET_ADDRESS_TYPE_VSOCK:
+ return g_strdup_printf("tcp:%s:%s",
+ addr->u.vsock.cid,
+ addr->u.vsock.port);
+ default:
+ return g_strdup("unknown address type");
+ }
+}
+
+static char *migrate_get_socket_address(QTestState *who, const char *parameter)
+{
+ QDict *rsp;
+ char *result;
+ Error *local_err = NULL;
+ SocketAddressList *addrs;
+ Visitor *iv = NULL;
+ QObject *object;
+
+ rsp = migrate_query(who);
+ object = qdict_get(rsp, parameter);
+
+ iv = qobject_input_visitor_new(object);
+ visit_type_SocketAddressList(iv, NULL, &addrs, &local_err);
+
+ /* we are only using a single address */
+ result = g_strdup_printf("%s", SocketAddress_to_str(addrs->value));
+
+ qapi_free_SocketAddressList(addrs);
+ qobject_unref(rsp);
+ return result;
+}
+
+static long long migrate_get_parameter(QTestState *who, const char *parameter)
+{
+ QDict *rsp;
+ long long result;
+
+ rsp = wait_command(who, "{ 'execute': 'query-migrate-parameters' }");
+ result = qdict_get_int(rsp, parameter);
+ qobject_unref(rsp);
+ return result;
+}
+
static void migrate_check_parameter(QTestState *who, const char *parameter,
long long value)
{
- QDict *rsp_return;
+ long long result;
- rsp_return = wait_command(who,
- "{ 'execute': 'query-migrate-parameters' }");
- g_assert_cmpint(qdict_get_int(rsp_return, parameter), ==, value);
- qobject_unref(rsp_return);
+ result = migrate_get_parameter(who, parameter);
+ g_assert_cmpint(result, ==, value);
}
static void migrate_set_parameter(QTestState *who, const char *parameter,
@@ -430,73 +498,95 @@
}
static int test_migrate_start(QTestState **from, QTestState **to,
- const char *uri, bool hide_stderr)
+ const char *uri, bool hide_stderr,
+ bool use_shmem)
{
gchar *cmd_src, *cmd_dst;
- char *bootpath = g_strdup_printf("%s/bootsect", tmpfs);
+ char *bootpath = NULL;
+ char *extra_opts = NULL;
+ char *shmem_path = NULL;
const char *arch = qtest_get_arch();
const char *accel = "kvm:tcg";
- got_stop = false;
+ if (use_shmem) {
+ if (!g_file_test("/dev/shm", G_FILE_TEST_IS_DIR)) {
+ g_test_skip("/dev/shm is not supported");
+ return -1;
+ }
+ shmem_path = g_strdup_printf("/dev/shm/qemu-%d", getpid());
+ }
+ got_stop = false;
+ bootpath = g_strdup_printf("%s/bootsect", tmpfs);
if (strcmp(arch, "i386") == 0 || strcmp(arch, "x86_64") == 0) {
init_bootfile(bootpath, x86_bootsect);
+ extra_opts = use_shmem ? get_shmem_opts("150M", shmem_path) : NULL;
cmd_src = g_strdup_printf("-machine accel=%s -m 150M"
" -name source,debug-threads=on"
" -serial file:%s/src_serial"
- " -drive file=%s,format=raw",
- accel, tmpfs, bootpath);
+ " -drive file=%s,format=raw %s",
+ accel, tmpfs, bootpath,
+ extra_opts ? extra_opts : "");
cmd_dst = g_strdup_printf("-machine accel=%s -m 150M"
" -name target,debug-threads=on"
" -serial file:%s/dest_serial"
" -drive file=%s,format=raw"
- " -incoming %s",
- accel, tmpfs, bootpath, uri);
+ " -incoming %s %s",
+ accel, tmpfs, bootpath, uri,
+ extra_opts ? extra_opts : "");
start_address = X86_TEST_MEM_START;
end_address = X86_TEST_MEM_END;
} else if (g_str_equal(arch, "s390x")) {
init_bootfile_s390x(bootpath);
+ extra_opts = use_shmem ? get_shmem_opts("128M", shmem_path) : NULL;
cmd_src = g_strdup_printf("-machine accel=%s -m 128M"
" -name source,debug-threads=on"
- " -serial file:%s/src_serial -bios %s",
- accel, tmpfs, bootpath);
+ " -serial file:%s/src_serial -bios %s %s",
+ accel, tmpfs, bootpath,
+ extra_opts ? extra_opts : "");
cmd_dst = g_strdup_printf("-machine accel=%s -m 128M"
" -name target,debug-threads=on"
" -serial file:%s/dest_serial -bios %s"
- " -incoming %s",
- accel, tmpfs, bootpath, uri);
+ " -incoming %s %s",
+ accel, tmpfs, bootpath, uri,
+ extra_opts ? extra_opts : "");
start_address = S390_TEST_MEM_START;
end_address = S390_TEST_MEM_END;
} else if (strcmp(arch, "ppc64") == 0) {
+ extra_opts = use_shmem ? get_shmem_opts("256M", shmem_path) : NULL;
cmd_src = g_strdup_printf("-machine accel=%s -m 256M -nodefaults"
" -name source,debug-threads=on"
" -serial file:%s/src_serial"
" -prom-env 'use-nvramrc?=true' -prom-env "
"'nvramrc=hex .\" _\" begin %x %x "
"do i c@ 1 + i c! 1000 +loop .\" B\" 0 "
- "until'", accel, tmpfs, end_address,
- start_address);
+ "until' %s", accel, tmpfs, end_address,
+ start_address, extra_opts ? extra_opts : "");
cmd_dst = g_strdup_printf("-machine accel=%s -m 256M"
" -name target,debug-threads=on"
" -serial file:%s/dest_serial"
- " -incoming %s",
- accel, tmpfs, uri);
+ " -incoming %s %s",
+ accel, tmpfs, uri,
+ extra_opts ? extra_opts : "");
start_address = PPC_TEST_MEM_START;
end_address = PPC_TEST_MEM_END;
} else if (strcmp(arch, "aarch64") == 0) {
init_bootfile(bootpath, aarch64_kernel);
+ extra_opts = use_shmem ? get_shmem_opts("150M", shmem_path) : NULL;
cmd_src = g_strdup_printf("-machine virt,accel=%s,gic-version=max "
"-name vmsource,debug-threads=on -cpu max "
"-m 150M -serial file:%s/src_serial "
- "-kernel %s ",
- accel, tmpfs, bootpath);
+ "-kernel %s %s",
+ accel, tmpfs, bootpath,
+ extra_opts ? extra_opts : "");
cmd_dst = g_strdup_printf("-machine virt,accel=%s,gic-version=max "
"-name vmdest,debug-threads=on -cpu max "
"-m 150M -serial file:%s/dest_serial "
"-kernel %s "
- "-incoming %s ",
- accel, tmpfs, bootpath, uri);
+ "-incoming %s %s",
+ accel, tmpfs, bootpath, uri,
+ extra_opts ? extra_opts : "");
start_address = ARM_TEST_MEM_START;
end_address = ARM_TEST_MEM_END;
@@ -507,6 +597,7 @@
}
g_free(bootpath);
+ g_free(extra_opts);
if (hide_stderr) {
gchar *tmp;
@@ -524,6 +615,16 @@
*to = qtest_init(cmd_dst);
g_free(cmd_dst);
+
+ /*
+ * Remove shmem file immediately to avoid memory leak in test failed case.
+ * It's valid becase QEMU has already opened this file
+ */
+ if (use_shmem) {
+ unlink(shmem_path);
+ g_free(shmem_path);
+ }
+
return 0;
}
@@ -584,6 +685,17 @@
migrate_check_parameter(who, "max-bandwidth", value);
}
+static void deprecated_set_cache_size(QTestState *who, long long value)
+{
+ QDict *rsp;
+
+ rsp = qtest_qmp(who, "{ 'execute': 'migrate-set-cache-size',"
+ "'arguments': { 'value': %lld } }", value);
+ g_assert(qdict_haskey(rsp, "return"));
+ qobject_unref(rsp);
+ migrate_check_parameter(who, "xbzrle-cache-size", value);
+}
+
static void test_deprecated(void)
{
QTestState *from;
@@ -592,6 +704,7 @@
deprecated_set_downtime(from, 0.12345);
deprecated_set_speed(from, 12345);
+ deprecated_set_cache_size(from, 4096);
qtest_quit(from);
}
@@ -603,7 +716,7 @@
char *uri = g_strdup_printf("unix:%s/migsocket", tmpfs);
QTestState *from, *to;
- if (test_migrate_start(&from, &to, uri, hide_error)) {
+ if (test_migrate_start(&from, &to, uri, hide_error, false)) {
return -1;
}
@@ -720,7 +833,7 @@
char *status;
bool failed;
- if (test_migrate_start(&from, &to, "tcp:0:0", true)) {
+ if (test_migrate_start(&from, &to, "tcp:0:0", true, false)) {
return;
}
migrate(from, "tcp:0:0", "{}");
@@ -745,7 +858,7 @@
char *uri = g_strdup_printf("unix:%s/migsocket", tmpfs);
QTestState *from, *to;
- if (test_migrate_start(&from, &to, uri, false)) {
+ if (test_migrate_start(&from, &to, uri, false, false)) {
return;
}
@@ -781,6 +894,138 @@
g_free(uri);
}
+#if 0
+/* Currently upset on aarch64 TCG */
+static void test_ignore_shared(void)
+{
+ char *uri = g_strdup_printf("unix:%s/migsocket", tmpfs);
+ QTestState *from, *to;
+
+ if (test_migrate_start(&from, &to, uri, false, true)) {
+ return;
+ }
+
+ migrate_set_capability(from, "x-ignore-shared", true);
+ migrate_set_capability(to, "x-ignore-shared", true);
+
+ /* Wait for the first serial output from the source */
+ wait_for_serial("src_serial");
+
+ migrate(from, uri, "{}");
+
+ wait_for_migration_pass(from);
+
+ if (!got_stop) {
+ qtest_qmp_eventwait(from, "STOP");
+ }
+
+ qtest_qmp_eventwait(to, "RESUME");
+
+ wait_for_serial("dest_serial");
+ wait_for_migration_complete(from);
+
+ /* Check whether shared RAM has been really skipped */
+ g_assert_cmpint(read_ram_property_int(from, "transferred"), <, 1024 * 1024);
+
+ test_migrate_end(from, to, true);
+ g_free(uri);
+}
+#endif
+
+static void test_xbzrle(const char *uri)
+{
+ QTestState *from, *to;
+
+ if (test_migrate_start(&from, &to, uri, 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);
+
+ migrate_set_parameter(from, "xbzrle-cache-size", 33554432);
+
+ migrate_set_capability(from, "xbzrle", "true");
+ migrate_set_capability(to, "xbzrle", "true");
+ /* Wait for the first serial output from the source */
+ wait_for_serial("src_serial");
+
+ migrate(from, uri, "{}");
+
+ 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");
+
+ wait_for_serial("dest_serial");
+ wait_for_migration_complete(from);
+
+ test_migrate_end(from, to, true);
+}
+
+static void test_xbzrle_unix(void)
+{
+ char *uri = g_strdup_printf("unix:%s/migsocket", tmpfs);
+
+ test_xbzrle(uri);
+ g_free(uri);
+}
+
+static void test_precopy_tcp(void)
+{
+ char *uri;
+ QTestState *from, *to;
+
+ if (test_migrate_start(&from, &to, "tcp:127.0.0.1:0", 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");
+
+ uri = migrate_get_socket_address(to, "socket-address");
+
+ migrate(from, uri, "{}");
+
+ 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");
+
+ wait_for_serial("dest_serial");
+ wait_for_migration_complete(from);
+
+ test_migrate_end(from, to, true);
+ g_free(uri);
+}
+
int main(int argc, char **argv)
{
char template[] = "/tmp/migration-test-XXXXXX";
@@ -832,6 +1077,9 @@
qtest_add_func("/migration/deprecated", test_deprecated);
qtest_add_func("/migration/bad_dest", test_baddest);
qtest_add_func("/migration/precopy/unix", test_precopy_unix);
+ 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);
ret = g_test_run();
diff --git a/tests/qapi-schema/include-relpath-sub.json b/tests/qapi-schema/include-relpath-sub.json
deleted file mode 100644
index 4bd4af4..0000000
--- a/tests/qapi-schema/include-relpath-sub.json
+++ /dev/null
@@ -1,2 +0,0 @@
-{ 'enum': 'Status',
- 'data': [ 'good', 'bad', 'ugly' ] }
diff --git a/tests/qapi-schema/include-relpath.err b/tests/qapi-schema/include-relpath.err
deleted file mode 100644
index e69de29..0000000
--- a/tests/qapi-schema/include-relpath.err
+++ /dev/null
diff --git a/tests/qapi-schema/include-relpath.exit b/tests/qapi-schema/include-relpath.exit
deleted file mode 100644
index 573541a..0000000
--- a/tests/qapi-schema/include-relpath.exit
+++ /dev/null
@@ -1 +0,0 @@
-0
diff --git a/tests/qapi-schema/include-relpath.json b/tests/qapi-schema/include-relpath.json
deleted file mode 100644
index 05018f3..0000000
--- a/tests/qapi-schema/include-relpath.json
+++ /dev/null
@@ -1 +0,0 @@
-{ 'include': 'include/relpath.json' }
diff --git a/tests/qapi-schema/include-relpath.out b/tests/qapi-schema/include-relpath.out
deleted file mode 100644
index cf8636b..0000000
--- a/tests/qapi-schema/include-relpath.out
+++ /dev/null
@@ -1,20 +0,0 @@
-module None
-object q_empty
-enum QType
- prefix QTYPE
- member none
- member qnull
- member qnum
- member qstring
- member qdict
- member qlist
- member qbool
-module include-relpath.json
-include include/relpath.json
-module include/relpath.json
-include include-relpath-sub.json
-module include-relpath-sub.json
-enum Status
- member good
- member bad
- member ugly
diff --git a/tests/qapi-schema/include/relpath.json b/tests/qapi-schema/include/relpath.json
deleted file mode 100644
index 45dee24..0000000
--- a/tests/qapi-schema/include/relpath.json
+++ /dev/null
@@ -1 +0,0 @@
-{ 'include': '../include-relpath-sub.json' }
diff --git a/tests/qapi-schema/include/sub-module.json b/tests/qapi-schema/include/sub-module.json
new file mode 100644
index 0000000..afdb267
--- /dev/null
+++ b/tests/qapi-schema/include/sub-module.json
@@ -0,0 +1,7 @@
+# *-*- Mode: Python -*-*
+
+# Sub-module of ../qapi-schema-test.json
+
+{ 'include': '../sub-sub-module.json' }
+
+{ 'struct': 'SecondArrayRef', 'data': { 's': ['Status'] } }
diff --git a/tests/qapi-schema/qapi-schema-test.json b/tests/qapi-schema/qapi-schema-test.json
index cb0857d..0952c68 100644
--- a/tests/qapi-schema/qapi-schema-test.json
+++ b/tests/qapi-schema/qapi-schema-test.json
@@ -113,8 +113,8 @@
# for testing use of 'str' within alternates
{ 'alternate': 'AltStrObj', 'data': { 's': 'str', 'o': 'TestStruct' } }
-# for testing native lists
-{ 'union': 'UserDefNativeListUnion',
+# for testing lists
+{ 'union': 'UserDefListUnion',
'data': { 'integer': ['int'],
's8': ['int8'],
's16': ['int16'],
@@ -128,7 +128,11 @@
'boolean': ['bool'],
'string': ['str'],
'sizes': ['size'],
- 'any': ['any'] } }
+ 'any': ['any'],
+ 'user': ['Status'] } } # intentional forward ref. to sub-module
+
+# for testing sub-modules
+{ 'include': 'include/sub-module.json' }
# testing commands
{ 'command': 'user_def_cmd', 'data': {} }
@@ -144,7 +148,7 @@
'returns': 'int' }
{ 'command': 'guest-sync', 'data': { 'arg': 'any' }, 'returns': 'any' }
{ 'command': 'boxed-struct', 'boxed': true, 'data': 'UserDefZero' }
-{ 'command': 'boxed-union', 'data': 'UserDefNativeListUnion', 'boxed': true }
+{ 'command': 'boxed-union', 'data': 'UserDefListUnion', 'boxed': true }
# Smoke test on out-of-band and allow-preconfig-test
{ 'command': 'test-flags-command', 'allow-oob': true, 'allow-preconfig': true }
@@ -236,5 +240,5 @@
{ 'event': 'TestIfEvent', 'data':
{ 'foo': 'TestIfStruct',
- 'bar': { 'type': 'TestIfEnum', 'if': 'defined(TEST_IF_EVT_BAR)' } },
+ 'bar': { 'type': ['TestIfEnum'], 'if': 'defined(TEST_IF_EVT_BAR)' } },
'if': 'defined(TEST_IF_EVT) && defined(TEST_IF_STRUCT)' }
diff --git a/tests/qapi-schema/qapi-schema-test.out b/tests/qapi-schema/qapi-schema-test.out
index d8aec17..77fb1e1 100644
--- a/tests/qapi-schema/qapi-schema-test.out
+++ b/tests/qapi-schema/qapi-schema-test.out
@@ -52,6 +52,9 @@
member dict1: UserDefTwoDict optional=False
object UserDefThree
member string0: str optional=False
+array UserDefOneList UserDefOne
+array UserDefTwoList UserDefTwo
+array TestStructList TestStruct
object ForceArrays
member unused1: UserDefOneList optional=False
member unused2: UserDefTwoList optional=False
@@ -141,7 +144,12 @@
member data: sizeList optional=False
object q_obj_anyList-wrapper
member data: anyList optional=False
-enum UserDefNativeListUnionKind
+module sub-sub-module.json
+array StatusList Status
+module qapi-schema-test.json
+object q_obj_StatusList-wrapper
+ member data: StatusList optional=False
+enum UserDefListUnionKind
member integer
member s8
member s16
@@ -156,8 +164,9 @@
member string
member sizes
member any
-object UserDefNativeListUnion
- member type: UserDefNativeListUnionKind optional=False
+ member user
+object UserDefListUnion
+ member type: UserDefListUnionKind optional=False
tag type
case integer: q_obj_intList-wrapper
case s8: q_obj_int8List-wrapper
@@ -173,6 +182,19 @@
case string: q_obj_strList-wrapper
case sizes: q_obj_sizeList-wrapper
case any: q_obj_anyList-wrapper
+ case user: q_obj_StatusList-wrapper
+include include/sub-module.json
+module include/sub-module.json
+include sub-sub-module.json
+module sub-sub-module.json
+enum Status
+ member good
+ member bad
+ member ugly
+module include/sub-module.json
+object SecondArrayRef
+ member s: StatusList optional=False
+module qapi-schema-test.json
command user_def_cmd None -> None
gen=True success_response=True boxed=False oob=False preconfig=False
object q_obj_user_def_cmd1-arg
@@ -197,7 +219,7 @@
gen=True success_response=True boxed=False oob=False preconfig=False
command boxed-struct UserDefZero -> None
gen=True success_response=True boxed=True oob=False preconfig=False
-command boxed-union UserDefNativeListUnion -> None
+command boxed-union UserDefListUnion -> None
gen=True success_response=True boxed=True oob=False preconfig=False
command test-flags-command None -> None
gen=True success_response=True boxed=False oob=True preconfig=True
@@ -248,6 +270,7 @@
member type: __org.qemu_x-Union1Kind optional=False
tag type
case __org.qemu_x-branch: q_obj_str-wrapper
+array __org.qemu_x-Union1List __org.qemu_x-Union1
object __org.qemu_x-Struct2
member array: __org.qemu_x-Union1List optional=False
object __org.qemu_x-Union2
@@ -260,6 +283,8 @@
case b: __org.qemu_x-Base
event __ORG.QEMU_X-EVENT __org.qemu_x-Struct
boxed=False
+array __org.qemu_x-EnumList __org.qemu_x-Enum
+array __org.qemu_x-StructList __org.qemu_x-Struct
object q_obj___org.qemu_x-command-arg
member a: __org.qemu_x-EnumList optional=False
member b: __org.qemu_x-StructList optional=False
@@ -319,9 +344,11 @@
if ['defined(TEST_IF_CMD)', 'defined(TEST_IF_STRUCT)']
command TestCmdReturnDefThree None -> UserDefThree
gen=True success_response=True boxed=False oob=False preconfig=False
+array TestIfEnumList TestIfEnum
+ if ['defined(TEST_IF_ENUM)']
object q_obj_TestIfEvent-arg
member foo: TestIfStruct optional=False
- member bar: TestIfEnum optional=False
+ member bar: TestIfEnumList optional=False
if ['defined(TEST_IF_EVT_BAR)']
if ['defined(TEST_IF_EVT) && defined(TEST_IF_STRUCT)']
event TestIfEvent q_obj_TestIfEvent-arg
diff --git a/tests/qapi-schema/sub-sub-module.json b/tests/qapi-schema/sub-sub-module.json
new file mode 100644
index 0000000..524ef9b
--- /dev/null
+++ b/tests/qapi-schema/sub-sub-module.json
@@ -0,0 +1,6 @@
+# *-*- Mode: Python -*-*
+
+# Sub-module of sub-module include/sub-module.json of qapi-schema-test.json
+
+{ 'enum': 'Status',
+ 'data': [ 'good', 'bad', 'ugly' ] }
diff --git a/tests/qapi-schema/test-qapi.py b/tests/qapi-schema/test-qapi.py
index d592854..d21fca0 100644
--- a/tests/qapi-schema/test-qapi.py
+++ b/tests/qapi-schema/test-qapi.py
@@ -32,6 +32,12 @@
self._print_if(m.ifcond, indent=8)
self._print_if(ifcond)
+ def visit_array_type(self, name, info, ifcond, element_type):
+ if not info:
+ return # suppress built-in arrays
+ print('array %s %s' % (name, element_type.name))
+ self._print_if(ifcond)
+
def visit_object_type(self, name, info, ifcond, base, members, variants):
print('object %s' % name)
if base:
diff --git a/tests/qemu-iotests/045 b/tests/qemu-iotests/045
index 55a5d31..d5484a0 100755
--- a/tests/qemu-iotests/045
+++ b/tests/qemu-iotests/045
@@ -132,7 +132,7 @@
qemu_img('create', '-f', iotests.imgfmt, image0, '128K')
# Add an unused monitor, to verify it works fine when two monitor
# instances present
- self.vm.add_monitor_telnet("0",4445)
+ self.vm.add_monitor_null()
self.vm.launch()
def tearDown(self):
diff --git a/tests/qemu-iotests/051.out b/tests/qemu-iotests/051.out
index 793af2a..b900935 100644
--- a/tests/qemu-iotests/051.out
+++ b/tests/qemu-iotests/051.out
@@ -82,7 +82,7 @@
Testing: -drive file=TEST_DIR/t.qcow2,driver=qcow2,backing.file.filename=TEST_DIR/t.qcow2.orig,if=none,id=drive0 -nodefaults
QEMU X.Y.Z monitor - type 'help' for more information
(qemu) info block
-drive0 (NODE_NAME): TEST_DIR/t.qcow2 (qcow2)
+drive0 (NODE_NAME): json:{"backing": {"driver": "qcow2", "file": {"driver": "file", "filename": "TEST_DIR/t.qcow2.orig"}}, "driver": "qcow2", "file": {"driver": "file", "filename": "TEST_DIR/t.qcow2"}} (qcow2)
Removable device: not locked, tray closed
Cache mode: writeback
Backing file: TEST_DIR/t.qcow2.orig (chain depth: 1)
@@ -172,7 +172,7 @@
Testing: -drive file=TEST_DIR/t.qcow2,cache=writeback,backing.file.filename=TEST_DIR/t.qcow2.base,backing.cache.no-flush=on,backing.node-name=backing,backing.file.node-name=backing-file,file.node-name=file,if=none,id=drive0 -nodefaults
QEMU X.Y.Z monitor - type 'help' for more information
(qemu) info block
-drive0 (NODE_NAME): TEST_DIR/t.qcow2 (qcow2)
+drive0 (NODE_NAME): json:{"backing": {"driver": "qcow2", "file": {"driver": "file", "filename": "TEST_DIR/t.qcow2.base"}}, "driver": "qcow2", "file": {"driver": "file", "filename": "TEST_DIR/t.qcow2"}} (qcow2)
Removable device: not locked, tray closed
Cache mode: writeback
Backing file: TEST_DIR/t.qcow2.base (chain depth: 1)
@@ -192,7 +192,7 @@
Testing: -drive file=TEST_DIR/t.qcow2,cache=writethrough,backing.file.filename=TEST_DIR/t.qcow2.base,backing.cache.no-flush=on,backing.node-name=backing,backing.file.node-name=backing-file,file.node-name=file,if=none,id=drive0 -nodefaults
QEMU X.Y.Z monitor - type 'help' for more information
(qemu) info block
-drive0 (NODE_NAME): TEST_DIR/t.qcow2 (qcow2)
+drive0 (NODE_NAME): json:{"backing": {"driver": "qcow2", "file": {"driver": "file", "filename": "TEST_DIR/t.qcow2.base"}}, "driver": "qcow2", "file": {"driver": "file", "filename": "TEST_DIR/t.qcow2"}} (qcow2)
Removable device: not locked, tray closed
Cache mode: writethrough
Backing file: TEST_DIR/t.qcow2.base (chain depth: 1)
@@ -212,7 +212,7 @@
Testing: -drive file=TEST_DIR/t.qcow2,cache=unsafe,backing.file.filename=TEST_DIR/t.qcow2.base,backing.cache.no-flush=on,backing.node-name=backing,backing.file.node-name=backing-file,file.node-name=file,if=none,id=drive0 -nodefaults
QEMU X.Y.Z monitor - type 'help' for more information
(qemu) info block
-drive0 (NODE_NAME): TEST_DIR/t.qcow2 (qcow2)
+drive0 (NODE_NAME): json:{"backing": {"driver": "qcow2", "file": {"driver": "file", "filename": "TEST_DIR/t.qcow2.base"}}, "driver": "qcow2", "file": {"driver": "file", "filename": "TEST_DIR/t.qcow2"}} (qcow2)
Removable device: not locked, tray closed
Cache mode: writeback, ignore flushes
Backing file: TEST_DIR/t.qcow2.base (chain depth: 1)
diff --git a/tests/qemu-iotests/051.pc.out b/tests/qemu-iotests/051.pc.out
index ca64eda..8c5c735 100644
--- a/tests/qemu-iotests/051.pc.out
+++ b/tests/qemu-iotests/051.pc.out
@@ -82,7 +82,7 @@
Testing: -drive file=TEST_DIR/t.qcow2,driver=qcow2,backing.file.filename=TEST_DIR/t.qcow2.orig,if=none,id=drive0 -nodefaults
QEMU X.Y.Z monitor - type 'help' for more information
(qemu) info block
-drive0 (NODE_NAME): TEST_DIR/t.qcow2 (qcow2)
+drive0 (NODE_NAME): json:{"backing": {"driver": "qcow2", "file": {"driver": "file", "filename": "TEST_DIR/t.qcow2.orig"}}, "driver": "qcow2", "file": {"driver": "file", "filename": "TEST_DIR/t.qcow2"}} (qcow2)
Removable device: not locked, tray closed
Cache mode: writeback
Backing file: TEST_DIR/t.qcow2.orig (chain depth: 1)
@@ -244,7 +244,7 @@
Testing: -drive file=TEST_DIR/t.qcow2,cache=writeback,backing.file.filename=TEST_DIR/t.qcow2.base,backing.cache.no-flush=on,backing.node-name=backing,backing.file.node-name=backing-file,file.node-name=file,if=none,id=drive0 -nodefaults
QEMU X.Y.Z monitor - type 'help' for more information
(qemu) info block
-drive0 (NODE_NAME): TEST_DIR/t.qcow2 (qcow2)
+drive0 (NODE_NAME): json:{"backing": {"driver": "qcow2", "file": {"driver": "file", "filename": "TEST_DIR/t.qcow2.base"}}, "driver": "qcow2", "file": {"driver": "file", "filename": "TEST_DIR/t.qcow2"}} (qcow2)
Removable device: not locked, tray closed
Cache mode: writeback
Backing file: TEST_DIR/t.qcow2.base (chain depth: 1)
@@ -264,7 +264,7 @@
Testing: -drive file=TEST_DIR/t.qcow2,cache=writethrough,backing.file.filename=TEST_DIR/t.qcow2.base,backing.cache.no-flush=on,backing.node-name=backing,backing.file.node-name=backing-file,file.node-name=file,if=none,id=drive0 -nodefaults
QEMU X.Y.Z monitor - type 'help' for more information
(qemu) info block
-drive0 (NODE_NAME): TEST_DIR/t.qcow2 (qcow2)
+drive0 (NODE_NAME): json:{"backing": {"driver": "qcow2", "file": {"driver": "file", "filename": "TEST_DIR/t.qcow2.base"}}, "driver": "qcow2", "file": {"driver": "file", "filename": "TEST_DIR/t.qcow2"}} (qcow2)
Removable device: not locked, tray closed
Cache mode: writethrough
Backing file: TEST_DIR/t.qcow2.base (chain depth: 1)
@@ -284,7 +284,7 @@
Testing: -drive file=TEST_DIR/t.qcow2,cache=unsafe,backing.file.filename=TEST_DIR/t.qcow2.base,backing.cache.no-flush=on,backing.node-name=backing,backing.file.node-name=backing-file,file.node-name=file,if=none,id=drive0 -nodefaults
QEMU X.Y.Z monitor - type 'help' for more information
(qemu) info block
-drive0 (NODE_NAME): TEST_DIR/t.qcow2 (qcow2)
+drive0 (NODE_NAME): json:{"backing": {"driver": "qcow2", "file": {"driver": "file", "filename": "TEST_DIR/t.qcow2.base"}}, "driver": "qcow2", "file": {"driver": "file", "filename": "TEST_DIR/t.qcow2"}} (qcow2)
Removable device: not locked, tray closed
Cache mode: writeback, ignore flushes
Backing file: TEST_DIR/t.qcow2.base (chain depth: 1)
diff --git a/tests/qemu-iotests/110 b/tests/qemu-iotests/110
index b64b3b2..185ad54 100755
--- a/tests/qemu-iotests/110
+++ b/tests/qemu-iotests/110
@@ -29,6 +29,7 @@
_cleanup()
{
_cleanup_test_img
+ rm -f "$TEST_IMG.copy"
}
trap "_cleanup; exit \$status" 0 1 2 3 15
@@ -60,7 +61,8 @@
echo
# Across blkdebug without a config file, you cannot reconstruct filenames, so
-# qemu is incapable of knowing the directory of the top image
+# qemu is incapable of knowing the directory of the top image from the filename
+# alone. However, using bdrv_dirname(), it should still work.
TEST_IMG="json:{
'driver': '$IMGFMT',
'file': {
@@ -85,6 +87,31 @@
# omit the image size; it should work anyway
_make_test_img -b "$TEST_IMG_REL.base"
+echo
+echo '=== Nodes without a common directory ==='
+echo
+
+cp "$TEST_IMG" "$TEST_IMG.copy"
+
+# Should inform us that the actual path of the backing file cannot be determined
+TEST_IMG="json:{
+ 'driver': '$IMGFMT',
+ 'file': {
+ 'driver': 'quorum',
+ 'vote-threshold': 1,
+ 'children': [
+ {
+ 'driver': 'file',
+ 'filename': '$TEST_IMG'
+ },
+ {
+ 'driver': 'file',
+ 'filename': '$TEST_IMG.copy'
+ }
+ ]
+ }
+}" _img_info | _filter_img_info
+
# success, all done
echo '*** done'
diff --git a/tests/qemu-iotests/110.out b/tests/qemu-iotests/110.out
index b3584ff..46e6a60 100644
--- a/tests/qemu-iotests/110.out
+++ b/tests/qemu-iotests/110.out
@@ -14,9 +14,16 @@
image: json:{"driver": "IMGFMT", "file": {"set-state.0.event": "read_aio", "image": {"driver": "file", "filename": "TEST_DIR/t.IMGFMT"}, "driver": "blkdebug", "set-state.0.new_state": 42}}
file format: IMGFMT
virtual size: 64M (67108864 bytes)
-backing file: t.IMGFMT.base (cannot determine actual path)
+backing file: t.IMGFMT.base (actual path: TEST_DIR/t.IMGFMT.base)
=== Backing name is always relative to the backed image ===
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864 backing_file=t.IMGFMT.base
+
+=== Nodes without a common directory ===
+
+image: json:{"driver": "IMGFMT", "file": {"children": [{"driver": "file", "filename": "TEST_DIR/t.IMGFMT"}, {"driver": "file", "filename": "TEST_DIR/t.IMGFMT.copy"}], "driver": "quorum", "vote-threshold": 1}}
+file format: IMGFMT
+virtual size: 64M (67108864 bytes)
+backing file: t.IMGFMT.base (cannot determine actual path)
*** done
diff --git a/tests/qemu-iotests/178 b/tests/qemu-iotests/178
index 3f4b4a4..927bf06 100755
--- a/tests/qemu-iotests/178
+++ b/tests/qemu-iotests/178
@@ -142,6 +142,14 @@
# The backing file doesn't need to exist :)
$QEMU_IMG measure --output=$ofmt -o backing_file=x \
-f "$fmt" -O "$IMGFMT" "$TEST_IMG"
+
+ echo
+ echo "== $fmt input image and LUKS encryption =="
+ echo
+ $QEMU_IMG measure --output=$ofmt \
+ --object secret,id=sec0,data=base \
+ -o encrypt.format=luks,encrypt.key-secret=sec0,encrypt.iter-time=10 \
+ -f "$fmt" -O "$IMGFMT" "$TEST_IMG"
fi
echo
diff --git a/tests/qemu-iotests/178.out.qcow2 b/tests/qemu-iotests/178.out.qcow2
index d42d4a4..55a8dc9 100644
--- a/tests/qemu-iotests/178.out.qcow2
+++ b/tests/qemu-iotests/178.out.qcow2
@@ -68,6 +68,11 @@
required size: 1074135040
fully allocated size: 1074135040
+== qcow2 input image and LUKS encryption ==
+
+required size: 2686976
+fully allocated size: 1076232192
+
== qcow2 input image and preallocation (human) ==
required size: 1074135040
@@ -114,6 +119,11 @@
required size: 1074135040
fully allocated size: 1074135040
+== raw input image and LUKS encryption ==
+
+required size: 2686976
+fully allocated size: 1076232192
+
== raw input image and preallocation (human) ==
required size: 1074135040
@@ -205,6 +215,13 @@
"fully-allocated": 1074135040
}
+== qcow2 input image and LUKS encryption ==
+
+{
+ "required": 2686976,
+ "fully-allocated": 1076232192
+}
+
== qcow2 input image and preallocation (json) ==
{
@@ -263,6 +280,13 @@
"fully-allocated": 1074135040
}
+== raw input image and LUKS encryption ==
+
+{
+ "required": 2686976,
+ "fully-allocated": 1076232192
+}
+
== raw input image and preallocation (json) ==
{
diff --git a/tests/qemu-iotests/206.out b/tests/qemu-iotests/206.out
index 91f4db5..0f1c23b 100644
--- a/tests/qemu-iotests/206.out
+++ b/tests/qemu-iotests/206.out
@@ -1,13 +1,13 @@
=== Successful image creation (defaults) ===
-{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "file", "filename": "TEST_DIR/PID-t.qcow2", "size": 0}}}
+{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"driver": "file", "filename": "TEST_DIR/PID-t.qcow2", "size": 0}}}
{"return": {}}
{"execute": "job-dismiss", "arguments": {"id": "job0"}}
{"return": {}}
-{"execute": "blockdev-add", "arguments": {"driver": "file", "filename": "TEST_DIR/PID-t.qcow2", "node_name": "imgfile"}}
+{"execute": "blockdev-add", "arguments": {"driver": "file", "filename": "TEST_DIR/PID-t.qcow2", "node-name": "imgfile"}}
{"return": {}}
-{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "qcow2", "file": "imgfile", "size": 134217728}}}
+{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"driver": "qcow2", "file": "imgfile", "size": 134217728}}}
{"return": {}}
{"execute": "job-dismiss", "arguments": {"id": "job0"}}
{"return": {}}
@@ -24,12 +24,12 @@
=== Successful image creation (inline blockdev-add, explicit defaults) ===
-{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "file", "filename": "TEST_DIR/PID-t.qcow2", "nocow": false, "preallocation": "off", "size": 0}}}
+{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"driver": "file", "filename": "TEST_DIR/PID-t.qcow2", "nocow": false, "preallocation": "off", "size": 0}}}
{"return": {}}
{"execute": "job-dismiss", "arguments": {"id": "job0"}}
{"return": {}}
-{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"cluster-size": 65536, "driver": "qcow2", "file": {"driver": "file", "filename": "TEST_DIR/PID-t.qcow2"}, "lazy-refcounts": false, "preallocation": "off", "refcount-bits": 16, "size": 67108864, "version": "v3"}}}
+{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"cluster-size": 65536, "driver": "qcow2", "file": {"driver": "file", "filename": "TEST_DIR/PID-t.qcow2"}, "lazy-refcounts": false, "preallocation": "off", "refcount-bits": 16, "size": 67108864, "version": "v3"}}}
{"return": {}}
{"execute": "job-dismiss", "arguments": {"id": "job0"}}
{"return": {}}
@@ -46,12 +46,12 @@
=== Successful image creation (v3 non-default options) ===
-{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "file", "filename": "TEST_DIR/PID-t.qcow2", "nocow": true, "preallocation": "falloc", "size": 0}}}
+{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"driver": "file", "filename": "TEST_DIR/PID-t.qcow2", "nocow": true, "preallocation": "falloc", "size": 0}}}
{"return": {}}
{"execute": "job-dismiss", "arguments": {"id": "job0"}}
{"return": {}}
-{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"cluster-size": 2097152, "driver": "qcow2", "file": {"driver": "file", "filename": "TEST_DIR/PID-t.qcow2"}, "lazy-refcounts": true, "preallocation": "metadata", "refcount-bits": 1, "size": 33554432, "version": "v3"}}}
+{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"cluster-size": 2097152, "driver": "qcow2", "file": {"driver": "file", "filename": "TEST_DIR/PID-t.qcow2"}, "lazy-refcounts": true, "preallocation": "metadata", "refcount-bits": 1, "size": 33554432, "version": "v3"}}}
{"return": {}}
{"execute": "job-dismiss", "arguments": {"id": "job0"}}
{"return": {}}
@@ -68,12 +68,12 @@
=== Successful image creation (v2 non-default options) ===
-{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "file", "filename": "TEST_DIR/PID-t.qcow2", "size": 0}}}
+{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"driver": "file", "filename": "TEST_DIR/PID-t.qcow2", "size": 0}}}
{"return": {}}
{"execute": "job-dismiss", "arguments": {"id": "job0"}}
{"return": {}}
-{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"backing-file": "TEST_DIR/PID-t.qcow2.base", "backing-fmt": "qcow2", "cluster-size": 512, "driver": "qcow2", "file": {"driver": "file", "filename": "TEST_DIR/PID-t.qcow2"}, "size": 33554432, "version": "v2"}}}
+{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"backing-file": "TEST_DIR/PID-t.qcow2.base", "backing-fmt": "qcow2", "cluster-size": 512, "driver": "qcow2", "file": {"driver": "file", "filename": "TEST_DIR/PID-t.qcow2"}, "size": 33554432, "version": "v2"}}}
{"return": {}}
{"execute": "job-dismiss", "arguments": {"id": "job0"}}
{"return": {}}
@@ -90,7 +90,7 @@
=== Successful image creation (encrypted) ===
-{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "qcow2", "encrypt": {"cipher-alg": "twofish-128", "cipher-mode": "ctr", "format": "luks", "hash-alg": "sha1", "iter-time": 10, "ivgen-alg": "plain64", "ivgen-hash-alg": "md5", "key-secret": "keysec0"}, "file": {"driver": "file", "filename": "TEST_DIR/PID-t.qcow2"}, "size": 33554432}}}
+{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"driver": "qcow2", "encrypt": {"cipher-alg": "twofish-128", "cipher-mode": "ctr", "format": "luks", "hash-alg": "sha1", "iter-time": 10, "ivgen-alg": "plain64", "ivgen-hash-alg": "md5", "key-secret": "keysec0"}, "file": {"driver": "file", "filename": "TEST_DIR/PID-t.qcow2"}, "size": 33554432}}}
{"return": {}}
{"execute": "job-dismiss", "arguments": {"id": "job0"}}
{"return": {}}
@@ -144,111 +144,111 @@
=== Invalid BlockdevRef ===
-{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "qcow2", "file": "this doesn't exist", "size": 33554432}}}
+{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"driver": "qcow2", "file": "this doesn't exist", "size": 33554432}}}
{"return": {}}
Job failed: Cannot find device=this doesn't exist nor node_name=this doesn't exist
{"execute": "job-dismiss", "arguments": {"id": "job0"}}
{"return": {}}
=== Invalid sizes ===
-{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "qcow2", "file": "node0", "size": 1234}}}
+{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"driver": "qcow2", "file": "node0", "size": 1234}}}
{"return": {}}
Job failed: Image size must be a multiple of 512 bytes
{"execute": "job-dismiss", "arguments": {"id": "job0"}}
{"return": {}}
-{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "qcow2", "file": "node0", "size": 18446744073709551104}}}
+{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"driver": "qcow2", "file": "node0", "size": 18446744073709551104}}}
{"return": {}}
Job failed: Could not resize image: Image size cannot be negative
{"execute": "job-dismiss", "arguments": {"id": "job0"}}
{"return": {}}
-{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "qcow2", "file": "node0", "size": 9223372036854775808}}}
+{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"driver": "qcow2", "file": "node0", "size": 9223372036854775808}}}
{"return": {}}
Job failed: Could not resize image: Image size cannot be negative
{"execute": "job-dismiss", "arguments": {"id": "job0"}}
{"return": {}}
-{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "qcow2", "file": "node0", "size": 9223372036854775296}}}
+{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"driver": "qcow2", "file": "node0", "size": 9223372036854775296}}}
{"return": {}}
Job failed: Could not resize image: Failed to grow the L1 table: File too large
{"execute": "job-dismiss", "arguments": {"id": "job0"}}
{"return": {}}
=== Invalid version ===
-{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "qcow2", "file": "node0", "size": 67108864, "version": "v1"}}}
+{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"driver": "qcow2", "file": "node0", "size": 67108864, "version": "v1"}}}
{"error": {"class": "GenericError", "desc": "Invalid parameter 'v1'"}}
-{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "qcow2", "file": "node0", "lazy-refcounts": true, "size": 67108864, "version": "v2"}}}
+{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"driver": "qcow2", "file": "node0", "lazy-refcounts": true, "size": 67108864, "version": "v2"}}}
{"return": {}}
Job failed: Lazy refcounts only supported with compatibility level 1.1 and above (use version=v3 or greater)
{"execute": "job-dismiss", "arguments": {"id": "job0"}}
{"return": {}}
-{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "qcow2", "file": "node0", "refcount-bits": 8, "size": 67108864, "version": "v2"}}}
+{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"driver": "qcow2", "file": "node0", "refcount-bits": 8, "size": 67108864, "version": "v2"}}}
{"return": {}}
Job failed: Different refcount widths than 16 bits require compatibility level 1.1 or above (use version=v3 or greater)
{"execute": "job-dismiss", "arguments": {"id": "job0"}}
{"return": {}}
=== Invalid backing file options ===
-{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"backing-file": "/dev/null", "driver": "qcow2", "file": "node0", "preallocation": "full", "size": 67108864}}}
+{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"backing-file": "/dev/null", "driver": "qcow2", "file": "node0", "preallocation": "full", "size": 67108864}}}
{"return": {}}
Job failed: Backing file and preallocation cannot be used at the same time
{"execute": "job-dismiss", "arguments": {"id": "job0"}}
{"return": {}}
-{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"backing-fmt": "qcow2", "driver": "qcow2", "file": "node0", "size": 67108864}}}
+{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"backing-fmt": "qcow2", "driver": "qcow2", "file": "node0", "size": 67108864}}}
{"return": {}}
Job failed: Backing format cannot be used without backing file
{"execute": "job-dismiss", "arguments": {"id": "job0"}}
{"return": {}}
=== Invalid cluster size ===
-{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"cluster-size": 1234, "driver": "qcow2", "file": "node0", "size": 67108864}}}
+{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"cluster-size": 1234, "driver": "qcow2", "file": "node0", "size": 67108864}}}
{"return": {}}
Job failed: Cluster size must be a power of two between 512 and 2048k
{"execute": "job-dismiss", "arguments": {"id": "job0"}}
{"return": {}}
-{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"cluster-size": 128, "driver": "qcow2", "file": "node0", "size": 67108864}}}
+{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"cluster-size": 128, "driver": "qcow2", "file": "node0", "size": 67108864}}}
{"return": {}}
Job failed: Cluster size must be a power of two between 512 and 2048k
{"execute": "job-dismiss", "arguments": {"id": "job0"}}
{"return": {}}
-{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"cluster-size": 4194304, "driver": "qcow2", "file": "node0", "size": 67108864}}}
+{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"cluster-size": 4194304, "driver": "qcow2", "file": "node0", "size": 67108864}}}
{"return": {}}
Job failed: Cluster size must be a power of two between 512 and 2048k
{"execute": "job-dismiss", "arguments": {"id": "job0"}}
{"return": {}}
-{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"cluster-size": 0, "driver": "qcow2", "file": "node0", "size": 67108864}}}
+{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"cluster-size": 0, "driver": "qcow2", "file": "node0", "size": 67108864}}}
{"return": {}}
Job failed: Cluster size must be a power of two between 512 and 2048k
{"execute": "job-dismiss", "arguments": {"id": "job0"}}
{"return": {}}
-{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"cluster-size": 512, "driver": "qcow2", "file": "node0", "size": 281474976710656}}}
+{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"cluster-size": 512, "driver": "qcow2", "file": "node0", "size": 281474976710656}}}
{"return": {}}
Job failed: Could not resize image: Failed to grow the L1 table: File too large
{"execute": "job-dismiss", "arguments": {"id": "job0"}}
{"return": {}}
=== Invalid refcount width ===
-{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "qcow2", "file": "node0", "refcount-bits": 128, "size": 67108864}}}
+{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"driver": "qcow2", "file": "node0", "refcount-bits": 128, "size": 67108864}}}
{"return": {}}
Job failed: Refcount width must be a power of two and may not exceed 64 bits
{"execute": "job-dismiss", "arguments": {"id": "job0"}}
{"return": {}}
-{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "qcow2", "file": "node0", "refcount-bits": 0, "size": 67108864}}}
+{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"driver": "qcow2", "file": "node0", "refcount-bits": 0, "size": 67108864}}}
{"return": {}}
Job failed: Refcount width must be a power of two and may not exceed 64 bits
{"execute": "job-dismiss", "arguments": {"id": "job0"}}
{"return": {}}
-{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "qcow2", "file": "node0", "refcount-bits": 7, "size": 67108864}}}
+{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"driver": "qcow2", "file": "node0", "refcount-bits": 7, "size": 67108864}}}
{"return": {}}
Job failed: Refcount width must be a power of two and may not exceed 64 bits
{"execute": "job-dismiss", "arguments": {"id": "job0"}}
diff --git a/tests/qemu-iotests/207 b/tests/qemu-iotests/207
index c617ee7..dfd3c51 100755
--- a/tests/qemu-iotests/207
+++ b/tests/qemu-iotests/207
@@ -27,12 +27,16 @@
iotests.verify_image_format(supported_fmts=['raw'])
iotests.verify_protocol(supported=['ssh'])
-def filter_hash(msg):
- return re.sub('"hash": "[0-9a-f]+"', '"hash": HASH', msg)
+def filter_hash(qmsg):
+ def _filter(key, value):
+ if key == 'hash' and re.match('[0-9a-f]+', value):
+ return 'HASH'
+ return value
+ return iotests.filter_qmp(qmsg, _filter)
def blockdev_create(vm, options):
result = vm.qmp_log('blockdev-create', job_id='job0', options=options,
- filters=[iotests.filter_testfiles, filter_hash])
+ filters=[iotests.filter_qmp_testfiles, filter_hash])
if 'return' in result:
assert result['return'] == {}
diff --git a/tests/qemu-iotests/207.out b/tests/qemu-iotests/207.out
index 45ac7c2..568e861 100644
--- a/tests/qemu-iotests/207.out
+++ b/tests/qemu-iotests/207.out
@@ -1,6 +1,6 @@
=== Successful image creation (defaults) ===
-{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "ssh", "location": {"path": "TEST_DIR/PID-t.img", "server": {"host": "127.0.0.1", "port": "22"}}, "size": 4194304}}}
+{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"driver": "ssh", "location": {"path": "TEST_DIR/PID-t.img", "server": {"host": "127.0.0.1", "port": "22"}}, "size": 4194304}}}
{"return": {}}
{"execute": "job-dismiss", "arguments": {"id": "job0"}}
{"return": {}}
@@ -16,7 +16,7 @@
=== Test host-key-check options ===
-{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "ssh", "location": {"host-key-check": {"mode": "none"}, "path": "TEST_DIR/PID-t.img", "server": {"host": "127.0.0.1", "port": "22"}}, "size": 8388608}}}
+{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"driver": "ssh", "location": {"host-key-check": {"mode": "none"}, "path": "TEST_DIR/PID-t.img", "server": {"host": "127.0.0.1", "port": "22"}}, "size": 8388608}}}
{"return": {}}
{"execute": "job-dismiss", "arguments": {"id": "job0"}}
{"return": {}}
@@ -25,7 +25,7 @@
file format: IMGFMT
virtual size: 8.0M (8388608 bytes)
-{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "ssh", "location": {"host-key-check": {"mode": "known_hosts"}, "path": "TEST_DIR/PID-t.img", "server": {"host": "127.0.0.1", "port": "22"}}, "size": 4194304}}}
+{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"driver": "ssh", "location": {"host-key-check": {"mode": "known_hosts"}, "path": "TEST_DIR/PID-t.img", "server": {"host": "127.0.0.1", "port": "22"}}, "size": 4194304}}}
{"return": {}}
{"execute": "job-dismiss", "arguments": {"id": "job0"}}
{"return": {}}
@@ -34,13 +34,13 @@
file format: IMGFMT
virtual size: 4.0M (4194304 bytes)
-{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "ssh", "location": {"host-key-check": {"hash": "wrong", "mode": "hash", "type": "md5"}, "path": "TEST_DIR/PID-t.img", "server": {"host": "127.0.0.1", "port": "22"}}, "size": 2097152}}}
+{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"driver": "ssh", "location": {"host-key-check": {"hash": "wrong", "mode": "hash", "type": "md5"}, "path": "TEST_DIR/PID-t.img", "server": {"host": "127.0.0.1", "port": "22"}}, "size": 2097152}}}
{"return": {}}
Job failed: remote host key does not match host_key_check 'wrong'
{"execute": "job-dismiss", "arguments": {"id": "job0"}}
{"return": {}}
-{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "ssh", "location": {"host-key-check": {"hash": HASH, "mode": "hash", "type": "md5"}, "path": "TEST_DIR/PID-t.img", "server": {"host": "127.0.0.1", "port": "22"}}, "size": 8388608}}}
+{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"driver": "ssh", "location": {"host-key-check": {"hash": "HASH", "mode": "hash", "type": "md5"}, "path": "TEST_DIR/PID-t.img", "server": {"host": "127.0.0.1", "port": "22"}}, "size": 8388608}}}
{"return": {}}
{"execute": "job-dismiss", "arguments": {"id": "job0"}}
{"return": {}}
@@ -49,13 +49,13 @@
file format: IMGFMT
virtual size: 8.0M (8388608 bytes)
-{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "ssh", "location": {"host-key-check": {"hash": "wrong", "mode": "hash", "type": "sha1"}, "path": "TEST_DIR/PID-t.img", "server": {"host": "127.0.0.1", "port": "22"}}, "size": 2097152}}}
+{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"driver": "ssh", "location": {"host-key-check": {"hash": "wrong", "mode": "hash", "type": "sha1"}, "path": "TEST_DIR/PID-t.img", "server": {"host": "127.0.0.1", "port": "22"}}, "size": 2097152}}}
{"return": {}}
Job failed: remote host key does not match host_key_check 'wrong'
{"execute": "job-dismiss", "arguments": {"id": "job0"}}
{"return": {}}
-{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "ssh", "location": {"host-key-check": {"hash": HASH, "mode": "hash", "type": "sha1"}, "path": "TEST_DIR/PID-t.img", "server": {"host": "127.0.0.1", "port": "22"}}, "size": 4194304}}}
+{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"driver": "ssh", "location": {"host-key-check": {"hash": "HASH", "mode": "hash", "type": "sha1"}, "path": "TEST_DIR/PID-t.img", "server": {"host": "127.0.0.1", "port": "22"}}, "size": 4194304}}}
{"return": {}}
{"execute": "job-dismiss", "arguments": {"id": "job0"}}
{"return": {}}
@@ -66,13 +66,13 @@
=== Invalid path and user ===
-{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "ssh", "location": {"host-key-check": {"mode": "none"}, "path": "/this/is/not/an/existing/path", "server": {"host": "127.0.0.1", "port": "22"}}, "size": 4194304}}}
+{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"driver": "ssh", "location": {"host-key-check": {"mode": "none"}, "path": "/this/is/not/an/existing/path", "server": {"host": "127.0.0.1", "port": "22"}}, "size": 4194304}}}
{"return": {}}
Job failed: failed to open remote file '/this/is/not/an/existing/path': Failed opening remote file (libssh2 error code: -31)
{"execute": "job-dismiss", "arguments": {"id": "job0"}}
{"return": {}}
-{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "ssh", "location": {"host-key-check": {"mode": "none"}, "path": "TEST_DIR/PID-t.img", "server": {"host": "127.0.0.1", "port": "22"}, "user": "invalid user"}, "size": 4194304}}}
+{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"driver": "ssh", "location": {"host-key-check": {"mode": "none"}, "path": "TEST_DIR/PID-t.img", "server": {"host": "127.0.0.1", "port": "22"}, "user": "invalid user"}, "size": 4194304}}}
{"return": {}}
Job failed: failed to authenticate using publickey authentication and the identities held by your ssh-agent
{"execute": "job-dismiss", "arguments": {"id": "job0"}}
diff --git a/tests/qemu-iotests/210 b/tests/qemu-iotests/210
index d142841..565e3b7 100755
--- a/tests/qemu-iotests/210
+++ b/tests/qemu-iotests/210
@@ -27,7 +27,8 @@
iotests.verify_protocol(supported=['file'])
def blockdev_create(vm, options):
- result = vm.qmp_log('blockdev-create', job_id='job0', options=options)
+ result = vm.qmp_log('blockdev-create', job_id='job0', options=options,
+ filters=[iotests.filter_qmp_testfiles])
if 'return' in result:
assert result['return'] == {}
@@ -53,7 +54,7 @@
'size': 0 })
vm.qmp_log('blockdev-add', driver='file', filename=disk_path,
- node_name='imgfile')
+ node_name='imgfile', filters=[iotests.filter_qmp_testfiles])
blockdev_create(vm, { 'driver': imgfmt,
'file': 'imgfile',
diff --git a/tests/qemu-iotests/210.out b/tests/qemu-iotests/210.out
index 923cb05..a3692ce 100644
--- a/tests/qemu-iotests/210.out
+++ b/tests/qemu-iotests/210.out
@@ -1,13 +1,13 @@
=== Successful image creation (defaults) ===
-{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "file", "filename": "TEST_DIR/PID-t.luks", "size": 0}}}
+{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"driver": "file", "filename": "TEST_DIR/PID-t.luks", "size": 0}}}
{"return": {}}
{"execute": "job-dismiss", "arguments": {"id": "job0"}}
{"return": {}}
-{"execute": "blockdev-add", "arguments": {"driver": "file", "filename": "TEST_DIR/PID-t.luks", "node_name": "imgfile"}}
+{"execute": "blockdev-add", "arguments": {"driver": "file", "filename": "TEST_DIR/PID-t.luks", "node-name": "imgfile"}}
{"return": {}}
-{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "luks", "file": "imgfile", "iter-time": 10, "key-secret": "keysec0", "size": 134217728}}}
+{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"driver": "luks", "file": "imgfile", "iter-time": 10, "key-secret": "keysec0", "size": 134217728}}}
{"return": {}}
{"execute": "job-dismiss", "arguments": {"id": "job0"}}
{"return": {}}
@@ -54,12 +54,12 @@
=== Successful image creation (with non-default options) ===
-{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "file", "filename": "TEST_DIR/PID-t.luks", "size": 0}}}
+{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"driver": "file", "filename": "TEST_DIR/PID-t.luks", "size": 0}}}
{"return": {}}
{"execute": "job-dismiss", "arguments": {"id": "job0"}}
{"return": {}}
-{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"cipher-alg": "twofish-128", "cipher-mode": "ctr", "driver": "luks", "file": {"driver": "file", "filename": "TEST_DIR/PID-t.luks"}, "hash-alg": "sha1", "iter-time": 10, "ivgen-alg": "plain64", "ivgen-hash-alg": "md5", "key-secret": "keysec0", "size": 67108864}}}
+{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"cipher-alg": "twofish-128", "cipher-mode": "ctr", "driver": "luks", "file": {"driver": "file", "filename": "TEST_DIR/PID-t.luks"}, "hash-alg": "sha1", "iter-time": 10, "ivgen-alg": "plain64", "ivgen-hash-alg": "md5", "key-secret": "keysec0", "size": 67108864}}}
{"return": {}}
{"execute": "job-dismiss", "arguments": {"id": "job0"}}
{"return": {}}
@@ -106,7 +106,7 @@
=== Invalid BlockdevRef ===
-{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "luks", "file": "this doesn't exist", "size": 67108864}}}
+{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"driver": "luks", "file": "this doesn't exist", "size": 67108864}}}
{"return": {}}
Job failed: Cannot find device=this doesn't exist nor node_name=this doesn't exist
{"execute": "job-dismiss", "arguments": {"id": "job0"}}
@@ -114,7 +114,7 @@
=== Zero size ===
-{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "luks", "file": "node0", "iter-time": 10, "key-secret": "keysec0", "size": 0}}}
+{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"driver": "luks", "file": "node0", "iter-time": 10, "key-secret": "keysec0", "size": 0}}}
{"return": {}}
{"execute": "job-dismiss", "arguments": {"id": "job0"}}
{"return": {}}
@@ -161,19 +161,19 @@
=== Invalid sizes ===
-{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "luks", "file": "node0", "key-secret": "keysec0", "size": 18446744073709551104}}}
+{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"driver": "luks", "file": "node0", "key-secret": "keysec0", "size": 18446744073709551104}}}
{"return": {}}
Job failed: The requested file size is too large
{"execute": "job-dismiss", "arguments": {"id": "job0"}}
{"return": {}}
-{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "luks", "file": "node0", "key-secret": "keysec0", "size": 9223372036854775808}}}
+{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"driver": "luks", "file": "node0", "key-secret": "keysec0", "size": 9223372036854775808}}}
{"return": {}}
Job failed: The requested file size is too large
{"execute": "job-dismiss", "arguments": {"id": "job0"}}
{"return": {}}
-{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "luks", "file": "node0", "key-secret": "keysec0", "size": 9223372036854775296}}}
+{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"driver": "luks", "file": "node0", "key-secret": "keysec0", "size": 9223372036854775296}}}
{"return": {}}
Job failed: The requested file size is too large
{"execute": "job-dismiss", "arguments": {"id": "job0"}}
@@ -181,13 +181,13 @@
=== Resize image with invalid sizes ===
-{"execute": "block_resize", "arguments": {"node_name": "node1", "size": 9223372036854775296}}
+{"execute": "block_resize", "arguments": {"node-name": "node1", "size": 9223372036854775296}}
{"error": {"class": "GenericError", "desc": "The requested file size is too large"}}
-{"execute": "block_resize", "arguments": {"node_name": "node1", "size": 9223372036854775808}}
+{"execute": "block_resize", "arguments": {"node-name": "node1", "size": 9223372036854775808}}
{"error": {"class": "GenericError", "desc": "Invalid parameter type for 'size', expected: integer"}}
-{"execute": "block_resize", "arguments": {"node_name": "node1", "size": 18446744073709551104}}
+{"execute": "block_resize", "arguments": {"node-name": "node1", "size": 18446744073709551104}}
{"error": {"class": "GenericError", "desc": "Invalid parameter type for 'size', expected: integer"}}
-{"execute": "block_resize", "arguments": {"node_name": "node1", "size": -9223372036854775808}}
+{"execute": "block_resize", "arguments": {"node-name": "node1", "size": -9223372036854775808}}
{"error": {"class": "GenericError", "desc": "Parameter 'size' expects a >0 size"}}
image: json:{"driver": "IMGFMT", "file": {"driver": "file", "filename": "TEST_IMG"}, "key-secret": "keysec0"}
file format: IMGFMT
diff --git a/tests/qemu-iotests/211 b/tests/qemu-iotests/211
index 7b7985d..6afc894 100755
--- a/tests/qemu-iotests/211
+++ b/tests/qemu-iotests/211
@@ -27,11 +27,14 @@
iotests.verify_protocol(supported=['file'])
def blockdev_create(vm, options):
- result = vm.qmp_log('blockdev-create', job_id='job0', options=options)
+ result = vm.qmp_log('blockdev-create', job_id='job0', options=options,
+ filters=[iotests.filter_qmp_testfiles])
if 'return' in result:
assert result['return'] == {}
- vm.run_job('job0')
+ error = vm.run_job('job0')
+ if error and 'Could not allocate bmap' in error:
+ iotests.notrun('Insufficient memory')
iotests.log("")
with iotests.FilePath('t.vdi') as disk_path, \
@@ -51,7 +54,7 @@
'size': 0 })
vm.qmp_log('blockdev-add', driver='file', filename=disk_path,
- node_name='imgfile')
+ node_name='imgfile', filters=[iotests.filter_qmp_testfiles])
blockdev_create(vm, { 'driver': imgfmt,
'file': 'imgfile',
diff --git a/tests/qemu-iotests/211.out b/tests/qemu-iotests/211.out
index eebb0ea..682adc2 100644
--- a/tests/qemu-iotests/211.out
+++ b/tests/qemu-iotests/211.out
@@ -1,13 +1,13 @@
=== Successful image creation (defaults) ===
-{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "file", "filename": "TEST_DIR/PID-t.vdi", "size": 0}}}
+{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"driver": "file", "filename": "TEST_DIR/PID-t.vdi", "size": 0}}}
{"return": {}}
{"execute": "job-dismiss", "arguments": {"id": "job0"}}
{"return": {}}
-{"execute": "blockdev-add", "arguments": {"driver": "file", "filename": "TEST_DIR/PID-t.vdi", "node_name": "imgfile"}}
+{"execute": "blockdev-add", "arguments": {"driver": "file", "filename": "TEST_DIR/PID-t.vdi", "node-name": "imgfile"}}
{"return": {}}
-{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "vdi", "file": "imgfile", "size": 134217728}}}
+{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"driver": "vdi", "file": "imgfile", "size": 134217728}}}
{"return": {}}
{"execute": "job-dismiss", "arguments": {"id": "job0"}}
{"return": {}}
@@ -21,12 +21,12 @@
=== Successful image creation (explicit defaults) ===
-{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "file", "filename": "TEST_DIR/PID-t.vdi", "size": 0}}}
+{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"driver": "file", "filename": "TEST_DIR/PID-t.vdi", "size": 0}}}
{"return": {}}
{"execute": "job-dismiss", "arguments": {"id": "job0"}}
{"return": {}}
-{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "vdi", "file": {"driver": "file", "filename": "TEST_DIR/PID-t.vdi"}, "preallocation": "off", "size": 67108864}}}
+{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"driver": "vdi", "file": {"driver": "file", "filename": "TEST_DIR/PID-t.vdi"}, "preallocation": "off", "size": 67108864}}}
{"return": {}}
{"execute": "job-dismiss", "arguments": {"id": "job0"}}
{"return": {}}
@@ -40,12 +40,12 @@
=== Successful image creation (with non-default options) ===
-{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "file", "filename": "TEST_DIR/PID-t.vdi", "size": 0}}}
+{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"driver": "file", "filename": "TEST_DIR/PID-t.vdi", "size": 0}}}
{"return": {}}
{"execute": "job-dismiss", "arguments": {"id": "job0"}}
{"return": {}}
-{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "vdi", "file": {"driver": "file", "filename": "TEST_DIR/PID-t.vdi"}, "preallocation": "metadata", "size": 33554432}}}
+{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"driver": "vdi", "file": {"driver": "file", "filename": "TEST_DIR/PID-t.vdi"}, "preallocation": "metadata", "size": 33554432}}}
{"return": {}}
{"execute": "job-dismiss", "arguments": {"id": "job0"}}
{"return": {}}
@@ -60,7 +60,7 @@
=== Invalid BlockdevRef ===
-{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "vdi", "file": "this doesn't exist", "size": 33554432}}}
+{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"driver": "vdi", "file": "this doesn't exist", "size": 33554432}}}
{"return": {}}
Job failed: Cannot find device=this doesn't exist nor node_name=this doesn't exist
{"execute": "job-dismiss", "arguments": {"id": "job0"}}
@@ -68,7 +68,7 @@
=== Zero size ===
-{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "vdi", "file": "node0", "size": 0}}}
+{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"driver": "vdi", "file": "node0", "size": 0}}}
{"return": {}}
{"execute": "job-dismiss", "arguments": {"id": "job0"}}
{"return": {}}
@@ -80,7 +80,7 @@
=== Maximum size ===
-{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "vdi", "file": "node0", "size": 562949819203584}}}
+{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"driver": "vdi", "file": "node0", "size": 562949819203584}}}
{"return": {}}
{"execute": "job-dismiss", "arguments": {"id": "job0"}}
{"return": {}}
@@ -92,19 +92,19 @@
=== Invalid sizes ===
-{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "vdi", "file": "node0", "size": 18446744073709551104}}}
+{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"driver": "vdi", "file": "node0", "size": 18446744073709551104}}}
{"return": {}}
Job failed: Unsupported VDI image size (size is 0xfffffffffffffe00, max supported is 0x1fffff8000000)
{"execute": "job-dismiss", "arguments": {"id": "job0"}}
{"return": {}}
-{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "vdi", "file": "node0", "size": 9223372036854775808}}}
+{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"driver": "vdi", "file": "node0", "size": 9223372036854775808}}}
{"return": {}}
Job failed: Unsupported VDI image size (size is 0x8000000000000000, max supported is 0x1fffff8000000)
{"execute": "job-dismiss", "arguments": {"id": "job0"}}
{"return": {}}
-{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "vdi", "file": "node0", "size": 562949819203585}}}
+{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"driver": "vdi", "file": "node0", "size": 562949819203585}}}
{"return": {}}
Job failed: Unsupported VDI image size (size is 0x1fffff8000001, max supported is 0x1fffff8000000)
{"execute": "job-dismiss", "arguments": {"id": "job0"}}
diff --git a/tests/qemu-iotests/212 b/tests/qemu-iotests/212
index 95c8810..42b74f2 100755
--- a/tests/qemu-iotests/212
+++ b/tests/qemu-iotests/212
@@ -27,7 +27,8 @@
iotests.verify_protocol(supported=['file'])
def blockdev_create(vm, options):
- result = vm.qmp_log('blockdev-create', job_id='job0', options=options)
+ result = vm.qmp_log('blockdev-create', job_id='job0', options=options,
+ filters=[iotests.filter_qmp_testfiles])
if 'return' in result:
assert result['return'] == {}
@@ -51,7 +52,7 @@
'size': 0 })
vm.qmp_log('blockdev-add', driver='file', filename=disk_path,
- node_name='imgfile')
+ node_name='imgfile', filters=[iotests.filter_qmp_testfiles])
blockdev_create(vm, { 'driver': imgfmt,
'file': 'imgfile',
diff --git a/tests/qemu-iotests/212.out b/tests/qemu-iotests/212.out
index 01da467..2281072 100644
--- a/tests/qemu-iotests/212.out
+++ b/tests/qemu-iotests/212.out
@@ -1,13 +1,13 @@
=== Successful image creation (defaults) ===
-{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "file", "filename": "TEST_DIR/PID-t.parallels", "size": 0}}}
+{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"driver": "file", "filename": "TEST_DIR/PID-t.parallels", "size": 0}}}
{"return": {}}
{"execute": "job-dismiss", "arguments": {"id": "job0"}}
{"return": {}}
-{"execute": "blockdev-add", "arguments": {"driver": "file", "filename": "TEST_DIR/PID-t.parallels", "node_name": "imgfile"}}
+{"execute": "blockdev-add", "arguments": {"driver": "file", "filename": "TEST_DIR/PID-t.parallels", "node-name": "imgfile"}}
{"return": {}}
-{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "parallels", "file": "imgfile", "size": 134217728}}}
+{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"driver": "parallels", "file": "imgfile", "size": 134217728}}}
{"return": {}}
{"execute": "job-dismiss", "arguments": {"id": "job0"}}
{"return": {}}
@@ -18,12 +18,12 @@
=== Successful image creation (explicit defaults) ===
-{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "file", "filename": "TEST_DIR/PID-t.parallels", "size": 0}}}
+{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"driver": "file", "filename": "TEST_DIR/PID-t.parallels", "size": 0}}}
{"return": {}}
{"execute": "job-dismiss", "arguments": {"id": "job0"}}
{"return": {}}
-{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"cluster-size": 1048576, "driver": "parallels", "file": {"driver": "file", "filename": "TEST_DIR/PID-t.parallels"}, "size": 67108864}}}
+{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"cluster-size": 1048576, "driver": "parallels", "file": {"driver": "file", "filename": "TEST_DIR/PID-t.parallels"}, "size": 67108864}}}
{"return": {}}
{"execute": "job-dismiss", "arguments": {"id": "job0"}}
{"return": {}}
@@ -34,12 +34,12 @@
=== Successful image creation (with non-default options) ===
-{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "file", "filename": "TEST_DIR/PID-t.parallels", "size": 0}}}
+{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"driver": "file", "filename": "TEST_DIR/PID-t.parallels", "size": 0}}}
{"return": {}}
{"execute": "job-dismiss", "arguments": {"id": "job0"}}
{"return": {}}
-{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"cluster-size": 65536, "driver": "parallels", "file": {"driver": "file", "filename": "TEST_DIR/PID-t.parallels"}, "size": 33554432}}}
+{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"cluster-size": 65536, "driver": "parallels", "file": {"driver": "file", "filename": "TEST_DIR/PID-t.parallels"}, "size": 33554432}}}
{"return": {}}
{"execute": "job-dismiss", "arguments": {"id": "job0"}}
{"return": {}}
@@ -50,7 +50,7 @@
=== Invalid BlockdevRef ===
-{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "parallels", "file": "this doesn't exist", "size": 33554432}}}
+{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"driver": "parallels", "file": "this doesn't exist", "size": 33554432}}}
{"return": {}}
Job failed: Cannot find device=this doesn't exist nor node_name=this doesn't exist
{"execute": "job-dismiss", "arguments": {"id": "job0"}}
@@ -58,7 +58,7 @@
=== Zero size ===
-{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "parallels", "file": "node0", "size": 0}}}
+{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"driver": "parallels", "file": "node0", "size": 0}}}
{"return": {}}
{"execute": "job-dismiss", "arguments": {"id": "job0"}}
{"return": {}}
@@ -69,7 +69,7 @@
=== Maximum size ===
-{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "parallels", "file": "node0", "size": 4503599627369984}}}
+{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"driver": "parallels", "file": "node0", "size": 4503599627369984}}}
{"return": {}}
{"execute": "job-dismiss", "arguments": {"id": "job0"}}
{"return": {}}
@@ -80,31 +80,31 @@
=== Invalid sizes ===
-{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "parallels", "file": "node0", "size": 1234}}}
+{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"driver": "parallels", "file": "node0", "size": 1234}}}
{"return": {}}
Job failed: Image size must be a multiple of 512 bytes
{"execute": "job-dismiss", "arguments": {"id": "job0"}}
{"return": {}}
-{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "parallels", "file": "node0", "size": 18446744073709551104}}}
+{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"driver": "parallels", "file": "node0", "size": 18446744073709551104}}}
{"return": {}}
Job failed: Image size is too large for this cluster size
{"execute": "job-dismiss", "arguments": {"id": "job0"}}
{"return": {}}
-{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "parallels", "file": "node0", "size": 9223372036854775808}}}
+{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"driver": "parallels", "file": "node0", "size": 9223372036854775808}}}
{"return": {}}
Job failed: Image size is too large for this cluster size
{"execute": "job-dismiss", "arguments": {"id": "job0"}}
{"return": {}}
-{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "parallels", "file": "node0", "size": 9223372036854775296}}}
+{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"driver": "parallels", "file": "node0", "size": 9223372036854775296}}}
{"return": {}}
Job failed: Image size is too large for this cluster size
{"execute": "job-dismiss", "arguments": {"id": "job0"}}
{"return": {}}
-{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "parallels", "file": "node0", "size": 4503599627370497}}}
+{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"driver": "parallels", "file": "node0", "size": 4503599627370497}}}
{"return": {}}
Job failed: Image size is too large for this cluster size
{"execute": "job-dismiss", "arguments": {"id": "job0"}}
@@ -112,43 +112,43 @@
=== Invalid cluster size ===
-{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"cluster-size": 1234, "driver": "parallels", "file": "node0", "size": 67108864}}}
+{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"cluster-size": 1234, "driver": "parallels", "file": "node0", "size": 67108864}}}
{"return": {}}
Job failed: Cluster size must be a multiple of 512 bytes
{"execute": "job-dismiss", "arguments": {"id": "job0"}}
{"return": {}}
-{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"cluster-size": 128, "driver": "parallels", "file": "node0", "size": 67108864}}}
+{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"cluster-size": 128, "driver": "parallels", "file": "node0", "size": 67108864}}}
{"return": {}}
Job failed: Cluster size must be a multiple of 512 bytes
{"execute": "job-dismiss", "arguments": {"id": "job0"}}
{"return": {}}
-{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"cluster-size": 4294967296, "driver": "parallels", "file": "node0", "size": 67108864}}}
+{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"cluster-size": 4294967296, "driver": "parallels", "file": "node0", "size": 67108864}}}
{"return": {}}
Job failed: Cluster size is too large
{"execute": "job-dismiss", "arguments": {"id": "job0"}}
{"return": {}}
-{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"cluster-size": 9223372036854775808, "driver": "parallels", "file": "node0", "size": 67108864}}}
+{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"cluster-size": 9223372036854775808, "driver": "parallels", "file": "node0", "size": 67108864}}}
{"return": {}}
Job failed: Cluster size is too large
{"execute": "job-dismiss", "arguments": {"id": "job0"}}
{"return": {}}
-{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"cluster-size": 18446744073709551104, "driver": "parallels", "file": "node0", "size": 67108864}}}
+{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"cluster-size": 18446744073709551104, "driver": "parallels", "file": "node0", "size": 67108864}}}
{"return": {}}
Job failed: Cluster size is too large
{"execute": "job-dismiss", "arguments": {"id": "job0"}}
{"return": {}}
-{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"cluster-size": 0, "driver": "parallels", "file": "node0", "size": 67108864}}}
+{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"cluster-size": 0, "driver": "parallels", "file": "node0", "size": 67108864}}}
{"return": {}}
Job failed: Image size is too large for this cluster size
{"execute": "job-dismiss", "arguments": {"id": "job0"}}
{"return": {}}
-{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"cluster-size": 512, "driver": "parallels", "file": "node0", "size": 281474976710656}}}
+{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"cluster-size": 512, "driver": "parallels", "file": "node0", "size": 281474976710656}}}
{"return": {}}
Job failed: Image size is too large for this cluster size
{"execute": "job-dismiss", "arguments": {"id": "job0"}}
diff --git a/tests/qemu-iotests/213 b/tests/qemu-iotests/213
index 4054439..5604f3c 100755
--- a/tests/qemu-iotests/213
+++ b/tests/qemu-iotests/213
@@ -27,7 +27,8 @@
iotests.verify_protocol(supported=['file'])
def blockdev_create(vm, options):
- result = vm.qmp_log('blockdev-create', job_id='job0', options=options)
+ result = vm.qmp_log('blockdev-create', job_id='job0', options=options,
+ filters=[iotests.filter_qmp_testfiles])
if 'return' in result:
assert result['return'] == {}
@@ -51,7 +52,7 @@
'size': 0 })
vm.qmp_log('blockdev-add', driver='file', filename=disk_path,
- node_name='imgfile')
+ node_name='imgfile', filters=[iotests.filter_qmp_testfiles])
blockdev_create(vm, { 'driver': imgfmt,
'file': 'imgfile',
diff --git a/tests/qemu-iotests/213.out b/tests/qemu-iotests/213.out
index 0c9d65b..169083e 100644
--- a/tests/qemu-iotests/213.out
+++ b/tests/qemu-iotests/213.out
@@ -1,13 +1,13 @@
=== Successful image creation (defaults) ===
-{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "file", "filename": "TEST_DIR/PID-t.vhdx", "size": 0}}}
+{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"driver": "file", "filename": "TEST_DIR/PID-t.vhdx", "size": 0}}}
{"return": {}}
{"execute": "job-dismiss", "arguments": {"id": "job0"}}
{"return": {}}
-{"execute": "blockdev-add", "arguments": {"driver": "file", "filename": "TEST_DIR/PID-t.vhdx", "node_name": "imgfile"}}
+{"execute": "blockdev-add", "arguments": {"driver": "file", "filename": "TEST_DIR/PID-t.vhdx", "node-name": "imgfile"}}
{"return": {}}
-{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "vhdx", "file": "imgfile", "size": 134217728}}}
+{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"driver": "vhdx", "file": "imgfile", "size": 134217728}}}
{"return": {}}
{"execute": "job-dismiss", "arguments": {"id": "job0"}}
{"return": {}}
@@ -19,12 +19,12 @@
=== Successful image creation (explicit defaults) ===
-{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "file", "filename": "TEST_DIR/PID-t.vhdx", "size": 0}}}
+{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"driver": "file", "filename": "TEST_DIR/PID-t.vhdx", "size": 0}}}
{"return": {}}
{"execute": "job-dismiss", "arguments": {"id": "job0"}}
{"return": {}}
-{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"block-size": 8388608, "block-state-zero": true, "driver": "vhdx", "file": {"driver": "file", "filename": "TEST_DIR/PID-t.vhdx"}, "log-size": 1048576, "size": 67108864, "subformat": "dynamic"}}}
+{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"block-size": 8388608, "block-state-zero": true, "driver": "vhdx", "file": {"driver": "file", "filename": "TEST_DIR/PID-t.vhdx"}, "log-size": 1048576, "size": 67108864, "subformat": "dynamic"}}}
{"return": {}}
{"execute": "job-dismiss", "arguments": {"id": "job0"}}
{"return": {}}
@@ -36,12 +36,12 @@
=== Successful image creation (with non-default options) ===
-{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "file", "filename": "TEST_DIR/PID-t.vhdx", "size": 0}}}
+{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"driver": "file", "filename": "TEST_DIR/PID-t.vhdx", "size": 0}}}
{"return": {}}
{"execute": "job-dismiss", "arguments": {"id": "job0"}}
{"return": {}}
-{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"block-size": 268435456, "block-state-zero": false, "driver": "vhdx", "file": {"driver": "file", "filename": "TEST_DIR/PID-t.vhdx"}, "log-size": 8388608, "size": 33554432, "subformat": "fixed"}}}
+{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"block-size": 268435456, "block-state-zero": false, "driver": "vhdx", "file": {"driver": "file", "filename": "TEST_DIR/PID-t.vhdx"}, "log-size": 8388608, "size": 33554432, "subformat": "fixed"}}}
{"return": {}}
{"execute": "job-dismiss", "arguments": {"id": "job0"}}
{"return": {}}
@@ -53,7 +53,7 @@
=== Invalid BlockdevRef ===
-{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "vhdx", "file": "this doesn't exist", "size": 33554432}}}
+{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"driver": "vhdx", "file": "this doesn't exist", "size": 33554432}}}
{"return": {}}
Job failed: Cannot find device=this doesn't exist nor node_name=this doesn't exist
{"execute": "job-dismiss", "arguments": {"id": "job0"}}
@@ -61,7 +61,7 @@
=== Zero size ===
-{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "vhdx", "file": "node0", "size": 0}}}
+{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"driver": "vhdx", "file": "node0", "size": 0}}}
{"return": {}}
{"execute": "job-dismiss", "arguments": {"id": "job0"}}
{"return": {}}
@@ -73,7 +73,7 @@
=== Maximum size ===
-{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "vhdx", "file": "node0", "size": 70368744177664}}}
+{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"driver": "vhdx", "file": "node0", "size": 70368744177664}}}
{"return": {}}
{"execute": "job-dismiss", "arguments": {"id": "job0"}}
{"return": {}}
@@ -85,25 +85,25 @@
=== Invalid sizes ===
-{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "vhdx", "file": "node0", "size": 18446744073709551104}}}
+{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"driver": "vhdx", "file": "node0", "size": 18446744073709551104}}}
{"return": {}}
Job failed: Image size too large; max of 64TB
{"execute": "job-dismiss", "arguments": {"id": "job0"}}
{"return": {}}
-{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "vhdx", "file": "node0", "size": 9223372036854775808}}}
+{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"driver": "vhdx", "file": "node0", "size": 9223372036854775808}}}
{"return": {}}
Job failed: Image size too large; max of 64TB
{"execute": "job-dismiss", "arguments": {"id": "job0"}}
{"return": {}}
-{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "vhdx", "file": "node0", "size": 9223372036854775296}}}
+{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"driver": "vhdx", "file": "node0", "size": 9223372036854775296}}}
{"return": {}}
Job failed: Image size too large; max of 64TB
{"execute": "job-dismiss", "arguments": {"id": "job0"}}
{"return": {}}
-{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "vhdx", "file": "node0", "size": 70368744177665}}}
+{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"driver": "vhdx", "file": "node0", "size": 70368744177665}}}
{"return": {}}
Job failed: Image size too large; max of 64TB
{"execute": "job-dismiss", "arguments": {"id": "job0"}}
@@ -111,31 +111,31 @@
=== Invalid block size ===
-{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"block-size": 1234567, "driver": "vhdx", "file": "node0", "size": 67108864}}}
+{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"block-size": 1234567, "driver": "vhdx", "file": "node0", "size": 67108864}}}
{"return": {}}
Job failed: Block size must be a multiple of 1 MB
{"execute": "job-dismiss", "arguments": {"id": "job0"}}
{"return": {}}
-{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"block-size": 128, "driver": "vhdx", "file": "node0", "size": 67108864}}}
+{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"block-size": 128, "driver": "vhdx", "file": "node0", "size": 67108864}}}
{"return": {}}
Job failed: Block size must be a multiple of 1 MB
{"execute": "job-dismiss", "arguments": {"id": "job0"}}
{"return": {}}
-{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"block-size": 3145728, "driver": "vhdx", "file": "node0", "size": 67108864}}}
+{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"block-size": 3145728, "driver": "vhdx", "file": "node0", "size": 67108864}}}
{"return": {}}
Job failed: Block size must be a power of two
{"execute": "job-dismiss", "arguments": {"id": "job0"}}
{"return": {}}
-{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"block-size": 536870912, "driver": "vhdx", "file": "node0", "size": 67108864}}}
+{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"block-size": 536870912, "driver": "vhdx", "file": "node0", "size": 67108864}}}
{"return": {}}
Job failed: Block size must not exceed 268435456
{"execute": "job-dismiss", "arguments": {"id": "job0"}}
{"return": {}}
-{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"block-size": 0, "driver": "vhdx", "file": "node0", "size": 67108864}}}
+{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"block-size": 0, "driver": "vhdx", "file": "node0", "size": 67108864}}}
{"return": {}}
Job failed: Block size must be a multiple of 1 MB
{"execute": "job-dismiss", "arguments": {"id": "job0"}}
@@ -143,25 +143,25 @@
=== Invalid log size ===
-{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "vhdx", "file": "node0", "log-size": 1234567, "size": 67108864}}}
+{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"driver": "vhdx", "file": "node0", "log-size": 1234567, "size": 67108864}}}
{"return": {}}
Job failed: Log size must be a multiple of 1 MB
{"execute": "job-dismiss", "arguments": {"id": "job0"}}
{"return": {}}
-{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "vhdx", "file": "node0", "log-size": 128, "size": 67108864}}}
+{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"driver": "vhdx", "file": "node0", "log-size": 128, "size": 67108864}}}
{"return": {}}
Job failed: Log size must be a multiple of 1 MB
{"execute": "job-dismiss", "arguments": {"id": "job0"}}
{"return": {}}
-{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "vhdx", "file": "node0", "log-size": 4294967296, "size": 67108864}}}
+{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"driver": "vhdx", "file": "node0", "log-size": 4294967296, "size": 67108864}}}
{"return": {}}
Job failed: Log size must be smaller than 4 GB
{"execute": "job-dismiss", "arguments": {"id": "job0"}}
{"return": {}}
-{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "vhdx", "file": "node0", "log-size": 0, "size": 67108864}}}
+{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"driver": "vhdx", "file": "node0", "log-size": 0, "size": 67108864}}}
{"return": {}}
Job failed: Log size must be a multiple of 1 MB
{"execute": "job-dismiss", "arguments": {"id": "job0"}}
diff --git a/tests/qemu-iotests/224 b/tests/qemu-iotests/224
new file mode 100755
index 0000000..b4dfaa6
--- /dev/null
+++ b/tests/qemu-iotests/224
@@ -0,0 +1,139 @@
+#!/usr/bin/env python
+#
+# Test json:{} filenames with qemu-internal BDSs
+# (the one of commit, to be precise)
+#
+# Copyright (C) 2018 Red Hat, Inc.
+#
+# 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: Max Reitz <mreitz@redhat.com>
+
+import iotests
+from iotests import log, qemu_img, qemu_io_silent, filter_qmp_testfiles, \
+ filter_qmp_imgfmt
+import json
+
+# Need backing file support (for arbitrary backing formats)
+iotests.verify_image_format(supported_fmts=['qcow2', 'qcow', 'qed'])
+iotests.verify_platform(['linux'])
+
+
+# There are two variations of this test:
+# (1) We do not set filter_node_name. In that case, the commit_top
+# driver should not appear anywhere.
+# (2) We do set filter_node_name. In that case, it should appear.
+#
+# This for loop executes both.
+for filter_node_name in False, True:
+ log('')
+ log('--- filter_node_name: %s ---' % filter_node_name)
+ log('')
+
+ with iotests.FilePath('base.img') as base_img_path, \
+ iotests.FilePath('mid.img') as mid_img_path, \
+ iotests.FilePath('top.img') as top_img_path, \
+ iotests.VM() as vm:
+
+ assert qemu_img('create', '-f', iotests.imgfmt,
+ base_img_path, '64M') == 0
+ assert qemu_img('create', '-f', iotests.imgfmt, '-b', base_img_path,
+ mid_img_path) == 0
+ assert qemu_img('create', '-f', iotests.imgfmt, '-b', mid_img_path,
+ top_img_path) == 0
+
+ # Something to commit
+ assert qemu_io_silent(mid_img_path, '-c', 'write -P 1 0 1M') == 0
+
+ vm.launch()
+
+ # Change the bottom-most image's backing file (to null-co://)
+ # to enforce json:{} filenames
+ vm.qmp_log('blockdev-add',
+ node_name='top',
+ driver=iotests.imgfmt,
+ file={
+ 'driver': 'file',
+ 'filename': top_img_path
+ },
+ backing={
+ 'node-name': 'mid',
+ 'driver': iotests.imgfmt,
+ 'file': {
+ 'driver': 'file',
+ 'filename': mid_img_path
+ },
+ 'backing': {
+ 'node-name': 'base',
+ 'driver': iotests.imgfmt,
+ 'file': {
+ 'driver': 'file',
+ 'filename': base_img_path
+ },
+ 'backing': {
+ 'driver': 'null-co'
+ }
+ }
+ },
+ filters=[filter_qmp_testfiles, filter_qmp_imgfmt])
+
+ # As long as block-commit does not accept node names, we have to
+ # get our mid/base filenames here
+ mid_name = vm.node_info('mid')['image']['filename']
+ base_name = vm.node_info('base')['image']['filename']
+
+ assert mid_name[:5] == 'json:'
+ assert base_name[:5] == 'json:'
+
+ # Start the block job
+ if filter_node_name:
+ vm.qmp_log('block-commit',
+ job_id='commit',
+ device='top',
+ filter_node_name='filter_node',
+ top=mid_name,
+ base=base_name,
+ speed=1,
+ filters=[filter_qmp_testfiles, filter_qmp_imgfmt])
+ else:
+ vm.qmp_log('block-commit',
+ job_id='commit',
+ device='top',
+ top=mid_name,
+ base=base_name,
+ speed=1,
+ filters=[filter_qmp_testfiles, filter_qmp_imgfmt])
+
+ vm.qmp_log('job-pause', id='commit')
+
+ # Get and parse top's json:{} filename
+ top_name = vm.node_info('top')['image']['filename']
+
+ vm.shutdown()
+
+ assert top_name[:5] == 'json:'
+ top_options = json.loads(top_name[5:])
+
+ if filter_node_name:
+ # This should be present and set
+ assert top_options['backing']['driver'] == 'commit_top'
+ # And the mid image is commit_top's backing image
+ mid_options = top_options['backing']['backing']
+ else:
+ # The mid image should appear as the immediate backing BDS
+ # of top
+ mid_options = top_options['backing']
+
+ assert mid_options['driver'] == iotests.imgfmt
+ assert mid_options['file']['filename'] == mid_img_path
diff --git a/tests/qemu-iotests/224.out b/tests/qemu-iotests/224.out
new file mode 100644
index 0000000..23374a1
--- /dev/null
+++ b/tests/qemu-iotests/224.out
@@ -0,0 +1,18 @@
+
+--- filter_node_name: False ---
+
+{"execute": "blockdev-add", "arguments": {"backing": {"backing": {"backing": {"driver": "null-co"}, "driver": "IMGFMT", "file": {"driver": "file", "filename": "TEST_DIR/PID-base.img"}, "node-name": "base"}, "driver": "IMGFMT", "file": {"driver": "file", "filename": "TEST_DIR/PID-mid.img"}, "node-name": "mid"}, "driver": "IMGFMT", "file": {"driver": "file", "filename": "TEST_DIR/PID-top.img"}, "node-name": "top"}}
+{"return": {}}
+{"execute": "block-commit", "arguments": {"base": "json:{\"backing\": {\"driver\": \"null-co\"}, \"driver\": \"IMGFMT\", \"file\": {\"driver\": \"file\", \"filename\": \"TEST_DIR/PID-base.img\"}}", "device": "top", "job-id": "commit", "speed": 1, "top": "json:{\"backing\": {\"backing\": {\"driver\": \"null-co\"}, \"driver\": \"IMGFMT\", \"file\": {\"driver\": \"file\", \"filename\": \"TEST_DIR/PID-base.img\"}}, \"driver\": \"IMGFMT\", \"file\": {\"driver\": \"file\", \"filename\": \"TEST_DIR/PID-mid.img\"}}"}}
+{"return": {}}
+{"execute": "job-pause", "arguments": {"id": "commit"}}
+{"return": {}}
+
+--- filter_node_name: True ---
+
+{"execute": "blockdev-add", "arguments": {"backing": {"backing": {"backing": {"driver": "null-co"}, "driver": "IMGFMT", "file": {"driver": "file", "filename": "TEST_DIR/PID-base.img"}, "node-name": "base"}, "driver": "IMGFMT", "file": {"driver": "file", "filename": "TEST_DIR/PID-mid.img"}, "node-name": "mid"}, "driver": "IMGFMT", "file": {"driver": "file", "filename": "TEST_DIR/PID-top.img"}, "node-name": "top"}}
+{"return": {}}
+{"execute": "block-commit", "arguments": {"base": "json:{\"backing\": {\"driver\": \"null-co\"}, \"driver\": \"IMGFMT\", \"file\": {\"driver\": \"file\", \"filename\": \"TEST_DIR/PID-base.img\"}}", "device": "top", "filter-node-name": "filter_node", "job-id": "commit", "speed": 1, "top": "json:{\"backing\": {\"backing\": {\"driver\": \"null-co\"}, \"driver\": \"IMGFMT\", \"file\": {\"driver\": \"file\", \"filename\": \"TEST_DIR/PID-base.img\"}}, \"driver\": \"IMGFMT\", \"file\": {\"driver\": \"file\", \"filename\": \"TEST_DIR/PID-mid.img\"}}"}}
+{"return": {}}
+{"execute": "job-pause", "arguments": {"id": "commit"}}
+{"return": {}}
diff --git a/tests/qemu-iotests/228 b/tests/qemu-iotests/228
new file mode 100755
index 0000000..9a50afd
--- /dev/null
+++ b/tests/qemu-iotests/228
@@ -0,0 +1,239 @@
+#!/usr/bin/env python
+#
+# Test for when a backing file is considered overridden (thus, a
+# json:{} filename is generated for the overlay) and when it is not
+#
+# Copyright (C) 2018 Red Hat, Inc.
+#
+# 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: Max Reitz <mreitz@redhat.com>
+
+import iotests
+from iotests import log, qemu_img, filter_testfiles, filter_imgfmt, \
+ filter_qmp_testfiles, filter_qmp_imgfmt
+
+# Need backing file and change-backing-file support
+iotests.verify_image_format(supported_fmts=['qcow2', 'qed'])
+iotests.verify_platform(['linux'])
+
+
+def log_node_info(node):
+ log('')
+
+ log('bs->filename: ' + node['image']['filename'],
+ filters=[filter_testfiles, filter_imgfmt])
+ log('bs->backing_file: ' + node['backing_file'],
+ filters=[filter_testfiles, filter_imgfmt])
+
+ if 'backing-image' in node['image']:
+ log('bs->backing->bs->filename: ' +
+ node['image']['backing-image']['filename'],
+ filters=[filter_testfiles, filter_imgfmt])
+ else:
+ log('bs->backing: (none)')
+
+ log('')
+
+
+with iotests.FilePath('base.img') as base_img_path, \
+ iotests.FilePath('top.img') as top_img_path, \
+ iotests.VM() as vm:
+
+ assert qemu_img('create', '-f', iotests.imgfmt, base_img_path, '64M') == 0
+ # Choose a funny way to describe the backing filename
+ assert qemu_img('create', '-f', iotests.imgfmt, '-b',
+ 'file:' + base_img_path, top_img_path) == 0
+
+ vm.launch()
+
+ log('--- Implicit backing file ---')
+ log('')
+
+ vm.qmp_log('blockdev-add',
+ node_name='node0',
+ driver=iotests.imgfmt,
+ file={
+ 'driver': 'file',
+ 'filename': top_img_path
+ },
+ filters=[filter_qmp_testfiles, filter_qmp_imgfmt])
+
+ # Filename should be plain, and the backing filename should not
+ # contain the "file:" prefix
+ log_node_info(vm.node_info('node0'))
+
+ vm.qmp_log('blockdev-del', node_name='node0')
+
+ log('')
+ log('--- change-backing-file ---')
+ log('')
+
+ vm.qmp_log('blockdev-add',
+ node_name='node0',
+ driver=iotests.imgfmt,
+ file={
+ 'driver': 'file',
+ 'filename': top_img_path
+ },
+ filters=[filter_qmp_testfiles, filter_qmp_imgfmt])
+
+ # Changing the backing file to a qemu-reported filename should
+ # result in qemu accepting the corresponding BDS as the implicit
+ # backing BDS (and thus not generate a json:{} filename).
+ # So, first, query the backing filename.
+
+ backing_filename = \
+ vm.node_info('node0')['image']['backing-image']['filename']
+
+ # Next, change the backing file to something different
+
+ vm.qmp_log('change-backing-file',
+ image_node_name='node0',
+ device='node0',
+ backing_file='null-co://',
+ filters=[filter_qmp_testfiles])
+
+ # Now, verify that we get a json:{} filename
+ # (Image header says "null-co://", actual backing file still is
+ # base_img_path)
+
+ log_node_info(vm.node_info('node0'))
+
+ # Change it back
+ # (To get header and backing file in sync)
+
+ vm.qmp_log('change-backing-file',
+ image_node_name='node0',
+ device='node0',
+ backing_file=backing_filename,
+ filters=[filter_qmp_testfiles])
+
+ # And verify that we get our original results
+
+ log_node_info(vm.node_info('node0'))
+
+ # Finally, try a "file:" prefix. While this is actually what we
+ # originally had in the image header, qemu will not reopen the
+ # backing file here, so it cannot verify that this filename
+ # "resolves" to the actual backing BDS's filename and will thus
+ # consider both to be different.
+ # (This may be fixed in the future.)
+
+ vm.qmp_log('change-backing-file',
+ image_node_name='node0',
+ device='node0',
+ backing_file=('file:' + backing_filename),
+ filters=[filter_qmp_testfiles])
+
+ # So now we should get a json:{} filename
+
+ log_node_info(vm.node_info('node0'))
+
+ # Remove and re-attach so we can see that (as in our first try),
+ # opening the image anew helps qemu resolve the header backing
+ # filename.
+
+ vm.qmp_log('blockdev-del', node_name='node0')
+
+ vm.qmp_log('blockdev-add',
+ node_name='node0',
+ driver=iotests.imgfmt,
+ file={
+ 'driver': 'file',
+ 'filename': top_img_path
+ },
+ filters=[filter_qmp_testfiles, filter_qmp_imgfmt])
+
+ log_node_info(vm.node_info('node0'))
+
+ vm.qmp_log('blockdev-del', node_name='node0')
+
+ log('')
+ log('--- Override backing file ---')
+ log('')
+
+ # For this test, we need the plain filename in the image header
+ # (because qemu cannot "canonicalize"/"resolve" the backing
+ # filename unless the backing file is opened implicitly with the
+ # overlay)
+ assert qemu_img('create', '-f', iotests.imgfmt, '-b', base_img_path,
+ top_img_path) == 0
+
+ # You can only reliably override backing options by using a node
+ # reference (or by specifying file.filename, but, well...)
+ vm.qmp_log('blockdev-add', node_name='null', driver='null-co')
+
+ vm.qmp_log('blockdev-add',
+ node_name='node0',
+ driver=iotests.imgfmt,
+ file={
+ 'driver': 'file',
+ 'filename': top_img_path
+ },
+ backing='null',
+ filters=[filter_qmp_testfiles, filter_qmp_imgfmt])
+
+ # Should get a json:{} filename (and bs->backing_file is
+ # null-co://, because that field actually has not much to do
+ # with the header backing filename (except that it is changed by
+ # change-backing-file))
+
+ log_node_info(vm.node_info('node0'))
+
+ # Detach the backing file by reopening the whole thing
+
+ vm.qmp_log('blockdev-del', node_name='node0')
+ vm.qmp_log('blockdev-del', node_name='null')
+
+ vm.qmp_log('blockdev-add',
+ node_name='node0',
+ driver=iotests.imgfmt,
+ file={
+ 'driver': 'file',
+ 'filename': top_img_path
+ },
+ backing=None,
+ filters=[filter_qmp_testfiles, filter_qmp_imgfmt])
+
+ # Should get a json:{} filename (because we overrode the backing
+ # file to not be there)
+
+ log_node_info(vm.node_info('node0'))
+
+ # Open the original backing file
+
+ vm.qmp_log('blockdev-add',
+ node_name='original-backing',
+ driver=iotests.imgfmt,
+ file={
+ 'driver': 'file',
+ 'filename': base_img_path
+ },
+ filters=[filter_qmp_testfiles, filter_qmp_imgfmt])
+
+ # Attach the original backing file to its overlay
+
+ vm.qmp_log('blockdev-snapshot',
+ node='original-backing',
+ overlay='node0')
+
+ # This should give us the original plain result
+
+ log_node_info(vm.node_info('node0'))
+
+ vm.qmp_log('blockdev-del', node_name='node0')
+ vm.qmp_log('blockdev-del', node_name='original-backing')
+
+ vm.shutdown()
diff --git a/tests/qemu-iotests/228.out b/tests/qemu-iotests/228.out
new file mode 100644
index 0000000..4217df2
--- /dev/null
+++ b/tests/qemu-iotests/228.out
@@ -0,0 +1,84 @@
+--- Implicit backing file ---
+
+{"execute": "blockdev-add", "arguments": {"driver": "IMGFMT", "file": {"driver": "file", "filename": "TEST_DIR/PID-top.img"}, "node-name": "node0"}}
+{"return": {}}
+
+bs->filename: TEST_DIR/PID-top.img
+bs->backing_file: TEST_DIR/PID-base.img
+bs->backing->bs->filename: TEST_DIR/PID-base.img
+
+{"execute": "blockdev-del", "arguments": {"node-name": "node0"}}
+{"return": {}}
+
+--- change-backing-file ---
+
+{"execute": "blockdev-add", "arguments": {"driver": "IMGFMT", "file": {"driver": "file", "filename": "TEST_DIR/PID-top.img"}, "node-name": "node0"}}
+{"return": {}}
+{"execute": "change-backing-file", "arguments": {"backing-file": "null-co://", "device": "node0", "image-node-name": "node0"}}
+{"return": {}}
+
+bs->filename: json:{"backing": {"driver": "IMGFMT", "file": {"driver": "file", "filename": "TEST_DIR/PID-base.img"}}, "driver": "IMGFMT", "file": {"driver": "file", "filename": "TEST_DIR/PID-top.img"}}
+bs->backing_file: null-co://
+bs->backing->bs->filename: TEST_DIR/PID-base.img
+
+{"execute": "change-backing-file", "arguments": {"backing-file": "TEST_DIR/PID-base.img", "device": "node0", "image-node-name": "node0"}}
+{"return": {}}
+
+bs->filename: TEST_DIR/PID-top.img
+bs->backing_file: TEST_DIR/PID-base.img
+bs->backing->bs->filename: TEST_DIR/PID-base.img
+
+{"execute": "change-backing-file", "arguments": {"backing-file": "file:TEST_DIR/PID-base.img", "device": "node0", "image-node-name": "node0"}}
+{"return": {}}
+
+bs->filename: json:{"backing": {"driver": "IMGFMT", "file": {"driver": "file", "filename": "TEST_DIR/PID-base.img"}}, "driver": "IMGFMT", "file": {"driver": "file", "filename": "TEST_DIR/PID-top.img"}}
+bs->backing_file: file:TEST_DIR/PID-base.img
+bs->backing->bs->filename: TEST_DIR/PID-base.img
+
+{"execute": "blockdev-del", "arguments": {"node-name": "node0"}}
+{"return": {}}
+{"execute": "blockdev-add", "arguments": {"driver": "IMGFMT", "file": {"driver": "file", "filename": "TEST_DIR/PID-top.img"}, "node-name": "node0"}}
+{"return": {}}
+
+bs->filename: TEST_DIR/PID-top.img
+bs->backing_file: TEST_DIR/PID-base.img
+bs->backing->bs->filename: TEST_DIR/PID-base.img
+
+{"execute": "blockdev-del", "arguments": {"node-name": "node0"}}
+{"return": {}}
+
+--- Override backing file ---
+
+{"execute": "blockdev-add", "arguments": {"driver": "null-co", "node-name": "null"}}
+{"return": {}}
+{"execute": "blockdev-add", "arguments": {"backing": "null", "driver": "IMGFMT", "file": {"driver": "file", "filename": "TEST_DIR/PID-top.img"}, "node-name": "node0"}}
+{"return": {}}
+
+bs->filename: json:{"backing": {"driver": "null-co"}, "driver": "IMGFMT", "file": {"driver": "file", "filename": "TEST_DIR/PID-top.img"}}
+bs->backing_file: null-co://
+bs->backing->bs->filename: null-co://
+
+{"execute": "blockdev-del", "arguments": {"node-name": "node0"}}
+{"return": {}}
+{"execute": "blockdev-del", "arguments": {"node-name": "null"}}
+{"return": {}}
+{"execute": "blockdev-add", "arguments": {"backing": null, "driver": "IMGFMT", "file": {"driver": "file", "filename": "TEST_DIR/PID-top.img"}, "node-name": "node0"}}
+{"return": {}}
+
+bs->filename: json:{"backing": null, "driver": "IMGFMT", "file": {"driver": "file", "filename": "TEST_DIR/PID-top.img"}}
+bs->backing_file: TEST_DIR/PID-base.img
+bs->backing: (none)
+
+{"execute": "blockdev-add", "arguments": {"driver": "IMGFMT", "file": {"driver": "file", "filename": "TEST_DIR/PID-base.img"}, "node-name": "original-backing"}}
+{"return": {}}
+{"execute": "blockdev-snapshot", "arguments": {"node": "original-backing", "overlay": "node0"}}
+{"return": {}}
+
+bs->filename: TEST_DIR/PID-top.img
+bs->backing_file: TEST_DIR/PID-base.img
+bs->backing->bs->filename: TEST_DIR/PID-base.img
+
+{"execute": "blockdev-del", "arguments": {"node-name": "node0"}}
+{"return": {}}
+{"execute": "blockdev-del", "arguments": {"node-name": "original-backing"}}
+{"return": {}}
diff --git a/tests/qemu-iotests/232 b/tests/qemu-iotests/232
index 0708b8b..e48bc8f 100755
--- a/tests/qemu-iotests/232
+++ b/tests/qemu-iotests/232
@@ -29,7 +29,6 @@
_cleanup()
{
_cleanup_test_img
- rm -f $TEST_IMG.snap
}
trap "_cleanup; exit \$status" 0 1 2 3 15
@@ -70,6 +69,10 @@
_make_test_img $size
+if [ -n "$TEST_IMG_FILE" ]; then
+ TEST_IMG=$TEST_IMG_FILE
+fi
+
echo
echo "=== -drive with read-write image: read-only/auto-read-only combinations ==="
echo
diff --git a/tests/qemu-iotests/233 b/tests/qemu-iotests/233
index fc345a1..adb742f 100755
--- a/tests/qemu-iotests/233
+++ b/tests/qemu-iotests/233
@@ -30,6 +30,8 @@
{
nbd_server_stop
_cleanup_test_img
+ # If we aborted early we want to see this log for diagnosis
+ test -f "$TEST_DIR/server.log" && cat "$TEST_DIR/server.log"
rm -f "$TEST_DIR/server.log"
tls_x509_cleanup
}
@@ -120,6 +122,7 @@
echo
echo "== final server log =="
cat "$TEST_DIR/server.log"
+rm -f "$TEST_DIR/server.log"
# success, all done
echo "*** done"
diff --git a/tests/qemu-iotests/237 b/tests/qemu-iotests/237
index 251771d..06897f8 100755
--- a/tests/qemu-iotests/237
+++ b/tests/qemu-iotests/237
@@ -27,7 +27,8 @@
iotests.verify_image_format(supported_fmts=['vmdk'])
def blockdev_create(vm, options):
- result = vm.qmp_log('blockdev-create', job_id='job0', options=options)
+ result = vm.qmp_log('blockdev-create', job_id='job0', options=options,
+ filters=[iotests.filter_qmp_testfiles])
if 'return' in result:
assert result['return'] == {}
@@ -54,7 +55,7 @@
'size': 0 })
vm.qmp_log('blockdev-add', driver='file', filename=disk_path,
- node_name='imgfile')
+ node_name='imgfile', filters=[iotests.filter_qmp_testfiles])
blockdev_create(vm, { 'driver': imgfmt,
'file': 'imgfile',
@@ -223,7 +224,7 @@
iotests.log("= %s %d =" % (subfmt, size))
iotests.log("")
- num_extents = math.ceil(size / 2.0**31)
+ num_extents = int(math.ceil(size / 2.0**31))
extents = [ "ext%d" % (i) for i in range(1, num_extents + 1) ]
vm.launch()
diff --git a/tests/qemu-iotests/237.out b/tests/qemu-iotests/237.out
index 241c864..2aaa68f 100644
--- a/tests/qemu-iotests/237.out
+++ b/tests/qemu-iotests/237.out
@@ -1,13 +1,13 @@
=== Successful image creation (defaults) ===
-{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "file", "filename": "TEST_DIR/PID-t.vmdk", "size": 0}}}
+{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"driver": "file", "filename": "TEST_DIR/PID-t.vmdk", "size": 0}}}
{"return": {}}
{"execute": "job-dismiss", "arguments": {"id": "job0"}}
{"return": {}}
-{"execute": "blockdev-add", "arguments": {"driver": "file", "filename": "TEST_DIR/PID-t.vmdk", "node_name": "imgfile"}}
+{"execute": "blockdev-add", "arguments": {"driver": "file", "filename": "TEST_DIR/PID-t.vmdk", "node-name": "imgfile"}}
{"return": {}}
-{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "vmdk", "file": "imgfile", "size": 5368709120}}}
+{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"driver": "vmdk", "file": "imgfile", "size": 5368709120}}}
{"return": {}}
{"execute": "job-dismiss", "arguments": {"id": "job0"}}
{"return": {}}
@@ -29,12 +29,12 @@
=== Successful image creation (inline blockdev-add, explicit defaults) ===
-{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "file", "filename": "TEST_DIR/PID-t.vmdk", "size": 0}}}
+{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"driver": "file", "filename": "TEST_DIR/PID-t.vmdk", "size": 0}}}
{"return": {}}
{"execute": "job-dismiss", "arguments": {"id": "job0"}}
{"return": {}}
-{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"adapter-type": "ide", "driver": "vmdk", "extents": [], "file": {"driver": "file", "filename": "TEST_DIR/PID-t.vmdk"}, "hwversion": "4", "size": 67108864, "subformat": "monolithicSparse", "zeroed-grain": false}}}
+{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"adapter-type": "ide", "driver": "vmdk", "extents": [], "file": {"driver": "file", "filename": "TEST_DIR/PID-t.vmdk"}, "hwversion": "4", "size": 67108864, "subformat": "monolithicSparse", "zeroed-grain": false}}}
{"return": {}}
{"execute": "job-dismiss", "arguments": {"id": "job0"}}
{"return": {}}
@@ -56,12 +56,12 @@
=== Successful image creation (with non-default options) ===
-{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "file", "filename": "TEST_DIR/PID-t.vmdk", "size": 0}}}
+{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"driver": "file", "filename": "TEST_DIR/PID-t.vmdk", "size": 0}}}
{"return": {}}
{"execute": "job-dismiss", "arguments": {"id": "job0"}}
{"return": {}}
-{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"adapter-type": "buslogic", "driver": "vmdk", "extents": [], "file": {"driver": "file", "filename": "TEST_DIR/PID-t.vmdk"}, "size": 33554432, "subformat": "monolithicSparse", "zeroed-grain": true}}}
+{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"adapter-type": "buslogic", "driver": "vmdk", "extents": [], "file": {"driver": "file", "filename": "TEST_DIR/PID-t.vmdk"}, "size": 33554432, "subformat": "monolithicSparse", "zeroed-grain": true}}}
{"return": {}}
{"execute": "job-dismiss", "arguments": {"id": "job0"}}
{"return": {}}
@@ -83,7 +83,7 @@
=== Invalid BlockdevRef ===
-{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "vmdk", "file": "this doesn't exist", "size": 33554432}}}
+{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"driver": "vmdk", "file": "this doesn't exist", "size": 33554432}}}
{"return": {}}
Job failed: Cannot find device=this doesn't exist nor node_name=this doesn't exist
{"execute": "job-dismiss", "arguments": {"id": "job0"}}
@@ -93,38 +93,38 @@
== Valid adapter types ==
-{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"adapter-type": "ide", "driver": "vmdk", "file": "node0", "size": 33554432}}}
+{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"adapter-type": "ide", "driver": "vmdk", "file": "node0", "size": 33554432}}}
{"return": {}}
{"execute": "job-dismiss", "arguments": {"id": "job0"}}
{"return": {}}
-{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"adapter-type": "buslogic", "driver": "vmdk", "file": "node0", "size": 33554432}}}
+{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"adapter-type": "buslogic", "driver": "vmdk", "file": "node0", "size": 33554432}}}
{"return": {}}
{"execute": "job-dismiss", "arguments": {"id": "job0"}}
{"return": {}}
-{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"adapter-type": "lsilogic", "driver": "vmdk", "file": "node0", "size": 33554432}}}
+{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"adapter-type": "lsilogic", "driver": "vmdk", "file": "node0", "size": 33554432}}}
{"return": {}}
{"execute": "job-dismiss", "arguments": {"id": "job0"}}
{"return": {}}
-{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"adapter-type": "legacyESX", "driver": "vmdk", "file": "node0", "size": 33554432}}}
+{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"adapter-type": "legacyESX", "driver": "vmdk", "file": "node0", "size": 33554432}}}
{"return": {}}
{"execute": "job-dismiss", "arguments": {"id": "job0"}}
{"return": {}}
== Invalid adapter types ==
-{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"adapter-type": "foo", "driver": "vmdk", "file": "node0", "size": 33554432}}}
+{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"adapter-type": "foo", "driver": "vmdk", "file": "node0", "size": 33554432}}}
{"error": {"class": "GenericError", "desc": "Invalid parameter 'foo'"}}
-{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"adapter-type": "IDE", "driver": "vmdk", "file": "node0", "size": 33554432}}}
+{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"adapter-type": "IDE", "driver": "vmdk", "file": "node0", "size": 33554432}}}
{"error": {"class": "GenericError", "desc": "Invalid parameter 'IDE'"}}
-{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"adapter-type": "legacyesx", "driver": "vmdk", "file": "node0", "size": 33554432}}}
+{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"adapter-type": "legacyesx", "driver": "vmdk", "file": "node0", "size": 33554432}}}
{"error": {"class": "GenericError", "desc": "Invalid parameter 'legacyesx'"}}
-{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"adapter-type": 1, "driver": "vmdk", "file": "node0", "size": 33554432}}}
+{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"adapter-type": 1, "driver": "vmdk", "file": "node0", "size": 33554432}}}
{"error": {"class": "GenericError", "desc": "Invalid parameter type for 'options.adapter-type', expected: string"}}
=== Other subformats ===
@@ -137,7 +137,7 @@
== Missing extent ==
-{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "vmdk", "file": "node0", "size": 33554432, "subformat": "monolithicFlat"}}}
+{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"driver": "vmdk", "file": "node0", "size": 33554432, "subformat": "monolithicFlat"}}}
{"return": {}}
Job failed: Extent [0] not specified
{"execute": "job-dismiss", "arguments": {"id": "job0"}}
@@ -145,14 +145,14 @@
== Correct extent ==
-{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "vmdk", "extents": ["ext1"], "file": "node0", "size": 33554432, "subformat": "monolithicFlat"}}}
+{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"driver": "vmdk", "extents": ["ext1"], "file": "node0", "size": 33554432, "subformat": "monolithicFlat"}}}
{"return": {}}
{"execute": "job-dismiss", "arguments": {"id": "job0"}}
{"return": {}}
== Extra extent ==
-{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "vmdk", "extents": ["ext1", "ext2", "ext3"], "file": "node0", "size": 512, "subformat": "monolithicFlat"}}}
+{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"driver": "vmdk", "extents": ["ext1", "ext2", "ext3"], "file": "node0", "size": 512, "subformat": "monolithicFlat"}}}
{"return": {}}
Job failed: List of extents contains unused extents
{"execute": "job-dismiss", "arguments": {"id": "job0"}}
@@ -162,7 +162,7 @@
= twoGbMaxExtentFlat 512 =
-{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "vmdk", "extents": ["ext1"], "file": "node0", "size": 512, "subformat": "twoGbMaxExtentFlat"}}}
+{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"driver": "vmdk", "extents": ["ext1"], "file": "node0", "size": 512, "subformat": "twoGbMaxExtentFlat"}}}
{"return": {}}
{"execute": "job-dismiss", "arguments": {"id": "job0"}}
{"return": {}}
@@ -182,7 +182,7 @@
= twoGbMaxExtentSparse 512 =
-{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "vmdk", "extents": ["ext1"], "file": "node0", "size": 512, "subformat": "twoGbMaxExtentSparse"}}}
+{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"driver": "vmdk", "extents": ["ext1"], "file": "node0", "size": 512, "subformat": "twoGbMaxExtentSparse"}}}
{"return": {}}
{"execute": "job-dismiss", "arguments": {"id": "job0"}}
{"return": {}}
@@ -204,7 +204,7 @@
= twoGbMaxExtentFlat 1073741824 =
-{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "vmdk", "extents": ["ext1"], "file": "node0", "size": 1073741824, "subformat": "twoGbMaxExtentFlat"}}}
+{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"driver": "vmdk", "extents": ["ext1"], "file": "node0", "size": 1073741824, "subformat": "twoGbMaxExtentFlat"}}}
{"return": {}}
{"execute": "job-dismiss", "arguments": {"id": "job0"}}
{"return": {}}
@@ -224,7 +224,7 @@
= twoGbMaxExtentSparse 1073741824 =
-{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "vmdk", "extents": ["ext1"], "file": "node0", "size": 1073741824, "subformat": "twoGbMaxExtentSparse"}}}
+{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"driver": "vmdk", "extents": ["ext1"], "file": "node0", "size": 1073741824, "subformat": "twoGbMaxExtentSparse"}}}
{"return": {}}
{"execute": "job-dismiss", "arguments": {"id": "job0"}}
{"return": {}}
@@ -246,7 +246,7 @@
= twoGbMaxExtentFlat 2147483648 =
-{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "vmdk", "extents": ["ext1"], "file": "node0", "size": 2147483648, "subformat": "twoGbMaxExtentFlat"}}}
+{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"driver": "vmdk", "extents": ["ext1"], "file": "node0", "size": 2147483648, "subformat": "twoGbMaxExtentFlat"}}}
{"return": {}}
{"execute": "job-dismiss", "arguments": {"id": "job0"}}
{"return": {}}
@@ -266,7 +266,7 @@
= twoGbMaxExtentSparse 2147483648 =
-{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "vmdk", "extents": ["ext1"], "file": "node0", "size": 2147483648, "subformat": "twoGbMaxExtentSparse"}}}
+{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"driver": "vmdk", "extents": ["ext1"], "file": "node0", "size": 2147483648, "subformat": "twoGbMaxExtentSparse"}}}
{"return": {}}
{"execute": "job-dismiss", "arguments": {"id": "job0"}}
{"return": {}}
@@ -288,7 +288,7 @@
= twoGbMaxExtentFlat 5368709120 =
-{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "vmdk", "extents": ["ext1", "ext2", "ext3"], "file": "node0", "size": 5368709120, "subformat": "twoGbMaxExtentFlat"}}}
+{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"driver": "vmdk", "extents": ["ext1", "ext2", "ext3"], "file": "node0", "size": 5368709120, "subformat": "twoGbMaxExtentFlat"}}}
{"return": {}}
{"execute": "job-dismiss", "arguments": {"id": "job0"}}
{"return": {}}
@@ -316,7 +316,7 @@
= twoGbMaxExtentSparse 5368709120 =
-{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "vmdk", "extents": ["ext1", "ext2", "ext3"], "file": "node0", "size": 5368709120, "subformat": "twoGbMaxExtentSparse"}}}
+{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"driver": "vmdk", "extents": ["ext1", "ext2", "ext3"], "file": "node0", "size": 5368709120, "subformat": "twoGbMaxExtentSparse"}}}
{"return": {}}
{"execute": "job-dismiss", "arguments": {"id": "job0"}}
{"return": {}}
diff --git a/tests/qemu-iotests/242 b/tests/qemu-iotests/242
index 16c65ed..c176e92 100755
--- a/tests/qemu-iotests/242
+++ b/tests/qemu-iotests/242
@@ -20,6 +20,7 @@
import iotests
import json
+import struct
from iotests import qemu_img_create, qemu_io, qemu_img_pipe, \
file_path, img_info_log, log, filter_qemu_io
@@ -64,10 +65,11 @@
def toggle_flag(offset):
with open(disk, "r+b") as f:
f.seek(offset, 0)
- c = f.read(1)
- toggled = chr(ord(c) ^ bitmap_flag_unknown)
+ # Read one byte in a way compatible with Python 2
+ flags = struct.unpack("B", f.read(1))
+ toggled = flags[0] ^ bitmap_flag_unknown
f.seek(-1, 1)
- f.write(toggled)
+ f.write(struct.pack("B", toggled))
qemu_img_create('-f', iotests.imgfmt, disk, '1M')
diff --git a/tests/qemu-iotests/common.rc b/tests/qemu-iotests/common.rc
index e15e7a7..09a27f0 100644
--- a/tests/qemu-iotests/common.rc
+++ b/tests/qemu-iotests/common.rc
@@ -145,6 +145,7 @@
TEST_IMG="nbd:127.0.0.1:10810"
elif [ "$IMGPROTO" = "ssh" ]; then
TEST_IMG_FILE=$TEST_DIR/t.$IMGFMT
+ REMOTE_TEST_DIR="ssh://127.0.0.1$TEST_DIR"
TEST_IMG="ssh://127.0.0.1$TEST_IMG_FILE"
elif [ "$IMGPROTO" = "nfs" ]; then
TEST_IMG_FILE=$TEST_DIR/t.$IMGFMT
diff --git a/tests/qemu-iotests/common.tls b/tests/qemu-iotests/common.tls
index eae8178..3caf989 100644
--- a/tests/qemu-iotests/common.tls
+++ b/tests/qemu-iotests/common.tls
@@ -29,6 +29,17 @@
}
+tls_certtool()
+{
+ certtool "$@" 1>"${tls_dir}"/certtool.log 2>&1
+ if test "$?" = 0; then
+ head -1 "${tls_dir}"/certtool.log
+ else
+ cat "${tls_dir}"/certtool.log
+ fi
+ rm -f "${tls_dir}"/certtool.log
+}
+
tls_x509_init()
{
(certtool --help) >/dev/null 2>&1 || \
@@ -71,10 +82,11 @@
cert_signing_key
EOF
- certtool --generate-self-signed \
- --load-privkey "${tls_dir}/key.pem" \
- --template "${tls_dir}/ca.info" \
- --outfile "${tls_dir}/$name-cert.pem" 2>&1 | head -1
+ tls_certtool \
+ --generate-self-signed \
+ --load-privkey "${tls_dir}/key.pem" \
+ --template "${tls_dir}/ca.info" \
+ --outfile "${tls_dir}/$name-cert.pem"
rm -f "${tls_dir}/ca.info"
}
@@ -98,12 +110,14 @@
signing_key
EOF
- certtool --generate-certificate \
- --load-ca-privkey "${tls_dir}/key.pem" \
- --load-ca-certificate "${tls_dir}/$caname-cert.pem" \
- --load-privkey "${tls_dir}/key.pem" \
- --template "${tls_dir}/cert.info" \
- --outfile "${tls_dir}/$name/server-cert.pem" 2>&1 | head -1
+ tls_certtool \
+ --generate-certificate \
+ --load-ca-privkey "${tls_dir}/key.pem" \
+ --load-ca-certificate "${tls_dir}/$caname-cert.pem" \
+ --load-privkey "${tls_dir}/key.pem" \
+ --template "${tls_dir}/cert.info" \
+ --outfile "${tls_dir}/$name/server-cert.pem"
+
ln -s "${tls_dir}/$caname-cert.pem" "${tls_dir}/$name/ca-cert.pem"
ln -s "${tls_dir}/key.pem" "${tls_dir}/$name/server-key.pem"
@@ -127,12 +141,14 @@
signing_key
EOF
- certtool --generate-certificate \
- --load-ca-privkey "${tls_dir}/key.pem" \
- --load-ca-certificate "${tls_dir}/$caname-cert.pem" \
- --load-privkey "${tls_dir}/key.pem" \
- --template "${tls_dir}/cert.info" \
- --outfile "${tls_dir}/$name/client-cert.pem" 2>&1 | head -1
+ tls_certtool \
+ --generate-certificate \
+ --load-ca-privkey "${tls_dir}/key.pem" \
+ --load-ca-certificate "${tls_dir}/$caname-cert.pem" \
+ --load-privkey "${tls_dir}/key.pem" \
+ --template "${tls_dir}/cert.info" \
+ --outfile "${tls_dir}/$name/client-cert.pem"
+
ln -s "${tls_dir}/$caname-cert.pem" "${tls_dir}/$name/ca-cert.pem"
ln -s "${tls_dir}/key.pem" "${tls_dir}/$name/client-key.pem"
diff --git a/tests/qemu-iotests/group b/tests/qemu-iotests/group
index fc4c416..b5ca63c 100644
--- a/tests/qemu-iotests/group
+++ b/tests/qemu-iotests/group
@@ -224,9 +224,11 @@
221 rw auto quick
222 rw auto quick
223 rw auto quick
+224 rw auto quick
225 rw auto quick
226 auto quick
227 auto quick
+228 rw auto quick
229 auto quick
231 auto quick
232 auto quick
diff --git a/tests/qemu-iotests/iotests.py b/tests/qemu-iotests/iotests.py
index 54a3104..3d15571 100644
--- a/tests/qemu-iotests/iotests.py
+++ b/tests/qemu-iotests/iotests.py
@@ -76,14 +76,16 @@
sys.stderr.write('qemu-img received signal %i: %s\n' % (-exitcode, ' '.join(qemu_img_args + list(args))))
return exitcode
-def ordered_qmp(qmsg):
+def ordered_qmp(qmsg, conv_keys=True):
# Dictionaries are not ordered prior to 3.6, therefore:
if isinstance(qmsg, list):
return [ordered_qmp(atom) for atom in qmsg]
if isinstance(qmsg, dict):
od = OrderedDict()
for k, v in sorted(qmsg.items()):
- od[k] = ordered_qmp(v)
+ if conv_keys:
+ k = k.replace('_', '-')
+ od[k] = ordered_qmp(v, conv_keys=False)
return od
return qmsg
@@ -236,6 +238,12 @@
r = qemu_img_pipe('info', '--output=json', '-f', imgfmt, img)
return json.loads(r)['virtual-size']
+def is_str(val):
+ if sys.version_info.major >= 3:
+ return isinstance(val, str)
+ else:
+ return isinstance(val, str) or isinstance(val, unicode)
+
test_dir_re = re.compile(r"%s" % test_dir)
def filter_test_dir(msg):
return test_dir_re.sub("TEST_DIR", msg)
@@ -283,7 +291,7 @@
def filter_qmp_testfiles(qmsg):
def _filter(key, value):
- if key == 'filename' or key == 'backing-file':
+ if is_str(value):
return filter_testfiles(value)
return value
return filter_qmp(qmsg, _filter)
@@ -304,6 +312,16 @@
lines.append(line)
return '\n'.join(lines)
+def filter_imgfmt(msg):
+ return msg.replace(imgfmt, 'IMGFMT')
+
+def filter_qmp_imgfmt(qmsg):
+ def _filter(key, value):
+ if is_str(value):
+ return filter_imgfmt(value)
+ return value
+ return filter_qmp(qmsg, _filter)
+
def log(msg, filters=[], indent=None):
'''Logs either a string message or a JSON serializable message (like QMP).
If indent is provided, JSON serializable messages are pretty-printed.'''
@@ -514,7 +532,9 @@
log(result, filters, indent=indent)
return result
+ # Returns None on success, and an error string on failure
def run_job(self, job, auto_finalize=True, auto_dismiss=False):
+ error = None
while True:
for ev in self.get_qmp_events_filtered(wait=True):
if ev['event'] == 'JOB_STATUS_CHANGE':
@@ -523,16 +543,24 @@
result = self.qmp('query-jobs')
for j in result['return']:
if j['id'] == job:
+ error = j['error']
log('Job failed: %s' % (j['error']))
elif status == 'pending' and not auto_finalize:
self.qmp_log('job-finalize', id=job)
elif status == 'concluded' and not auto_dismiss:
self.qmp_log('job-dismiss', id=job)
elif status == 'null':
- return
+ return error
else:
iotests.log(ev)
+ def node_info(self, node_name):
+ nodes = self.qmp('query-named-block-nodes')
+ for x in nodes['return']:
+ if x['node-name'] == node_name:
+ return x
+ return None
+
index_re = re.compile(r'([^\[]+)\[([^\]]+)\]')
diff --git a/tests/tcg/mips/include/test_inputs.h b/tests/tcg/mips/include/test_inputs.h
index c173d58..5406e4e 100644
--- a/tests/tcg/mips/include/test_inputs.h
+++ b/tests/tcg/mips/include/test_inputs.h
@@ -28,7 +28,7 @@
#define PATTERN_INPUTS_COUNT 64
#define PATTERN_INPUTS_SHORT_COUNT 8
-uint64_t b128_pattern[PATTERN_INPUTS_COUNT][2] = {
+static const uint64_t b128_pattern[PATTERN_INPUTS_COUNT][2] = {
{ 0xFFFFFFFFFFFFFFFFULL, 0xFFFFFFFFFFFFFFFFULL, }, /* 0 */
{ 0x0000000000000000ULL, 0x0000000000000000ULL, },
{ 0xAAAAAAAAAAAAAAAAULL, 0xAAAAAAAAAAAAAAAAULL, },
@@ -99,7 +99,7 @@
#define RANDOM_INPUTS_COUNT 16
#define RANDOM_INPUTS_SHORT_COUNT 4
-uint64_t b128_random[RANDOM_INPUTS_COUNT][2] = {
+static const uint64_t b128_random[RANDOM_INPUTS_COUNT][2] = {
{ 0x886AE6CC28625540ULL, 0x4B670B5EFE7BB00CULL, }, /* 0 */
{ 0xFBBE00634D93C708ULL, 0x12F7BB1A153F52FCULL, },
{ 0xAC5AAEAAB9CF8B80ULL, 0x27D8C6FFAB2B2514ULL, },
diff --git a/tests/tcg/mips/include/test_inputs_32.h b/tests/tcg/mips/include/test_inputs_32.h
new file mode 100644
index 0000000..a3b7e54
--- /dev/null
+++ b/tests/tcg/mips/include/test_inputs_32.h
@@ -0,0 +1,122 @@
+/*
+ * Header file for pattern and random test inputs
+ *
+ * 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/>.
+ *
+ */
+
+#ifndef TEST_INPUTS_32_H
+#define TEST_INPUTS_32_H
+
+#include <stdint.h>
+
+
+#define PATTERN_INPUTS_32_COUNT 64
+#define PATTERN_INPUTS_32_SHORT_COUNT 8
+
+static const uint32_t b32_pattern[PATTERN_INPUTS_32_COUNT] = {
+ 0xFFFFFFFF, /* 0 */
+ 0x00000000,
+ 0xAAAAAAAA,
+ 0x55555555,
+ 0xCCCCCCCC,
+ 0x33333333,
+ 0xE38E38E3,
+ 0x1C71C71C,
+ 0xF0F0F0F0, /* 8 */
+ 0x0F0F0F0F,
+ 0xF83E0F83,
+ 0x07C1F07C,
+ 0xFC0FC0FC,
+ 0x03F03F03,
+ 0xFE03F80F,
+ 0x01FC07F0,
+ 0xFF00FF00, /* 16 */
+ 0x00FF00FF,
+ 0xFF803FE0,
+ 0x007FC01F,
+ 0xFFC00FFC,
+ 0x003FF003,
+ 0xFFE003FF,
+ 0x001FFC00,
+ 0xFFF000FF, /* 24 */
+ 0x000FFF00,
+ 0xFFF8003F,
+ 0x0007FFC0,
+ 0xFFFC000F,
+ 0x0003FFF0,
+ 0xFFFE0003,
+ 0x0001FFFC,
+ 0xFFFF0000, /* 32 */
+ 0x0000FFFF,
+ 0xFFFF8000,
+ 0x00007FFF,
+ 0xFFFFC000,
+ 0x00003FFF,
+ 0xFFFFE000,
+ 0x00001FFF,
+ 0xFFFFF000, /* 40 */
+ 0x00000FFF,
+ 0xFFFFF800,
+ 0x000007FF,
+ 0xFFFFFC00,
+ 0x000003FF,
+ 0xFFFFFE00,
+ 0x000001FF,
+ 0xFFFFFF00, /* 48 */
+ 0x000000FF,
+ 0xFFFFFF80,
+ 0x0000007F,
+ 0xFFFFFFC0,
+ 0x0000003F,
+ 0xFFFFFFE0,
+ 0x0000001F,
+ 0xFFFFFFF0, /* 56 */
+ 0x0000000F,
+ 0xFFFFFFF8,
+ 0x00000007,
+ 0xFFFFFFFC,
+ 0x00000003,
+ 0xFFFFFFFE,
+ 0x00000001,
+};
+
+
+#define RANDOM_INPUTS_32_COUNT 16
+#define RANDOM_INPUTS_32_SHORT_COUNT 4
+
+static const uint32_t b32_random[RANDOM_INPUTS_32_COUNT] = {
+ 0x886AE6CC, /* 0 */
+ 0xFBBE0063,
+ 0xAC5AAEAA,
+ 0x704F164D,
+ 0xB9926B7C,
+ 0xD027BE89,
+ 0xB83B5806,
+ 0xFC8F23F0,
+ 0x201E09CD, /* 8 */
+ 0xA57CD913,
+ 0xA2E8F6F5,
+ 0xA89CF2F1,
+ 0xE61438E9,
+ 0x944A35FD,
+ 0x46304263,
+ 0x8B5AA7A2,
+};
+
+
+#endif
diff --git a/tests/tcg/mips/include/test_inputs_64.h b/tests/tcg/mips/include/test_inputs_64.h
new file mode 100644
index 0000000..6891a36
--- /dev/null
+++ b/tests/tcg/mips/include/test_inputs_64.h
@@ -0,0 +1,208 @@
+/*
+ * Header file for pattern and random test inputs
+ *
+ * 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/>.
+ *
+ */
+
+#ifndef TEST_INPUTS_64_H
+#define TEST_INPUTS_64_H
+
+#include <stdint.h>
+
+
+#define PATTERN_INPUTS_64_COUNT 64
+#define PATTERN_INPUTS_64_SHORT_COUNT 8
+
+static const uint64_t b64_pattern[PATTERN_INPUTS_64_COUNT] = {
+ 0xFFFFFFFFFFFFFFFFULL, /* 0 */
+ 0x0000000000000000ULL,
+ 0xAAAAAAAAAAAAAAAAULL,
+ 0x5555555555555555ULL,
+ 0xCCCCCCCCCCCCCCCCULL,
+ 0x3333333333333333ULL,
+ 0xE38E38E38E38E38EULL,
+ 0x1C71C71C71C71C71ULL,
+ 0xF0F0F0F0F0F0F0F0ULL, /* 8 */
+ 0x0F0F0F0F0F0F0F0FULL,
+ 0xF83E0F83E0F83E0FULL,
+ 0x07C1F07C1F07C1F0ULL,
+ 0xFC0FC0FC0FC0FC0FULL,
+ 0x03F03F03F03F03F0ULL,
+ 0xFE03F80FE03F80FEULL,
+ 0x01FC07F01FC07F01ULL,
+ 0xFF00FF00FF00FF00ULL, /* 16 */
+ 0x00FF00FF00FF00FFULL,
+ 0xFF803FE00FF803FEULL,
+ 0x007FC01FF007FC01ULL,
+ 0xFFC00FFC00FFC00FULL,
+ 0x003FF003FF003FF0ULL,
+ 0xFFE003FF800FFE00ULL,
+ 0x001FFC007FF001FFULL,
+ 0xFFF000FFF000FFF0ULL, /* 24 */
+ 0x000FFF000FFF000FULL,
+ 0xFFF8003FFE000FFFULL,
+ 0x0007FFC001FFF000ULL,
+ 0xFFFC000FFFC000FFULL,
+ 0x0003FFF0003FFF00ULL,
+ 0xFFFE0003FFF8000FULL,
+ 0x0001FFFC0007FFF0ULL,
+ 0xFFFF0000FFFF0000ULL, /* 32 */
+ 0x0000FFFF0000FFFFULL,
+ 0xFFFF80003FFFE000ULL,
+ 0x00007FFFC0001FFFULL,
+ 0xFFFFC0000FFFFC00ULL,
+ 0x00003FFFF00003FFULL,
+ 0xFFFFE00003FFFF80ULL,
+ 0x00001FFFFC00007FULL,
+ 0xFFFFF00000FFFFF0ULL, /* 40 */
+ 0x00000FFFFF00000FULL,
+ 0xFFFFF800003FFFFEULL,
+ 0x000007FFFFC00001ULL,
+ 0xFFFFFC00000FFFFFULL,
+ 0x000003FFFFF00000ULL,
+ 0xFFFFFE000003FFFFULL,
+ 0x000001FFFFFC0000ULL,
+ 0xFFFFFF000000FFFFULL, /* 48 */
+ 0x000000FFFFFF0000ULL,
+ 0xFFFFFF8000003FFFULL,
+ 0x0000007FFFFFC000ULL,
+ 0xFFFFFFC000000FFFULL,
+ 0x0000003FFFFFF000ULL,
+ 0xFFFFFFE0000003FFULL,
+ 0x0000001FFFFFFC00ULL,
+ 0xFFFFFFF0000000FFULL, /* 56 */
+ 0x0000000FFFFFFF00ULL,
+ 0xFFFFFFF80000003FULL,
+ 0x00000007FFFFFFC0ULL,
+ 0xFFFFFFFC0000000FULL,
+ 0x00000003FFFFFFF0ULL,
+ 0xFFFFFFFE00000003ULL,
+ 0x00000001FFFFFFFCULL,
+};
+
+static const uint64_t b64_pattern_se[PATTERN_INPUTS_64_COUNT] = {
+ 0xFFFFFFFFFFFFFFFFULL, /* 0 */
+ 0x0000000000000000ULL,
+ 0xFFFFFFFFAAAAAAAAULL,
+ 0x0000000055555555ULL,
+ 0xFFFFFFFFCCCCCCCCULL,
+ 0x0000000033333333ULL,
+ 0xFFFFFFFFE38E38E3ULL,
+ 0x000000001C71C71CULL,
+ 0xFFFFFFFFF0F0F0F0ULL, /* 8 */
+ 0x000000000F0F0F0FULL,
+ 0xFFFFFFFFF83E0F83ULL,
+ 0x0000000007C1F07CULL,
+ 0xFFFFFFFFFC0FC0FCULL,
+ 0x0000000003F03F03ULL,
+ 0xFFFFFFFFFE03F80FULL,
+ 0x0000000001FC07F0ULL,
+ 0xFFFFFFFFFF00FF00ULL, /* 16 */
+ 0x0000000000FF00FFULL,
+ 0xFFFFFFFFFF803FE0ULL,
+ 0x00000000007FC01FULL,
+ 0xFFFFFFFFFFC00FFCULL,
+ 0x00000000003FF003ULL,
+ 0xFFFFFFFFFFE003FFULL,
+ 0x00000000001FFC00ULL,
+ 0xFFFFFFFFFFF000FFULL, /* 24 */
+ 0x00000000000FFF00ULL,
+ 0xFFFFFFFFFFF8003FULL,
+ 0x000000000007FFC0ULL,
+ 0xFFFFFFFFFFFC000FULL,
+ 0x000000000003FFF0ULL,
+ 0xFFFFFFFFFFFE0003ULL,
+ 0x000000000001FFFCULL,
+ 0xFFFFFFFFFFFF0000ULL, /* 32 */
+ 0x000000000000FFFFULL,
+ 0xFFFFFFFFFFFF8000ULL,
+ 0x0000000000007FFFULL,
+ 0xFFFFFFFFFFFFC000ULL,
+ 0x0000000000003FFFULL,
+ 0xFFFFFFFFFFFFE000ULL,
+ 0x0000000000001FFFULL,
+ 0xFFFFFFFFFFFFF000ULL, /* 40 */
+ 0x0000000000000FFFULL,
+ 0xFFFFFFFFFFFFF800ULL,
+ 0x00000000000007FFULL,
+ 0xFFFFFFFFFFFFFC00ULL,
+ 0x00000000000003FFULL,
+ 0xFFFFFFFFFFFFFE00ULL,
+ 0x00000000000001FFULL,
+ 0xFFFFFFFFFFFFFF00ULL, /* 48 */
+ 0x00000000000000FFULL,
+ 0xFFFFFFFFFFFFFF80ULL,
+ 0x000000000000007FULL,
+ 0xFFFFFFFFFFFFFFC0ULL,
+ 0x000000000000003FULL,
+ 0xFFFFFFFFFFFFFFE0ULL,
+ 0x000000000000001FULL,
+ 0xFFFFFFFFFFFFFFF0ULL, /* 56 */
+ 0x000000000000000FULL,
+ 0xFFFFFFFFFFFFFFF8ULL,
+ 0x0000000000000007ULL,
+ 0xFFFFFFFFFFFFFFFCULL,
+ 0x0000000000000003ULL,
+ 0xFFFFFFFFFFFFFFFEULL,
+ 0x0000000000000001ULL,
+};
+
+
+#define RANDOM_INPUTS_64_COUNT 16
+#define RANDOM_INPUTS_64_SHORT_COUNT 4
+
+static const uint64_t b64_random[RANDOM_INPUTS_64_COUNT] = {
+ 0x886AE6CC28625540ULL, /* 0 */
+ 0xFBBE00634D93C708ULL,
+ 0xAC5AAEAAB9CF8B80ULL,
+ 0x704F164D5E31E24EULL,
+ 0xB9926B7C7DAF4258ULL,
+ 0xD027BE89FF0A2EF9ULL,
+ 0xB83B580665CABC4AULL,
+ 0xFC8F23F09AA6B782ULL,
+ 0x201E09CD56AEE649ULL, /* 8 */
+ 0xA57CD91365D9E5D7ULL,
+ 0xA2E8F6F5C9CBC61BULL,
+ 0xA89CF2F131A864AEULL,
+ 0xE61438E9A652EA0AULL,
+ 0x944A35FD192361A8ULL,
+ 0x4630426322BEF79CULL,
+ 0x8B5AA7A2F259DEADULL,
+};
+
+static const uint64_t b64_random_se[RANDOM_INPUTS_64_COUNT] = {
+ 0xFFFFFFFF886AE6CCULL, /* 0 */
+ 0xFFFFFFFFFBBE0063ULL,
+ 0xFFFFFFFFAC5AAEAAULL,
+ 0x00000000704F164DULL,
+ 0xFFFFFFFFB9926B7CULL,
+ 0xFFFFFFFFD027BE89ULL,
+ 0xFFFFFFFFB83B5806ULL,
+ 0xFFFFFFFFFC8F23F0ULL,
+ 0x00000000201E09CDULL, /* 8 */
+ 0xFFFFFFFFA57CD913ULL,
+ 0xFFFFFFFFA2E8F6F5ULL,
+ 0xFFFFFFFFA89CF2F1ULL,
+ 0xFFFFFFFFE61438E9ULL,
+ 0xFFFFFFFF944A35FDULL,
+ 0x0000000046304263ULL,
+ 0xFFFFFFFF8B5AA7A2ULL,
+};
+
+
+#endif
diff --git a/tests/tcg/mips/include/test_utils.h b/tests/tcg/mips/include/test_utils.h
index 82f4b5b..9672903 100644
--- a/tests/tcg/mips/include/test_utils.h
+++ b/tests/tcg/mips/include/test_utils.h
@@ -27,14 +27,14 @@
#include <inttypes.h>
#include <string.h>
-#define PRINT_RESULTS 1
+#define PRINT_RESULTS 0
-static inline int32_t check_results(char *instruction_name,
- uint32_t test_count,
- double elapsed_time,
- uint64_t *b128_result,
- uint64_t *b128_expect)
+static inline int32_t check_results(const char *instruction_name,
+ const uint32_t test_count,
+ const double elapsed_time,
+ const uint64_t *b128_result,
+ const uint64_t *b128_expect)
{
#if PRINT_RESULTS
uint32_t ii;
@@ -58,7 +58,8 @@
printf("%s: ", instruction_name);
for (i = 0; i < test_count; i++) {
- if (b128_result[i] == b128_expect[i]) {
+ if ((b128_result[2 * i] == b128_expect[2 * i]) &&
+ (b128_result[2 * i + 1] == b128_expect[2 * i + 1])) {
pass_count++;
} else {
fail_count++;
diff --git a/tests/tcg/mips/include/test_utils_32.h b/tests/tcg/mips/include/test_utils_32.h
new file mode 100644
index 0000000..c33990c
--- /dev/null
+++ b/tests/tcg/mips/include/test_utils_32.h
@@ -0,0 +1,78 @@
+/*
+ * Header file for test utilities
+ *
+ * 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/>.
+ *
+ */
+
+#ifndef TEST_UTILS_32_H
+#define TEST_UTILS_32_H
+
+#include <stdio.h>
+#include <stdint.h>
+#include <inttypes.h>
+#include <string.h>
+
+#define PRINT_RESULTS 0
+
+
+static inline int32_t check_results_32(const char *instruction_name,
+ const uint32_t test_count,
+ const double elapsed_time,
+ const uint32_t *b32_result,
+ const uint32_t *b32_expect)
+{
+#if PRINT_RESULTS
+ uint32_t ii;
+ printf("\n");
+ for (ii = 0; ii < test_count; ii++) {
+ uint64_t a;
+ memcpy(&a, (b32_result + ii), 8);
+ if (ii % 8 != 0) {
+ printf(" 0x%08lxULL,\n", a);
+ } else {
+ printf(" 0x%08lxULL, /* %3d */\n",
+ a, ii);
+ }
+ }
+ printf("\n");
+#endif
+ uint32_t i;
+ uint32_t pass_count = 0;
+ uint32_t fail_count = 0;
+
+ printf("%s: ", instruction_name);
+ for (i = 0; i < test_count; i++) {
+ if (b32_result[i] == b32_expect[i]) {
+ pass_count++;
+ } else {
+ fail_count++;
+ }
+ }
+
+ printf("PASS: %3d FAIL: %3d elapsed time: %5.2f ms\n",
+ pass_count, fail_count, elapsed_time);
+
+ if (fail_count > 0) {
+ return -1;
+ } else {
+ return 0;
+ }
+}
+
+
+#endif
diff --git a/tests/tcg/mips/include/test_utils_64.h b/tests/tcg/mips/include/test_utils_64.h
new file mode 100644
index 0000000..ee38284
--- /dev/null
+++ b/tests/tcg/mips/include/test_utils_64.h
@@ -0,0 +1,78 @@
+/*
+ * Header file for test utilities
+ *
+ * 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/>.
+ *
+ */
+
+#ifndef TEST_UTILS_64_H
+#define TEST_UTILS_64_H
+
+#include <stdio.h>
+#include <stdint.h>
+#include <inttypes.h>
+#include <string.h>
+
+#define PRINT_RESULTS 0
+
+
+static inline int32_t check_results_64(const char *instruction_name,
+ const uint32_t test_count,
+ const double elapsed_time,
+ const uint64_t *b64_result,
+ const uint64_t *b64_expect)
+{
+#if PRINT_RESULTS
+ uint32_t ii;
+ printf("\n");
+ for (ii = 0; ii < test_count; ii++) {
+ uint64_t a;
+ memcpy(&a, (b64_result + ii), 8);
+ if (ii % 8 != 0) {
+ printf(" 0x%016llxULL,\n", a);
+ } else {
+ printf(" 0x%016llxULL, /* %3d */\n",
+ a, ii);
+ }
+ }
+ printf("\n");
+#endif
+ uint32_t i;
+ uint32_t pass_count = 0;
+ uint32_t fail_count = 0;
+
+ printf("%s: ", instruction_name);
+ for (i = 0; i < test_count; i++) {
+ if (b64_result[i] == b64_expect[i]) {
+ pass_count++;
+ } else {
+ fail_count++;
+ }
+ }
+
+ printf("PASS: %3d FAIL: %3d elapsed time: %5.2f ms\n",
+ pass_count, fail_count, elapsed_time);
+
+ if (fail_count > 0) {
+ return -1;
+ } else {
+ return 0;
+ }
+}
+
+
+#endif
diff --git a/tests/tcg/mips/include/wrappers_mips64r6.h b/tests/tcg/mips/include/wrappers_mips64r6.h
new file mode 100644
index 0000000..d1e5edb
--- /dev/null
+++ b/tests/tcg/mips/include/wrappers_mips64r6.h
@@ -0,0 +1,83 @@
+/*
+ * Header file for wrappers around MIPS64R6 instructions assembler
+ * invocations
+ *
+ * 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/>.
+ *
+ */
+
+#ifndef WRAPPERS_MIPS64R6_H
+#define WRAPPERS_MIPS64R6_H
+
+
+#define DO_MIPS64R6__RD__RS(suffix, mnemonic) \
+static inline void do_mips64r6_##suffix(const void *input, \
+ void *output) \
+{ \
+ __asm__ volatile ( \
+ "ld $t1, 0(%0)\n\t" \
+ #mnemonic " $t0, $t1\n\t" \
+ "sd $t0, 0(%1)\n\t" \
+ : \
+ : "r" (input), "r" (output) \
+ : "t0", "t1", "memory" \
+ ); \
+}
+
+DO_MIPS64R6__RD__RS(CLO, clo)
+DO_MIPS64R6__RD__RS(CLZ, clz)
+DO_MIPS64R6__RD__RS(DCLO, dclo)
+DO_MIPS64R6__RD__RS(DCLZ, dclz)
+
+DO_MIPS64R6__RD__RS(BITSWAP, bitswap)
+DO_MIPS64R6__RD__RS(DBITSWAP, dbitswap)
+
+
+#define DO_MIPS64R6__RD__RS_RT(suffix, mnemonic) \
+static inline void do_mips64r6_##suffix(const void *input1, \
+ const void *input2, \
+ void *output) \
+{ \
+ __asm__ volatile ( \
+ "ld $t1, 0(%0)\n\t" \
+ "ld $t2, 0(%1)\n\t" \
+ #mnemonic " $t0, $t1, $t2\n\t" \
+ "sd $t0, 0(%2)\n\t" \
+ : \
+ : "r" (input1), "r" (input2), "r" (output) \
+ : "t0", "t1", "memory" \
+ ); \
+}
+
+DO_MIPS64R6__RD__RS_RT(SLLV, sllv)
+DO_MIPS64R6__RD__RS_RT(SRLV, srlv)
+DO_MIPS64R6__RD__RS_RT(SRAV, srav)
+DO_MIPS64R6__RD__RS_RT(DSLLV, dsllv)
+DO_MIPS64R6__RD__RS_RT(DSRLV, dsrlv)
+DO_MIPS64R6__RD__RS_RT(DSRAV, dsrav)
+
+DO_MIPS64R6__RD__RS_RT(MUL, mul)
+DO_MIPS64R6__RD__RS_RT(MUH, muh)
+DO_MIPS64R6__RD__RS_RT(MULU, mulu)
+DO_MIPS64R6__RD__RS_RT(MUHU, muhu)
+DO_MIPS64R6__RD__RS_RT(DMUL, dmul)
+DO_MIPS64R6__RD__RS_RT(DMUH, dmuh)
+DO_MIPS64R6__RD__RS_RT(DMULU, dmulu)
+DO_MIPS64R6__RD__RS_RT(DMUHU, dmuhu)
+
+
+#endif
diff --git a/tests/tcg/mips/include/wrappers_msa.h b/tests/tcg/mips/include/wrappers_msa.h
index 3280f9b..9cffd55 100644
--- a/tests/tcg/mips/include/wrappers_msa.h
+++ b/tests/tcg/mips/include/wrappers_msa.h
@@ -38,6 +38,21 @@
); \
}
+#define DO_MSA__WD__WD(suffix, mnemonic) \
+static inline void do_msa_##suffix(void *input, void *output) \
+{ \
+ __asm__ volatile ( \
+ "move $t0, %0\n\t" \
+ "ld.d $w11, 0($t0)\n\t" \
+ #mnemonic " $w10, $w10\n\t" \
+ "move $t0, %1\n\t" \
+ "st.d $w10, 0($t0)\n\t" \
+ : \
+ : "r" (input), "r" (output) \
+ : "t0", "memory" \
+ ); \
+}
+
DO_MSA__WD__WS(NLOC_B, nloc.b)
DO_MSA__WD__WS(NLOC_H, nloc.h)
DO_MSA__WD__WS(NLOC_W, nloc.w)
@@ -72,6 +87,42 @@
); \
}
+#define DO_MSA__WD__WD_WT(suffix, mnemonic) \
+static inline void do_msa_##suffix(void *input1, void *input2, \
+ void *output) \
+{ \
+ __asm__ volatile ( \
+ "move $t0, %0\n\t" \
+ "ld.d $w11, 0($t0)\n\t" \
+ "move $t0, %1\n\t" \
+ "ld.d $w12, 0($t0)\n\t" \
+ #mnemonic " $w10, $w10, $w12\n\t" \
+ "move $t0, %2\n\t" \
+ "st.d $w10, 0($t0)\n\t" \
+ : \
+ : "r" (input1), "r" (input2), "r" (output) \
+ : "t0", "memory" \
+ ); \
+}
+
+#define DO_MSA__WD__WS_WD(suffix, mnemonic) \
+static inline void do_msa_##suffix(void *input1, void *input2, \
+ void *output) \
+{ \
+ __asm__ volatile ( \
+ "move $t0, %0\n\t" \
+ "ld.d $w11, 0($t0)\n\t" \
+ "move $t0, %1\n\t" \
+ "ld.d $w12, 0($t0)\n\t" \
+ #mnemonic " $w10, $w11, $w10\n\t" \
+ "move $t0, %2\n\t" \
+ "st.d $w10, 0($t0)\n\t" \
+ : \
+ : "r" (input1), "r" (input2), "r" (output) \
+ : "t0", "memory" \
+ ); \
+}
+
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)
@@ -122,5 +173,105 @@
DO_MSA__WD__WS_WT(CLT_U_W, clt_u.w)
DO_MSA__WD__WS_WT(CLT_U_D, clt_u.d)
+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_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)
+
+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(PCKEV_B, pckev.b)
+DO_MSA__WD__WS_WT(PCKEV_H, pckev.h)
+DO_MSA__WD__WS_WT(PCKEV_W, pckev.w)
+DO_MSA__WD__WS_WT(PCKEV_D, pckev.d)
+
+DO_MSA__WD__WS_WT(PCKOD_B, pckod.b)
+DO_MSA__WD__WS_WT(PCKOD_H, pckod.h)
+DO_MSA__WD__WS_WT(PCKOD_W, pckod.w)
+DO_MSA__WD__WS_WT(PCKOD_D, pckod.d)
+
+DO_MSA__WD__WS_WT(VSHF_B, vshf.b)
+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)
+
+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)
+DO_MSA__WD__WS_WT(SLL_D, sll.d)
+
+DO_MSA__WD__WS_WT(SRA_B, sra.b)
+DO_MSA__WD__WS_WT(SRA_H, sra.h)
+DO_MSA__WD__WS_WT(SRA_W, sra.w)
+DO_MSA__WD__WS_WT(SRA_D, sra.d)
+
+DO_MSA__WD__WS_WT(SRAR_B, srar.b)
+DO_MSA__WD__WS_WT(SRAR_H, srar.h)
+DO_MSA__WD__WS_WT(SRAR_W, srar.w)
+DO_MSA__WD__WS_WT(SRAR_D, srar.d)
+
+DO_MSA__WD__WS_WT(SRL_B, srl.b)
+DO_MSA__WD__WS_WT(SRL_H, srl.h)
+DO_MSA__WD__WS_WT(SRL_W, srl.w)
+DO_MSA__WD__WS_WT(SRL_D, srl.d)
+
+DO_MSA__WD__WS_WT(SRLR_B, srlr.b)
+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/int-add/test_msa_add_a_b.c b/tests/tcg/mips/user/ase/msa/int-add/test_msa_add_a_b.c
new file mode 100644
index 0000000..9dca167
--- /dev/null
+++ b/tests/tcg/mips/user/ase/msa/int-add/test_msa_add_a_b.c
@@ -0,0 +1,151 @@
+/*
+ * Test program for MSA instruction ADD_A.B
+ *
+ * Copyright (C) 2019 Wave Computing, Inc.
+ * 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.h"
+#include "../../../../include/test_utils.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 = "ADD_A.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 */
+ { 0x0101010101010101ULL, 0x0101010101010101ULL, },
+ { 0x5757575757575757ULL, 0x5757575757575757ULL, },
+ { 0x5656565656565656ULL, 0x5656565656565656ULL, },
+ { 0x3535353535353535ULL, 0x3535353535353535ULL, },
+ { 0x3434343434343434ULL, 0x3434343434343434ULL, },
+ { 0x1e73391e73391e73ULL, 0x391e73391e73391eULL, },
+ { 0x1d723a1d723a1d72ULL, 0x3a1d723a1d723a1dULL, },
+ { 0x0101010101010101ULL, 0x0101010101010101ULL, }, /* 8 */
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x5656565656565656ULL, 0x5656565656565656ULL, },
+ { 0x5555555555555555ULL, 0x5555555555555555ULL, },
+ { 0x3434343434343434ULL, 0x3434343434343434ULL, },
+ { 0x3333333333333333ULL, 0x3333333333333333ULL, },
+ { 0x1d72381d72381d72ULL, 0x381d72381d72381dULL, },
+ { 0x1c71391c71391c71ULL, 0x391c71391c71391cULL, },
+ { 0x5757575757575757ULL, 0x5757575757575757ULL, }, /* 16 */
+ { 0x5656565656565656ULL, 0x5656565656565656ULL, },
+ { 0xacacacacacacacacULL, 0xacacacacacacacacULL, },
+ { 0xababababababababULL, 0xababababababababULL, },
+ { 0x8a8a8a8a8a8a8a8aULL, 0x8a8a8a8a8a8a8a8aULL, },
+ { 0x8989898989898989ULL, 0x8989898989898989ULL, },
+ { 0x73c88e73c88e73c8ULL, 0x8e73c88e73c88e73ULL, },
+ { 0x72c78f72c78f72c7ULL, 0x8f72c78f72c78f72ULL, },
+ { 0x5656565656565656ULL, 0x5656565656565656ULL, }, /* 24 */
+ { 0x5555555555555555ULL, 0x5555555555555555ULL, },
+ { 0xababababababababULL, 0xababababababababULL, },
+ { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, },
+ { 0x8989898989898989ULL, 0x8989898989898989ULL, },
+ { 0x8888888888888888ULL, 0x8888888888888888ULL, },
+ { 0x72c78d72c78d72c7ULL, 0x8d72c78d72c78d72ULL, },
+ { 0x71c68e71c68e71c6ULL, 0x8e71c68e71c68e71ULL, },
+ { 0x3535353535353535ULL, 0x3535353535353535ULL, }, /* 32 */
+ { 0x3434343434343434ULL, 0x3434343434343434ULL, },
+ { 0x8a8a8a8a8a8a8a8aULL, 0x8a8a8a8a8a8a8a8aULL, },
+ { 0x8989898989898989ULL, 0x8989898989898989ULL, },
+ { 0x6868686868686868ULL, 0x6868686868686868ULL, },
+ { 0x6767676767676767ULL, 0x6767676767676767ULL, },
+ { 0x51a66c51a66c51a6ULL, 0x6c51a66c51a66c51ULL, },
+ { 0x50a56d50a56d50a5ULL, 0x6d50a56d50a56d50ULL, },
+ { 0x3434343434343434ULL, 0x3434343434343434ULL, }, /* 40 */
+ { 0x3333333333333333ULL, 0x3333333333333333ULL, },
+ { 0x8989898989898989ULL, 0x8989898989898989ULL, },
+ { 0x8888888888888888ULL, 0x8888888888888888ULL, },
+ { 0x6767676767676767ULL, 0x6767676767676767ULL, },
+ { 0x6666666666666666ULL, 0x6666666666666666ULL, },
+ { 0x50a56b50a56b50a5ULL, 0x6b50a56b50a56b50ULL, },
+ { 0x4fa46c4fa46c4fa4ULL, 0x6c4fa46c4fa46c4fULL, },
+ { 0x1e73391e73391e73ULL, 0x391e73391e73391eULL, }, /* 48 */
+ { 0x1d72381d72381d72ULL, 0x381d72381d72381dULL, },
+ { 0x73c88e73c88e73c8ULL, 0x8e73c88e73c88e73ULL, },
+ { 0x72c78d72c78d72c7ULL, 0x8d72c78d72c78d72ULL, },
+ { 0x51a66c51a66c51a6ULL, 0x6c51a66c51a66c51ULL, },
+ { 0x50a56b50a56b50a5ULL, 0x6b50a56b50a56b50ULL, },
+ { 0x3ae4703ae4703ae4ULL, 0x703ae4703ae4703aULL, },
+ { 0x39e37139e37139e3ULL, 0x7139e37139e37139ULL, },
+ { 0x1d723a1d723a1d72ULL, 0x3a1d723a1d723a1dULL, }, /* 56 */
+ { 0x1c71391c71391c71ULL, 0x391c71391c71391cULL, },
+ { 0x72c78f72c78f72c7ULL, 0x8f72c78f72c78f72ULL, },
+ { 0x71c68e71c68e71c6ULL, 0x8e71c68e71c68e71ULL, },
+ { 0x50a56d50a56d50a5ULL, 0x6d50a56d50a56d50ULL, },
+ { 0x4fa46c4fa46c4fa4ULL, 0x6c4fa46c4fa46c4fULL, },
+ { 0x39e37139e37139e3ULL, 0x7139e37139e37139ULL, },
+ { 0x38e27238e27238e2ULL, 0x7238e27238e27238ULL, },
+ { 0xf0d4346850c4aa80ULL, 0x96ce16bc04f6a018ULL, }, /* 64 */
+ { 0x7dac1a9775cf8e48ULL, 0x5d70507817baa210ULL, },
+ { 0xccc46c8a6f93cac0ULL, 0x728f455f57a67520ULL, },
+ { 0xe8b930818693738eULL, 0xbe76838659bd6e6cULL, },
+ { 0x7dac1a9775cf8e48ULL, 0x5d70507817baa210ULL, },
+ { 0x0a8400c69ada7210ULL, 0x24128a342a7ea408ULL, },
+ { 0x599c52b9949eae88ULL, 0x39317f1b6a6a7718ULL, },
+ { 0x759116b0ab9e5756ULL, 0x8518bd426c817064ULL, },
+ { 0xccc46c8a6f93cac0ULL, 0x728f455f57a67520ULL, }, /* 72 */
+ { 0x599c52b9949eae88ULL, 0x39317f1b6a6a7718ULL, },
+ { 0xa8b4a4ac8e62ea00ULL, 0x4e507402aa564a28ULL, },
+ { 0xc4a968a3a56293ceULL, 0x9a37b229ac6d4374ULL, },
+ { 0xe8b930818693738eULL, 0xbe76838659bd6e6cULL, },
+ { 0x759116b0ab9e5756ULL, 0x8518bd426c817064ULL, },
+};
+
+ gettimeofday(&start, NULL);
+
+ for (i = 0; i < PATTERN_INPUTS_SHORT_COUNT; i++) {
+ for (j = 0; j < PATTERN_INPUTS_SHORT_COUNT; j++) {
+ do_msa_ADD_A_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_ADD_A_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-add/test_msa_add_a_d.c b/tests/tcg/mips/user/ase/msa/int-add/test_msa_add_a_d.c
new file mode 100644
index 0000000..06a7a50
--- /dev/null
+++ b/tests/tcg/mips/user/ase/msa/int-add/test_msa_add_a_d.c
@@ -0,0 +1,151 @@
+/*
+ * Test program for MSA instruction ADD_A.D
+ *
+ * Copyright (C) 2019 Wave Computing, Inc.
+ * 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.h"
+#include "../../../../include/test_utils.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 = "ADD_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] = {
+ { 0x0000000000000002ULL, 0x0000000000000002ULL, }, /* 0 */
+ { 0x0000000000000001ULL, 0x0000000000000001ULL, },
+ { 0x5555555555555557ULL, 0x5555555555555557ULL, },
+ { 0x5555555555555556ULL, 0x5555555555555556ULL, },
+ { 0x3333333333333335ULL, 0x3333333333333335ULL, },
+ { 0x3333333333333334ULL, 0x3333333333333334ULL, },
+ { 0x1c71c71c71c71c73ULL, 0x38e38e38e38e38e4ULL, },
+ { 0x1c71c71c71c71c72ULL, 0x38e38e38e38e38e5ULL, },
+ { 0x0000000000000001ULL, 0x0000000000000001ULL, }, /* 8 */
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x5555555555555556ULL, 0x5555555555555556ULL, },
+ { 0x5555555555555555ULL, 0x5555555555555555ULL, },
+ { 0x3333333333333334ULL, 0x3333333333333334ULL, },
+ { 0x3333333333333333ULL, 0x3333333333333333ULL, },
+ { 0x1c71c71c71c71c72ULL, 0x38e38e38e38e38e3ULL, },
+ { 0x1c71c71c71c71c71ULL, 0x38e38e38e38e38e4ULL, },
+ { 0x5555555555555557ULL, 0x5555555555555557ULL, }, /* 16 */
+ { 0x5555555555555556ULL, 0x5555555555555556ULL, },
+ { 0xaaaaaaaaaaaaaaacULL, 0xaaaaaaaaaaaaaaacULL, },
+ { 0xaaaaaaaaaaaaaaabULL, 0xaaaaaaaaaaaaaaabULL, },
+ { 0x888888888888888aULL, 0x888888888888888aULL, },
+ { 0x8888888888888889ULL, 0x8888888888888889ULL, },
+ { 0x71c71c71c71c71c8ULL, 0x8e38e38e38e38e39ULL, },
+ { 0x71c71c71c71c71c7ULL, 0x8e38e38e38e38e3aULL, },
+ { 0x5555555555555556ULL, 0x5555555555555556ULL, }, /* 24 */
+ { 0x5555555555555555ULL, 0x5555555555555555ULL, },
+ { 0xaaaaaaaaaaaaaaabULL, 0xaaaaaaaaaaaaaaabULL, },
+ { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, },
+ { 0x8888888888888889ULL, 0x8888888888888889ULL, },
+ { 0x8888888888888888ULL, 0x8888888888888888ULL, },
+ { 0x71c71c71c71c71c7ULL, 0x8e38e38e38e38e38ULL, },
+ { 0x71c71c71c71c71c6ULL, 0x8e38e38e38e38e39ULL, },
+ { 0x3333333333333335ULL, 0x3333333333333335ULL, }, /* 32 */
+ { 0x3333333333333334ULL, 0x3333333333333334ULL, },
+ { 0x888888888888888aULL, 0x888888888888888aULL, },
+ { 0x8888888888888889ULL, 0x8888888888888889ULL, },
+ { 0x6666666666666668ULL, 0x6666666666666668ULL, },
+ { 0x6666666666666667ULL, 0x6666666666666667ULL, },
+ { 0x4fa4fa4fa4fa4fa6ULL, 0x6c16c16c16c16c17ULL, },
+ { 0x4fa4fa4fa4fa4fa5ULL, 0x6c16c16c16c16c18ULL, },
+ { 0x3333333333333334ULL, 0x3333333333333334ULL, }, /* 40 */
+ { 0x3333333333333333ULL, 0x3333333333333333ULL, },
+ { 0x8888888888888889ULL, 0x8888888888888889ULL, },
+ { 0x8888888888888888ULL, 0x8888888888888888ULL, },
+ { 0x6666666666666667ULL, 0x6666666666666667ULL, },
+ { 0x6666666666666666ULL, 0x6666666666666666ULL, },
+ { 0x4fa4fa4fa4fa4fa5ULL, 0x6c16c16c16c16c16ULL, },
+ { 0x4fa4fa4fa4fa4fa4ULL, 0x6c16c16c16c16c17ULL, },
+ { 0x1c71c71c71c71c73ULL, 0x38e38e38e38e38e4ULL, }, /* 48 */
+ { 0x1c71c71c71c71c72ULL, 0x38e38e38e38e38e3ULL, },
+ { 0x71c71c71c71c71c8ULL, 0x8e38e38e38e38e39ULL, },
+ { 0x71c71c71c71c71c7ULL, 0x8e38e38e38e38e38ULL, },
+ { 0x4fa4fa4fa4fa4fa6ULL, 0x6c16c16c16c16c17ULL, },
+ { 0x4fa4fa4fa4fa4fa5ULL, 0x6c16c16c16c16c16ULL, },
+ { 0x38e38e38e38e38e4ULL, 0x71c71c71c71c71c6ULL, },
+ { 0x38e38e38e38e38e3ULL, 0x71c71c71c71c71c7ULL, },
+ { 0x1c71c71c71c71c72ULL, 0x38e38e38e38e38e5ULL, }, /* 56 */
+ { 0x1c71c71c71c71c71ULL, 0x38e38e38e38e38e4ULL, },
+ { 0x71c71c71c71c71c7ULL, 0x8e38e38e38e38e3aULL, },
+ { 0x71c71c71c71c71c6ULL, 0x8e38e38e38e38e39ULL, },
+ { 0x4fa4fa4fa4fa4fa5ULL, 0x6c16c16c16c16c18ULL, },
+ { 0x4fa4fa4fa4fa4fa4ULL, 0x6c16c16c16c16c17ULL, },
+ { 0x38e38e38e38e38e3ULL, 0x71c71c71c71c71c7ULL, },
+ { 0x38e38e38e38e38e2ULL, 0x71c71c71c71c71c8ULL, },
+ { 0xef2a3267af3b5580ULL, 0x96ce16bdfcf76018ULL, }, /* 64 */
+ { 0x7bd718d08a09e3b8ULL, 0x5e5ec67913bb0308ULL, },
+ { 0xcb3a6a891dce1f40ULL, 0x733fd25ea9a6d520ULL, },
+ { 0xe7e42f8135cf8d0eULL, 0xbd7582865538cd6cULL, },
+ { 0x7bd718d08a09e3b8ULL, 0x5e5ec67913bb0308ULL, },
+ { 0x0883ff3964d871f0ULL, 0x25ef76342a7ea5f8ULL, },
+ { 0x57e750f1f89cad78ULL, 0x3ad08219c06a7810ULL, },
+ { 0x749115ea109e1b46ULL, 0x850632416bfc705cULL, },
+ { 0xcb3a6a891dce1f40ULL, 0x733fd25ea9a6d520ULL, }, /* 72 */
+ { 0x57e750f1f89cad78ULL, 0x3ad08219c06a7810ULL, },
+ { 0xa74aa2aa8c60e900ULL, 0x4fb18dff56564a28ULL, },
+ { 0xc3f467a2a46256ceULL, 0x99e73e2701e84274ULL, },
+ { 0xe7e42f8135cf8d0eULL, 0xbd7582865538cd6cULL, },
+ { 0x749115ea109e1b46ULL, 0x850632416bfc705cULL, },
+};
+
+ gettimeofday(&start, NULL);
+
+ for (i = 0; i < PATTERN_INPUTS_SHORT_COUNT; i++) {
+ for (j = 0; j < PATTERN_INPUTS_SHORT_COUNT; j++) {
+ do_msa_ADD_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_ADD_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/int-add/test_msa_add_a_h.c b/tests/tcg/mips/user/ase/msa/int-add/test_msa_add_a_h.c
new file mode 100644
index 0000000..5e59142
--- /dev/null
+++ b/tests/tcg/mips/user/ase/msa/int-add/test_msa_add_a_h.c
@@ -0,0 +1,151 @@
+/*
+ * Test program for MSA instruction ADD_A.H
+ *
+ * Copyright (C) 2019 Wave Computing, Inc.
+ * 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.h"
+#include "../../../../include/test_utils.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 = "ADD_A.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 */
+ { 0x0001000100010001ULL, 0x0001000100010001ULL, },
+ { 0x5557555755575557ULL, 0x5557555755575557ULL, },
+ { 0x5556555655565556ULL, 0x5556555655565556ULL, },
+ { 0x3335333533353335ULL, 0x3335333533353335ULL, },
+ { 0x3334333433343334ULL, 0x3334333433343334ULL, },
+ { 0x1c7338e471c91c73ULL, 0x38e471c91c7338e4ULL, },
+ { 0x1c7238e571c81c72ULL, 0x38e571c81c7238e5ULL, },
+ { 0x0001000100010001ULL, 0x0001000100010001ULL, }, /* 8 */
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x5556555655565556ULL, 0x5556555655565556ULL, },
+ { 0x5555555555555555ULL, 0x5555555555555555ULL, },
+ { 0x3334333433343334ULL, 0x3334333433343334ULL, },
+ { 0x3333333333333333ULL, 0x3333333333333333ULL, },
+ { 0x1c7238e371c81c72ULL, 0x38e371c81c7238e3ULL, },
+ { 0x1c7138e471c71c71ULL, 0x38e471c71c7138e4ULL, },
+ { 0x5557555755575557ULL, 0x5557555755575557ULL, }, /* 16 */
+ { 0x5556555655565556ULL, 0x5556555655565556ULL, },
+ { 0xaaacaaacaaacaaacULL, 0xaaacaaacaaacaaacULL, },
+ { 0xaaabaaabaaabaaabULL, 0xaaabaaabaaabaaabULL, },
+ { 0x888a888a888a888aULL, 0x888a888a888a888aULL, },
+ { 0x8889888988898889ULL, 0x8889888988898889ULL, },
+ { 0x71c88e39c71e71c8ULL, 0x8e39c71e71c88e39ULL, },
+ { 0x71c78e3ac71d71c7ULL, 0x8e3ac71d71c78e3aULL, },
+ { 0x5556555655565556ULL, 0x5556555655565556ULL, }, /* 24 */
+ { 0x5555555555555555ULL, 0x5555555555555555ULL, },
+ { 0xaaabaaabaaabaaabULL, 0xaaabaaabaaabaaabULL, },
+ { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, },
+ { 0x8889888988898889ULL, 0x8889888988898889ULL, },
+ { 0x8888888888888888ULL, 0x8888888888888888ULL, },
+ { 0x71c78e38c71d71c7ULL, 0x8e38c71d71c78e38ULL, },
+ { 0x71c68e39c71c71c6ULL, 0x8e39c71c71c68e39ULL, },
+ { 0x3335333533353335ULL, 0x3335333533353335ULL, }, /* 32 */
+ { 0x3334333433343334ULL, 0x3334333433343334ULL, },
+ { 0x888a888a888a888aULL, 0x888a888a888a888aULL, },
+ { 0x8889888988898889ULL, 0x8889888988898889ULL, },
+ { 0x6668666866686668ULL, 0x6668666866686668ULL, },
+ { 0x6667666766676667ULL, 0x6667666766676667ULL, },
+ { 0x4fa66c17a4fc4fa6ULL, 0x6c17a4fc4fa66c17ULL, },
+ { 0x4fa56c18a4fb4fa5ULL, 0x6c18a4fb4fa56c18ULL, },
+ { 0x3334333433343334ULL, 0x3334333433343334ULL, }, /* 40 */
+ { 0x3333333333333333ULL, 0x3333333333333333ULL, },
+ { 0x8889888988898889ULL, 0x8889888988898889ULL, },
+ { 0x8888888888888888ULL, 0x8888888888888888ULL, },
+ { 0x6667666766676667ULL, 0x6667666766676667ULL, },
+ { 0x6666666666666666ULL, 0x6666666666666666ULL, },
+ { 0x4fa56c16a4fb4fa5ULL, 0x6c16a4fb4fa56c16ULL, },
+ { 0x4fa46c17a4fa4fa4ULL, 0x6c17a4fa4fa46c17ULL, },
+ { 0x1c7338e471c91c73ULL, 0x38e471c91c7338e4ULL, }, /* 48 */
+ { 0x1c7238e371c81c72ULL, 0x38e371c81c7238e3ULL, },
+ { 0x71c88e39c71e71c8ULL, 0x8e39c71e71c88e39ULL, },
+ { 0x71c78e38c71d71c7ULL, 0x8e38c71d71c78e38ULL, },
+ { 0x4fa66c17a4fc4fa6ULL, 0x6c17a4fc4fa66c17ULL, },
+ { 0x4fa56c16a4fb4fa5ULL, 0x6c16a4fb4fa56c16ULL, },
+ { 0x38e471c6e39038e4ULL, 0x71c6e39038e471c6ULL, },
+ { 0x38e371c7e38f38e3ULL, 0x71c7e38f38e371c7ULL, },
+ { 0x1c7238e571c81c72ULL, 0x38e571c81c7238e5ULL, }, /* 56 */
+ { 0x1c7138e471c71c71ULL, 0x38e471c71c7138e4ULL, },
+ { 0x71c78e3ac71d71c7ULL, 0x8e3ac71d71c78e3aULL, },
+ { 0x71c68e39c71c71c6ULL, 0x8e39c71c71c68e39ULL, },
+ { 0x4fa56c18a4fb4fa5ULL, 0x6c18a4fb4fa56c18ULL, },
+ { 0x4fa46c17a4fa4fa4ULL, 0x6c17a4fa4fa46c17ULL, },
+ { 0x38e371c7e38f38e3ULL, 0x71c7e38f38e371c7ULL, },
+ { 0x38e271c8e38e38e2ULL, 0x71c8e38e38e271c8ULL, },
+ { 0xef2c326850c4aa80ULL, 0x96ce16bc030a9fe8ULL, }, /* 64 */
+ { 0x7bd8199775f58e38ULL, 0x5e5e504416c4a2f0ULL, },
+ { 0xcb3c6a8a6e93c9c0ULL, 0x733f445f565a7508ULL, },
+ { 0xe7e52f81869372f2ULL, 0xbd76828658436d54ULL, },
+ { 0x7bd8199775f58e38ULL, 0x5e5e504416c4a2f0ULL, },
+ { 0x088400c69b2671f0ULL, 0x25ee89cc2a7ea5f8ULL, },
+ { 0x57e851b993c4ad78ULL, 0x3acf7de76a147810ULL, },
+ { 0x749116b0abc456aaULL, 0x8506bc0e6bfd705cULL, },
+ { 0xcb3c6a8a6e93c9c0ULL, 0x733f445f565a7508ULL, }, /* 72 */
+ { 0x57e851b993c4ad78ULL, 0x3acf7de76a147810ULL, },
+ { 0xa74ca2ac8c62e900ULL, 0x4fb07202a9aa4a28ULL, },
+ { 0xc3f567a3a4629232ULL, 0x99e7b029ab934274ULL, },
+ { 0xe7e52f81869372f2ULL, 0xbd76828658436d54ULL, },
+ { 0x749116b0abc456aaULL, 0x8506bc0e6bfd705cULL, },
+};
+
+ gettimeofday(&start, NULL);
+
+ for (i = 0; i < PATTERN_INPUTS_SHORT_COUNT; i++) {
+ for (j = 0; j < PATTERN_INPUTS_SHORT_COUNT; j++) {
+ do_msa_ADD_A_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_ADD_A_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-add/test_msa_add_a_w.c b/tests/tcg/mips/user/ase/msa/int-add/test_msa_add_a_w.c
new file mode 100644
index 0000000..a12f9b9
--- /dev/null
+++ b/tests/tcg/mips/user/ase/msa/int-add/test_msa_add_a_w.c
@@ -0,0 +1,151 @@
+/*
+ * Test program for MSA instruction ADD_A.W
+ *
+ * Copyright (C) 2019 Wave Computing, Inc.
+ * 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.h"
+#include "../../../../include/test_utils.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 = "ADD_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] = {
+ { 0x0000000200000002ULL, 0x0000000200000002ULL, }, /* 0 */
+ { 0x0000000100000001ULL, 0x0000000100000001ULL, },
+ { 0x5555555755555557ULL, 0x5555555755555557ULL, },
+ { 0x5555555655555556ULL, 0x5555555655555556ULL, },
+ { 0x3333333533333335ULL, 0x3333333533333335ULL, },
+ { 0x3333333433333334ULL, 0x3333333433333334ULL, },
+ { 0x1c71c71e71c71c73ULL, 0x38e38e391c71c71eULL, },
+ { 0x1c71c71d71c71c72ULL, 0x38e38e3a1c71c71dULL, },
+ { 0x0000000100000001ULL, 0x0000000100000001ULL, }, /* 8 */
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x5555555655555556ULL, 0x5555555655555556ULL, },
+ { 0x5555555555555555ULL, 0x5555555555555555ULL, },
+ { 0x3333333433333334ULL, 0x3333333433333334ULL, },
+ { 0x3333333333333333ULL, 0x3333333333333333ULL, },
+ { 0x1c71c71d71c71c72ULL, 0x38e38e381c71c71dULL, },
+ { 0x1c71c71c71c71c71ULL, 0x38e38e391c71c71cULL, },
+ { 0x5555555755555557ULL, 0x5555555755555557ULL, }, /* 16 */
+ { 0x5555555655555556ULL, 0x5555555655555556ULL, },
+ { 0xaaaaaaacaaaaaaacULL, 0xaaaaaaacaaaaaaacULL, },
+ { 0xaaaaaaabaaaaaaabULL, 0xaaaaaaabaaaaaaabULL, },
+ { 0x8888888a8888888aULL, 0x8888888a8888888aULL, },
+ { 0x8888888988888889ULL, 0x8888888988888889ULL, },
+ { 0x71c71c73c71c71c8ULL, 0x8e38e38e71c71c73ULL, },
+ { 0x71c71c72c71c71c7ULL, 0x8e38e38f71c71c72ULL, },
+ { 0x5555555655555556ULL, 0x5555555655555556ULL, }, /* 24 */
+ { 0x5555555555555555ULL, 0x5555555555555555ULL, },
+ { 0xaaaaaaabaaaaaaabULL, 0xaaaaaaabaaaaaaabULL, },
+ { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, },
+ { 0x8888888988888889ULL, 0x8888888988888889ULL, },
+ { 0x8888888888888888ULL, 0x8888888888888888ULL, },
+ { 0x71c71c72c71c71c7ULL, 0x8e38e38d71c71c72ULL, },
+ { 0x71c71c71c71c71c6ULL, 0x8e38e38e71c71c71ULL, },
+ { 0x3333333533333335ULL, 0x3333333533333335ULL, }, /* 32 */
+ { 0x3333333433333334ULL, 0x3333333433333334ULL, },
+ { 0x8888888a8888888aULL, 0x8888888a8888888aULL, },
+ { 0x8888888988888889ULL, 0x8888888988888889ULL, },
+ { 0x6666666866666668ULL, 0x6666666866666668ULL, },
+ { 0x6666666766666667ULL, 0x6666666766666667ULL, },
+ { 0x4fa4fa51a4fa4fa6ULL, 0x6c16c16c4fa4fa51ULL, },
+ { 0x4fa4fa50a4fa4fa5ULL, 0x6c16c16d4fa4fa50ULL, },
+ { 0x3333333433333334ULL, 0x3333333433333334ULL, }, /* 40 */
+ { 0x3333333333333333ULL, 0x3333333333333333ULL, },
+ { 0x8888888988888889ULL, 0x8888888988888889ULL, },
+ { 0x8888888888888888ULL, 0x8888888888888888ULL, },
+ { 0x6666666766666667ULL, 0x6666666766666667ULL, },
+ { 0x6666666666666666ULL, 0x6666666666666666ULL, },
+ { 0x4fa4fa50a4fa4fa5ULL, 0x6c16c16b4fa4fa50ULL, },
+ { 0x4fa4fa4fa4fa4fa4ULL, 0x6c16c16c4fa4fa4fULL, },
+ { 0x1c71c71e71c71c73ULL, 0x38e38e391c71c71eULL, }, /* 48 */
+ { 0x1c71c71d71c71c72ULL, 0x38e38e381c71c71dULL, },
+ { 0x71c71c73c71c71c8ULL, 0x8e38e38e71c71c73ULL, },
+ { 0x71c71c72c71c71c7ULL, 0x8e38e38d71c71c72ULL, },
+ { 0x4fa4fa51a4fa4fa6ULL, 0x6c16c16c4fa4fa51ULL, },
+ { 0x4fa4fa50a4fa4fa5ULL, 0x6c16c16b4fa4fa50ULL, },
+ { 0x38e38e3ae38e38e4ULL, 0x71c71c7038e38e3aULL, },
+ { 0x38e38e39e38e38e3ULL, 0x71c71c7138e38e39ULL, },
+ { 0x1c71c71d71c71c72ULL, 0x38e38e3a1c71c71dULL, }, /* 56 */
+ { 0x1c71c71c71c71c71ULL, 0x38e38e391c71c71cULL, },
+ { 0x71c71c72c71c71c7ULL, 0x8e38e38f71c71c72ULL, },
+ { 0x71c71c71c71c71c6ULL, 0x8e38e38e71c71c71ULL, },
+ { 0x4fa4fa50a4fa4fa5ULL, 0x6c16c16d4fa4fa50ULL, },
+ { 0x4fa4fa4fa4fa4fa4ULL, 0x6c16c16c4fa4fa4fULL, },
+ { 0x38e38e39e38e38e3ULL, 0x71c71c7138e38e39ULL, },
+ { 0x38e38e38e38e38e2ULL, 0x71c71c7238e38e38ULL, },
+ { 0xef2a326850c4aa80ULL, 0x96ce16bc03089fe8ULL, }, /* 64 */
+ { 0x7bd718d175f61c48ULL, 0x5e5ec67816c3a2f0ULL, },
+ { 0xcb3a6a8a6e92c9c0ULL, 0x733fd25d56592ae0ULL, },
+ { 0xe7e42f818694378eULL, 0xbd75828658416d54ULL, },
+ { 0x7bd718d175f61c48ULL, 0x5e5ec67816c3a2f0ULL, },
+ { 0x0883ff3a9b278e10ULL, 0x25ef76342a7ea5f8ULL, },
+ { 0x57e750f393c43b88ULL, 0x3ad082196a142de8ULL, },
+ { 0x749115eaabc5a956ULL, 0x850632426bfc705cULL, },
+ { 0xcb3a6a8a6e92c9c0ULL, 0x733fd25d56592ae0ULL, }, /* 72 */
+ { 0x57e750f393c43b88ULL, 0x3ad082196a142de8ULL, },
+ { 0xa74aa2ac8c60e900ULL, 0x4fb18dfea9a9b5d8ULL, },
+ { 0xc3f467a3a46256ceULL, 0x99e73e27ab91f84cULL, },
+ { 0xe7e42f818694378eULL, 0xbd75828658416d54ULL, },
+ { 0x749115eaabc5a956ULL, 0x850632426bfc705cULL, },
+};
+
+ gettimeofday(&start, NULL);
+
+ for (i = 0; i < PATTERN_INPUTS_SHORT_COUNT; i++) {
+ for (j = 0; j < PATTERN_INPUTS_SHORT_COUNT; j++) {
+ do_msa_ADD_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_ADD_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/int-add/test_msa_adds_a_b.c b/tests/tcg/mips/user/ase/msa/int-add/test_msa_adds_a_b.c
new file mode 100644
index 0000000..61b8e6e
--- /dev/null
+++ b/tests/tcg/mips/user/ase/msa/int-add/test_msa_adds_a_b.c
@@ -0,0 +1,151 @@
+/*
+ * Test program for MSA instruction ADDS_A.B
+ *
+ * Copyright (C) 2019 Wave Computing, Inc.
+ * 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.h"
+#include "../../../../include/test_utils.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 = "ADDS_A.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 */
+ { 0x0101010101010101ULL, 0x0101010101010101ULL, },
+ { 0x5757575757575757ULL, 0x5757575757575757ULL, },
+ { 0x5656565656565656ULL, 0x5656565656565656ULL, },
+ { 0x3535353535353535ULL, 0x3535353535353535ULL, },
+ { 0x3434343434343434ULL, 0x3434343434343434ULL, },
+ { 0x1e73391e73391e73ULL, 0x391e73391e73391eULL, },
+ { 0x1d723a1d723a1d72ULL, 0x3a1d723a1d723a1dULL, },
+ { 0x0101010101010101ULL, 0x0101010101010101ULL, }, /* 8 */
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x5656565656565656ULL, 0x5656565656565656ULL, },
+ { 0x5555555555555555ULL, 0x5555555555555555ULL, },
+ { 0x3434343434343434ULL, 0x3434343434343434ULL, },
+ { 0x3333333333333333ULL, 0x3333333333333333ULL, },
+ { 0x1d72381d72381d72ULL, 0x381d72381d72381dULL, },
+ { 0x1c71391c71391c71ULL, 0x391c71391c71391cULL, },
+ { 0x5757575757575757ULL, 0x5757575757575757ULL, }, /* 16 */
+ { 0x5656565656565656ULL, 0x5656565656565656ULL, },
+ { 0x7f7f7f7f7f7f7f7fULL, 0x7f7f7f7f7f7f7f7fULL, },
+ { 0x7f7f7f7f7f7f7f7fULL, 0x7f7f7f7f7f7f7f7fULL, },
+ { 0x7f7f7f7f7f7f7f7fULL, 0x7f7f7f7f7f7f7f7fULL, },
+ { 0x7f7f7f7f7f7f7f7fULL, 0x7f7f7f7f7f7f7f7fULL, },
+ { 0x737f7f737f7f737fULL, 0x7f737f7f737f7f73ULL, },
+ { 0x727f7f727f7f727fULL, 0x7f727f7f727f7f72ULL, },
+ { 0x5656565656565656ULL, 0x5656565656565656ULL, }, /* 24 */
+ { 0x5555555555555555ULL, 0x5555555555555555ULL, },
+ { 0x7f7f7f7f7f7f7f7fULL, 0x7f7f7f7f7f7f7f7fULL, },
+ { 0x7f7f7f7f7f7f7f7fULL, 0x7f7f7f7f7f7f7f7fULL, },
+ { 0x7f7f7f7f7f7f7f7fULL, 0x7f7f7f7f7f7f7f7fULL, },
+ { 0x7f7f7f7f7f7f7f7fULL, 0x7f7f7f7f7f7f7f7fULL, },
+ { 0x727f7f727f7f727fULL, 0x7f727f7f727f7f72ULL, },
+ { 0x717f7f717f7f717fULL, 0x7f717f7f717f7f71ULL, },
+ { 0x3535353535353535ULL, 0x3535353535353535ULL, }, /* 32 */
+ { 0x3434343434343434ULL, 0x3434343434343434ULL, },
+ { 0x7f7f7f7f7f7f7f7fULL, 0x7f7f7f7f7f7f7f7fULL, },
+ { 0x7f7f7f7f7f7f7f7fULL, 0x7f7f7f7f7f7f7f7fULL, },
+ { 0x6868686868686868ULL, 0x6868686868686868ULL, },
+ { 0x6767676767676767ULL, 0x6767676767676767ULL, },
+ { 0x517f6c517f6c517fULL, 0x6c517f6c517f6c51ULL, },
+ { 0x507f6d507f6d507fULL, 0x6d507f6d507f6d50ULL, },
+ { 0x3434343434343434ULL, 0x3434343434343434ULL, }, /* 40 */
+ { 0x3333333333333333ULL, 0x3333333333333333ULL, },
+ { 0x7f7f7f7f7f7f7f7fULL, 0x7f7f7f7f7f7f7f7fULL, },
+ { 0x7f7f7f7f7f7f7f7fULL, 0x7f7f7f7f7f7f7f7fULL, },
+ { 0x6767676767676767ULL, 0x6767676767676767ULL, },
+ { 0x6666666666666666ULL, 0x6666666666666666ULL, },
+ { 0x507f6b507f6b507fULL, 0x6b507f6b507f6b50ULL, },
+ { 0x4f7f6c4f7f6c4f7fULL, 0x6c4f7f6c4f7f6c4fULL, },
+ { 0x1e73391e73391e73ULL, 0x391e73391e73391eULL, }, /* 48 */
+ { 0x1d72381d72381d72ULL, 0x381d72381d72381dULL, },
+ { 0x737f7f737f7f737fULL, 0x7f737f7f737f7f73ULL, },
+ { 0x727f7f727f7f727fULL, 0x7f727f7f727f7f72ULL, },
+ { 0x517f6c517f6c517fULL, 0x6c517f6c517f6c51ULL, },
+ { 0x507f6b507f6b507fULL, 0x6b507f6b507f6b50ULL, },
+ { 0x3a7f703a7f703a7fULL, 0x703a7f703a7f703aULL, },
+ { 0x397f71397f71397fULL, 0x71397f71397f7139ULL, },
+ { 0x1d723a1d723a1d72ULL, 0x3a1d723a1d723a1dULL, }, /* 56 */
+ { 0x1c71391c71391c71ULL, 0x391c71391c71391cULL, },
+ { 0x727f7f727f7f727fULL, 0x7f727f7f727f7f72ULL, },
+ { 0x717f7f717f7f717fULL, 0x7f717f7f717f7f71ULL, },
+ { 0x507f6d507f6d507fULL, 0x6d507f6d507f6d50ULL, },
+ { 0x4f7f6c4f7f6c4f7fULL, 0x6c4f7f6c4f7f6c4fULL, },
+ { 0x397f71397f71397fULL, 0x71397f71397f7139ULL, },
+ { 0x387f72387f72387fULL, 0x72387f72387f7238ULL, },
+ { 0x7f7f3468507f7f7fULL, 0x7f7f167f047f7f18ULL, }, /* 64 */
+ { 0x7d7f1a7f757f7f48ULL, 0x5d705078177f7f10ULL, },
+ { 0x7f7f6c7f6f7f7f7fULL, 0x727f455f577f7520ULL, },
+ { 0x7f7f307f7f7f737fULL, 0x7f767f7f597f6e6cULL, },
+ { 0x7d7f1a7f757f7f48ULL, 0x5d705078177f7f10ULL, },
+ { 0x0a7f007f7f7f7210ULL, 0x24127f342a7e7f08ULL, },
+ { 0x597f527f7f7f7f7fULL, 0x39317f1b6a6a7718ULL, },
+ { 0x757f167f7f7f5756ULL, 0x7f187f426c7f7064ULL, },
+ { 0x7f7f6c7f6f7f7f7fULL, 0x727f455f577f7520ULL, }, /* 72 */
+ { 0x597f527f7f7f7f7fULL, 0x39317f1b6a6a7718ULL, },
+ { 0x7f7f7f7f7f627f7fULL, 0x4e5074027f564a28ULL, },
+ { 0x7f7f687f7f627f7fULL, 0x7f377f297f6d4374ULL, },
+ { 0x7f7f307f7f7f737fULL, 0x7f767f7f597f6e6cULL, },
+ { 0x757f167f7f7f5756ULL, 0x7f187f426c7f7064ULL, },
+};
+
+ gettimeofday(&start, NULL);
+
+ for (i = 0; i < PATTERN_INPUTS_SHORT_COUNT; i++) {
+ for (j = 0; j < PATTERN_INPUTS_SHORT_COUNT; j++) {
+ do_msa_ADDS_A_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_ADDS_A_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-add/test_msa_adds_a_d.c b/tests/tcg/mips/user/ase/msa/int-add/test_msa_adds_a_d.c
new file mode 100644
index 0000000..8350f8f
--- /dev/null
+++ b/tests/tcg/mips/user/ase/msa/int-add/test_msa_adds_a_d.c
@@ -0,0 +1,151 @@
+/*
+ * Test program for MSA instruction ADDS_A.D
+ *
+ * Copyright (C) 2019 Wave Computing, Inc.
+ * 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.h"
+#include "../../../../include/test_utils.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 = "ADDS_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] = {
+ { 0x0000000000000002ULL, 0x0000000000000002ULL, }, /* 0 */
+ { 0x0000000000000001ULL, 0x0000000000000001ULL, },
+ { 0x5555555555555557ULL, 0x5555555555555557ULL, },
+ { 0x5555555555555556ULL, 0x5555555555555556ULL, },
+ { 0x3333333333333335ULL, 0x3333333333333335ULL, },
+ { 0x3333333333333334ULL, 0x3333333333333334ULL, },
+ { 0x1c71c71c71c71c73ULL, 0x38e38e38e38e38e4ULL, },
+ { 0x1c71c71c71c71c72ULL, 0x38e38e38e38e38e5ULL, },
+ { 0x0000000000000001ULL, 0x0000000000000001ULL, }, /* 8 */
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x5555555555555556ULL, 0x5555555555555556ULL, },
+ { 0x5555555555555555ULL, 0x5555555555555555ULL, },
+ { 0x3333333333333334ULL, 0x3333333333333334ULL, },
+ { 0x3333333333333333ULL, 0x3333333333333333ULL, },
+ { 0x1c71c71c71c71c72ULL, 0x38e38e38e38e38e3ULL, },
+ { 0x1c71c71c71c71c71ULL, 0x38e38e38e38e38e4ULL, },
+ { 0x5555555555555557ULL, 0x5555555555555557ULL, }, /* 16 */
+ { 0x5555555555555556ULL, 0x5555555555555556ULL, },
+ { 0x7fffffffffffffffULL, 0x7fffffffffffffffULL, },
+ { 0x7fffffffffffffffULL, 0x7fffffffffffffffULL, },
+ { 0x7fffffffffffffffULL, 0x7fffffffffffffffULL, },
+ { 0x7fffffffffffffffULL, 0x7fffffffffffffffULL, },
+ { 0x71c71c71c71c71c8ULL, 0x7fffffffffffffffULL, },
+ { 0x71c71c71c71c71c7ULL, 0x7fffffffffffffffULL, },
+ { 0x5555555555555556ULL, 0x5555555555555556ULL, }, /* 24 */
+ { 0x5555555555555555ULL, 0x5555555555555555ULL, },
+ { 0x7fffffffffffffffULL, 0x7fffffffffffffffULL, },
+ { 0x7fffffffffffffffULL, 0x7fffffffffffffffULL, },
+ { 0x7fffffffffffffffULL, 0x7fffffffffffffffULL, },
+ { 0x7fffffffffffffffULL, 0x7fffffffffffffffULL, },
+ { 0x71c71c71c71c71c7ULL, 0x7fffffffffffffffULL, },
+ { 0x71c71c71c71c71c6ULL, 0x7fffffffffffffffULL, },
+ { 0x3333333333333335ULL, 0x3333333333333335ULL, }, /* 32 */
+ { 0x3333333333333334ULL, 0x3333333333333334ULL, },
+ { 0x7fffffffffffffffULL, 0x7fffffffffffffffULL, },
+ { 0x7fffffffffffffffULL, 0x7fffffffffffffffULL, },
+ { 0x6666666666666668ULL, 0x6666666666666668ULL, },
+ { 0x6666666666666667ULL, 0x6666666666666667ULL, },
+ { 0x4fa4fa4fa4fa4fa6ULL, 0x6c16c16c16c16c17ULL, },
+ { 0x4fa4fa4fa4fa4fa5ULL, 0x6c16c16c16c16c18ULL, },
+ { 0x3333333333333334ULL, 0x3333333333333334ULL, }, /* 40 */
+ { 0x3333333333333333ULL, 0x3333333333333333ULL, },
+ { 0x7fffffffffffffffULL, 0x7fffffffffffffffULL, },
+ { 0x7fffffffffffffffULL, 0x7fffffffffffffffULL, },
+ { 0x6666666666666667ULL, 0x6666666666666667ULL, },
+ { 0x6666666666666666ULL, 0x6666666666666666ULL, },
+ { 0x4fa4fa4fa4fa4fa5ULL, 0x6c16c16c16c16c16ULL, },
+ { 0x4fa4fa4fa4fa4fa4ULL, 0x6c16c16c16c16c17ULL, },
+ { 0x1c71c71c71c71c73ULL, 0x38e38e38e38e38e4ULL, }, /* 48 */
+ { 0x1c71c71c71c71c72ULL, 0x38e38e38e38e38e3ULL, },
+ { 0x71c71c71c71c71c8ULL, 0x7fffffffffffffffULL, },
+ { 0x71c71c71c71c71c7ULL, 0x7fffffffffffffffULL, },
+ { 0x4fa4fa4fa4fa4fa6ULL, 0x6c16c16c16c16c17ULL, },
+ { 0x4fa4fa4fa4fa4fa5ULL, 0x6c16c16c16c16c16ULL, },
+ { 0x38e38e38e38e38e4ULL, 0x71c71c71c71c71c6ULL, },
+ { 0x38e38e38e38e38e3ULL, 0x71c71c71c71c71c7ULL, },
+ { 0x1c71c71c71c71c72ULL, 0x38e38e38e38e38e5ULL, }, /* 56 */
+ { 0x1c71c71c71c71c71ULL, 0x38e38e38e38e38e4ULL, },
+ { 0x71c71c71c71c71c7ULL, 0x7fffffffffffffffULL, },
+ { 0x71c71c71c71c71c6ULL, 0x7fffffffffffffffULL, },
+ { 0x4fa4fa4fa4fa4fa5ULL, 0x6c16c16c16c16c18ULL, },
+ { 0x4fa4fa4fa4fa4fa4ULL, 0x6c16c16c16c16c17ULL, },
+ { 0x38e38e38e38e38e3ULL, 0x71c71c71c71c71c7ULL, },
+ { 0x38e38e38e38e38e2ULL, 0x71c71c71c71c71c8ULL, },
+ { 0x7fffffffffffffffULL, 0x7fffffffffffffffULL, }, /* 64 */
+ { 0x7bd718d08a09e3b8ULL, 0x5e5ec67913bb0308ULL, },
+ { 0x7fffffffffffffffULL, 0x733fd25ea9a6d520ULL, },
+ { 0x7fffffffffffffffULL, 0x7fffffffffffffffULL, },
+ { 0x7bd718d08a09e3b8ULL, 0x5e5ec67913bb0308ULL, },
+ { 0x0883ff3964d871f0ULL, 0x25ef76342a7ea5f8ULL, },
+ { 0x57e750f1f89cad78ULL, 0x3ad08219c06a7810ULL, },
+ { 0x749115ea109e1b46ULL, 0x7fffffffffffffffULL, },
+ { 0x7fffffffffffffffULL, 0x733fd25ea9a6d520ULL, }, /* 72 */
+ { 0x57e750f1f89cad78ULL, 0x3ad08219c06a7810ULL, },
+ { 0x7fffffffffffffffULL, 0x4fb18dff56564a28ULL, },
+ { 0x7fffffffffffffffULL, 0x7fffffffffffffffULL, },
+ { 0x7fffffffffffffffULL, 0x7fffffffffffffffULL, },
+ { 0x749115ea109e1b46ULL, 0x7fffffffffffffffULL, },
+};
+
+ gettimeofday(&start, NULL);
+
+ for (i = 0; i < PATTERN_INPUTS_SHORT_COUNT; i++) {
+ for (j = 0; j < PATTERN_INPUTS_SHORT_COUNT; j++) {
+ do_msa_ADDS_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_ADDS_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/int-add/test_msa_adds_a_h.c b/tests/tcg/mips/user/ase/msa/int-add/test_msa_adds_a_h.c
new file mode 100644
index 0000000..952f9f8
--- /dev/null
+++ b/tests/tcg/mips/user/ase/msa/int-add/test_msa_adds_a_h.c
@@ -0,0 +1,151 @@
+/*
+ * Test program for MSA instruction ADDS_A.H
+ *
+ * Copyright (C) 2019 Wave Computing, Inc.
+ * 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.h"
+#include "../../../../include/test_utils.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 = "ADDS_A.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 */
+ { 0x0001000100010001ULL, 0x0001000100010001ULL, },
+ { 0x5557555755575557ULL, 0x5557555755575557ULL, },
+ { 0x5556555655565556ULL, 0x5556555655565556ULL, },
+ { 0x3335333533353335ULL, 0x3335333533353335ULL, },
+ { 0x3334333433343334ULL, 0x3334333433343334ULL, },
+ { 0x1c7338e471c91c73ULL, 0x38e471c91c7338e4ULL, },
+ { 0x1c7238e571c81c72ULL, 0x38e571c81c7238e5ULL, },
+ { 0x0001000100010001ULL, 0x0001000100010001ULL, }, /* 8 */
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x5556555655565556ULL, 0x5556555655565556ULL, },
+ { 0x5555555555555555ULL, 0x5555555555555555ULL, },
+ { 0x3334333433343334ULL, 0x3334333433343334ULL, },
+ { 0x3333333333333333ULL, 0x3333333333333333ULL, },
+ { 0x1c7238e371c81c72ULL, 0x38e371c81c7238e3ULL, },
+ { 0x1c7138e471c71c71ULL, 0x38e471c71c7138e4ULL, },
+ { 0x5557555755575557ULL, 0x5557555755575557ULL, }, /* 16 */
+ { 0x5556555655565556ULL, 0x5556555655565556ULL, },
+ { 0x7fff7fff7fff7fffULL, 0x7fff7fff7fff7fffULL, },
+ { 0x7fff7fff7fff7fffULL, 0x7fff7fff7fff7fffULL, },
+ { 0x7fff7fff7fff7fffULL, 0x7fff7fff7fff7fffULL, },
+ { 0x7fff7fff7fff7fffULL, 0x7fff7fff7fff7fffULL, },
+ { 0x71c87fff7fff71c8ULL, 0x7fff7fff71c87fffULL, },
+ { 0x71c77fff7fff71c7ULL, 0x7fff7fff71c77fffULL, },
+ { 0x5556555655565556ULL, 0x5556555655565556ULL, }, /* 24 */
+ { 0x5555555555555555ULL, 0x5555555555555555ULL, },
+ { 0x7fff7fff7fff7fffULL, 0x7fff7fff7fff7fffULL, },
+ { 0x7fff7fff7fff7fffULL, 0x7fff7fff7fff7fffULL, },
+ { 0x7fff7fff7fff7fffULL, 0x7fff7fff7fff7fffULL, },
+ { 0x7fff7fff7fff7fffULL, 0x7fff7fff7fff7fffULL, },
+ { 0x71c77fff7fff71c7ULL, 0x7fff7fff71c77fffULL, },
+ { 0x71c67fff7fff71c6ULL, 0x7fff7fff71c67fffULL, },
+ { 0x3335333533353335ULL, 0x3335333533353335ULL, }, /* 32 */
+ { 0x3334333433343334ULL, 0x3334333433343334ULL, },
+ { 0x7fff7fff7fff7fffULL, 0x7fff7fff7fff7fffULL, },
+ { 0x7fff7fff7fff7fffULL, 0x7fff7fff7fff7fffULL, },
+ { 0x6668666866686668ULL, 0x6668666866686668ULL, },
+ { 0x6667666766676667ULL, 0x6667666766676667ULL, },
+ { 0x4fa66c177fff4fa6ULL, 0x6c177fff4fa66c17ULL, },
+ { 0x4fa56c187fff4fa5ULL, 0x6c187fff4fa56c18ULL, },
+ { 0x3334333433343334ULL, 0x3334333433343334ULL, }, /* 40 */
+ { 0x3333333333333333ULL, 0x3333333333333333ULL, },
+ { 0x7fff7fff7fff7fffULL, 0x7fff7fff7fff7fffULL, },
+ { 0x7fff7fff7fff7fffULL, 0x7fff7fff7fff7fffULL, },
+ { 0x6667666766676667ULL, 0x6667666766676667ULL, },
+ { 0x6666666666666666ULL, 0x6666666666666666ULL, },
+ { 0x4fa56c167fff4fa5ULL, 0x6c167fff4fa56c16ULL, },
+ { 0x4fa46c177fff4fa4ULL, 0x6c177fff4fa46c17ULL, },
+ { 0x1c7338e471c91c73ULL, 0x38e471c91c7338e4ULL, }, /* 48 */
+ { 0x1c7238e371c81c72ULL, 0x38e371c81c7238e3ULL, },
+ { 0x71c87fff7fff71c8ULL, 0x7fff7fff71c87fffULL, },
+ { 0x71c77fff7fff71c7ULL, 0x7fff7fff71c77fffULL, },
+ { 0x4fa66c177fff4fa6ULL, 0x6c177fff4fa66c17ULL, },
+ { 0x4fa56c167fff4fa5ULL, 0x6c167fff4fa56c16ULL, },
+ { 0x38e471c67fff38e4ULL, 0x71c67fff38e471c6ULL, },
+ { 0x38e371c77fff38e3ULL, 0x71c77fff38e371c7ULL, },
+ { 0x1c7238e571c81c72ULL, 0x38e571c81c7238e5ULL, }, /* 56 */
+ { 0x1c7138e471c71c71ULL, 0x38e471c71c7138e4ULL, },
+ { 0x71c77fff7fff71c7ULL, 0x7fff7fff71c77fffULL, },
+ { 0x71c67fff7fff71c6ULL, 0x7fff7fff71c67fffULL, },
+ { 0x4fa56c187fff4fa5ULL, 0x6c187fff4fa56c18ULL, },
+ { 0x4fa46c177fff4fa4ULL, 0x6c177fff4fa46c17ULL, },
+ { 0x38e371c77fff38e3ULL, 0x71c77fff38e371c7ULL, },
+ { 0x38e271c87fff38e2ULL, 0x71c87fff38e271c8ULL, },
+ { 0x7fff326850c47fffULL, 0x7fff16bc030a7fffULL, }, /* 64 */
+ { 0x7bd8199775f57fffULL, 0x5e5e504416c47fffULL, },
+ { 0x7fff6a8a6e937fffULL, 0x733f445f565a7508ULL, },
+ { 0x7fff2f817fff72f2ULL, 0x7fff7fff58436d54ULL, },
+ { 0x7bd8199775f57fffULL, 0x5e5e504416c47fffULL, },
+ { 0x088400c67fff71f0ULL, 0x25ee7fff2a7e7fffULL, },
+ { 0x57e851b97fff7fffULL, 0x3acf7de76a147810ULL, },
+ { 0x749116b07fff56aaULL, 0x7fff7fff6bfd705cULL, },
+ { 0x7fff6a8a6e937fffULL, 0x733f445f565a7508ULL, }, /* 72 */
+ { 0x57e851b97fff7fffULL, 0x3acf7de76a147810ULL, },
+ { 0x7fff7fff7fff7fffULL, 0x4fb072027fff4a28ULL, },
+ { 0x7fff67a37fff7fffULL, 0x7fff7fff7fff4274ULL, },
+ { 0x7fff2f817fff72f2ULL, 0x7fff7fff58436d54ULL, },
+ { 0x749116b07fff56aaULL, 0x7fff7fff6bfd705cULL, },
+};
+
+ gettimeofday(&start, NULL);
+
+ for (i = 0; i < PATTERN_INPUTS_SHORT_COUNT; i++) {
+ for (j = 0; j < PATTERN_INPUTS_SHORT_COUNT; j++) {
+ do_msa_ADDS_A_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_ADDS_A_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-add/test_msa_adds_a_w.c b/tests/tcg/mips/user/ase/msa/int-add/test_msa_adds_a_w.c
new file mode 100644
index 0000000..d058c64
--- /dev/null
+++ b/tests/tcg/mips/user/ase/msa/int-add/test_msa_adds_a_w.c
@@ -0,0 +1,151 @@
+/*
+ * Test program for MSA instruction ADDS_A.W
+ *
+ * Copyright (C) 2019 Wave Computing, Inc.
+ * 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.h"
+#include "../../../../include/test_utils.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 = "ADDS_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] = {
+ { 0x0000000200000002ULL, 0x0000000200000002ULL, }, /* 0 */
+ { 0x0000000100000001ULL, 0x0000000100000001ULL, },
+ { 0x5555555755555557ULL, 0x5555555755555557ULL, },
+ { 0x5555555655555556ULL, 0x5555555655555556ULL, },
+ { 0x3333333533333335ULL, 0x3333333533333335ULL, },
+ { 0x3333333433333334ULL, 0x3333333433333334ULL, },
+ { 0x1c71c71e71c71c73ULL, 0x38e38e391c71c71eULL, },
+ { 0x1c71c71d71c71c72ULL, 0x38e38e3a1c71c71dULL, },
+ { 0x0000000100000001ULL, 0x0000000100000001ULL, }, /* 8 */
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x5555555655555556ULL, 0x5555555655555556ULL, },
+ { 0x5555555555555555ULL, 0x5555555555555555ULL, },
+ { 0x3333333433333334ULL, 0x3333333433333334ULL, },
+ { 0x3333333333333333ULL, 0x3333333333333333ULL, },
+ { 0x1c71c71d71c71c72ULL, 0x38e38e381c71c71dULL, },
+ { 0x1c71c71c71c71c71ULL, 0x38e38e391c71c71cULL, },
+ { 0x5555555755555557ULL, 0x5555555755555557ULL, }, /* 16 */
+ { 0x5555555655555556ULL, 0x5555555655555556ULL, },
+ { 0x7fffffff7fffffffULL, 0x7fffffff7fffffffULL, },
+ { 0x7fffffff7fffffffULL, 0x7fffffff7fffffffULL, },
+ { 0x7fffffff7fffffffULL, 0x7fffffff7fffffffULL, },
+ { 0x7fffffff7fffffffULL, 0x7fffffff7fffffffULL, },
+ { 0x71c71c737fffffffULL, 0x7fffffff71c71c73ULL, },
+ { 0x71c71c727fffffffULL, 0x7fffffff71c71c72ULL, },
+ { 0x5555555655555556ULL, 0x5555555655555556ULL, }, /* 24 */
+ { 0x5555555555555555ULL, 0x5555555555555555ULL, },
+ { 0x7fffffff7fffffffULL, 0x7fffffff7fffffffULL, },
+ { 0x7fffffff7fffffffULL, 0x7fffffff7fffffffULL, },
+ { 0x7fffffff7fffffffULL, 0x7fffffff7fffffffULL, },
+ { 0x7fffffff7fffffffULL, 0x7fffffff7fffffffULL, },
+ { 0x71c71c727fffffffULL, 0x7fffffff71c71c72ULL, },
+ { 0x71c71c717fffffffULL, 0x7fffffff71c71c71ULL, },
+ { 0x3333333533333335ULL, 0x3333333533333335ULL, }, /* 32 */
+ { 0x3333333433333334ULL, 0x3333333433333334ULL, },
+ { 0x7fffffff7fffffffULL, 0x7fffffff7fffffffULL, },
+ { 0x7fffffff7fffffffULL, 0x7fffffff7fffffffULL, },
+ { 0x6666666866666668ULL, 0x6666666866666668ULL, },
+ { 0x6666666766666667ULL, 0x6666666766666667ULL, },
+ { 0x4fa4fa517fffffffULL, 0x6c16c16c4fa4fa51ULL, },
+ { 0x4fa4fa507fffffffULL, 0x6c16c16d4fa4fa50ULL, },
+ { 0x3333333433333334ULL, 0x3333333433333334ULL, }, /* 40 */
+ { 0x3333333333333333ULL, 0x3333333333333333ULL, },
+ { 0x7fffffff7fffffffULL, 0x7fffffff7fffffffULL, },
+ { 0x7fffffff7fffffffULL, 0x7fffffff7fffffffULL, },
+ { 0x6666666766666667ULL, 0x6666666766666667ULL, },
+ { 0x6666666666666666ULL, 0x6666666666666666ULL, },
+ { 0x4fa4fa507fffffffULL, 0x6c16c16b4fa4fa50ULL, },
+ { 0x4fa4fa4f7fffffffULL, 0x6c16c16c4fa4fa4fULL, },
+ { 0x1c71c71e71c71c73ULL, 0x38e38e391c71c71eULL, }, /* 48 */
+ { 0x1c71c71d71c71c72ULL, 0x38e38e381c71c71dULL, },
+ { 0x71c71c737fffffffULL, 0x7fffffff71c71c73ULL, },
+ { 0x71c71c727fffffffULL, 0x7fffffff71c71c72ULL, },
+ { 0x4fa4fa517fffffffULL, 0x6c16c16c4fa4fa51ULL, },
+ { 0x4fa4fa507fffffffULL, 0x6c16c16b4fa4fa50ULL, },
+ { 0x38e38e3a7fffffffULL, 0x71c71c7038e38e3aULL, },
+ { 0x38e38e397fffffffULL, 0x71c71c7138e38e39ULL, },
+ { 0x1c71c71d71c71c72ULL, 0x38e38e3a1c71c71dULL, }, /* 56 */
+ { 0x1c71c71c71c71c71ULL, 0x38e38e391c71c71cULL, },
+ { 0x71c71c727fffffffULL, 0x7fffffff71c71c72ULL, },
+ { 0x71c71c717fffffffULL, 0x7fffffff71c71c71ULL, },
+ { 0x4fa4fa507fffffffULL, 0x6c16c16d4fa4fa50ULL, },
+ { 0x4fa4fa4f7fffffffULL, 0x6c16c16c4fa4fa4fULL, },
+ { 0x38e38e397fffffffULL, 0x71c71c7138e38e39ULL, },
+ { 0x38e38e387fffffffULL, 0x71c71c7238e38e38ULL, },
+ { 0x7fffffff50c4aa80ULL, 0x7fffffff03089fe8ULL, }, /* 64 */
+ { 0x7bd718d175f61c48ULL, 0x5e5ec67816c3a2f0ULL, },
+ { 0x7fffffff6e92c9c0ULL, 0x733fd25d56592ae0ULL, },
+ { 0x7fffffff7fffffffULL, 0x7fffffff58416d54ULL, },
+ { 0x7bd718d175f61c48ULL, 0x5e5ec67816c3a2f0ULL, },
+ { 0x0883ff3a7fffffffULL, 0x25ef76342a7ea5f8ULL, },
+ { 0x57e750f37fffffffULL, 0x3ad082196a142de8ULL, },
+ { 0x749115ea7fffffffULL, 0x7fffffff6bfc705cULL, },
+ { 0x7fffffff6e92c9c0ULL, 0x733fd25d56592ae0ULL, }, /* 72 */
+ { 0x57e750f37fffffffULL, 0x3ad082196a142de8ULL, },
+ { 0x7fffffff7fffffffULL, 0x4fb18dfe7fffffffULL, },
+ { 0x7fffffff7fffffffULL, 0x7fffffff7fffffffULL, },
+ { 0x7fffffff7fffffffULL, 0x7fffffff58416d54ULL, },
+ { 0x749115ea7fffffffULL, 0x7fffffff6bfc705cULL, },
+};
+
+ gettimeofday(&start, NULL);
+
+ for (i = 0; i < PATTERN_INPUTS_SHORT_COUNT; i++) {
+ for (j = 0; j < PATTERN_INPUTS_SHORT_COUNT; j++) {
+ do_msa_ADDS_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_ADDS_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/int-add/test_msa_adds_s_b.c b/tests/tcg/mips/user/ase/msa/int-add/test_msa_adds_s_b.c
new file mode 100644
index 0000000..63e27da
--- /dev/null
+++ b/tests/tcg/mips/user/ase/msa/int-add/test_msa_adds_s_b.c
@@ -0,0 +1,151 @@
+/*
+ * Test program for MSA instruction ADDS_S.B
+ *
+ * Copyright (C) 2019 Wave Computing, Inc.
+ * 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.h"
+#include "../../../../include/test_utils.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 = "ADDS_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] = {
+ { 0xfefefefefefefefeULL, 0xfefefefefefefefeULL, }, /* 0 */
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0xa9a9a9a9a9a9a9a9ULL, 0xa9a9a9a9a9a9a9a9ULL, },
+ { 0x5454545454545454ULL, 0x5454545454545454ULL, },
+ { 0xcbcbcbcbcbcbcbcbULL, 0xcbcbcbcbcbcbcbcbULL, },
+ { 0x3232323232323232ULL, 0x3232323232323232ULL, },
+ { 0xe28d37e28d37e28dULL, 0x37e28d37e28d37e2ULL, },
+ { 0x1b70c61b70c61b70ULL, 0xc61b70c61b70c61bULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 8 */
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, },
+ { 0x5555555555555555ULL, 0x5555555555555555ULL, },
+ { 0xccccccccccccccccULL, 0xccccccccccccccccULL, },
+ { 0x3333333333333333ULL, 0x3333333333333333ULL, },
+ { 0xe38e38e38e38e38eULL, 0x38e38e38e38e38e3ULL, },
+ { 0x1c71c71c71c71c71ULL, 0xc71c71c71c71c71cULL, },
+ { 0xa9a9a9a9a9a9a9a9ULL, 0xa9a9a9a9a9a9a9a9ULL, }, /* 16 */
+ { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, },
+ { 0x8080808080808080ULL, 0x8080808080808080ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0x8080808080808080ULL, 0x8080808080808080ULL, },
+ { 0xddddddddddddddddULL, 0xddddddddddddddddULL, },
+ { 0x8d80e28d80e28d80ULL, 0xe28d80e28d80e28dULL, },
+ { 0xc61b80c61b80c61bULL, 0x80c61b80c61b80c6ULL, },
+ { 0x5454545454545454ULL, 0x5454545454545454ULL, }, /* 24 */
+ { 0x5555555555555555ULL, 0x5555555555555555ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0x7f7f7f7f7f7f7f7fULL, 0x7f7f7f7f7f7f7f7fULL, },
+ { 0x2121212121212121ULL, 0x2121212121212121ULL, },
+ { 0x7f7f7f7f7f7f7f7fULL, 0x7f7f7f7f7f7f7f7fULL, },
+ { 0x38e37f38e37f38e3ULL, 0x7f38e37f38e37f38ULL, },
+ { 0x717f1c717f1c717fULL, 0x1c717f1c717f1c71ULL, },
+ { 0xcbcbcbcbcbcbcbcbULL, 0xcbcbcbcbcbcbcbcbULL, }, /* 32 */
+ { 0xccccccccccccccccULL, 0xccccccccccccccccULL, },
+ { 0x8080808080808080ULL, 0x8080808080808080ULL, },
+ { 0x2121212121212121ULL, 0x2121212121212121ULL, },
+ { 0x9898989898989898ULL, 0x9898989898989898ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0xaf8004af8004af80ULL, 0x04af8004af8004afULL, },
+ { 0xe83d93e83d93e83dULL, 0x93e83d93e83d93e8ULL, },
+ { 0x3232323232323232ULL, 0x3232323232323232ULL, }, /* 40 */
+ { 0x3333333333333333ULL, 0x3333333333333333ULL, },
+ { 0xddddddddddddddddULL, 0xddddddddddddddddULL, },
+ { 0x7f7f7f7f7f7f7f7fULL, 0x7f7f7f7f7f7f7f7fULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0x6666666666666666ULL, 0x6666666666666666ULL, },
+ { 0x16c16b16c16b16c1ULL, 0x6b16c16b16c16b16ULL, },
+ { 0x4f7ffa4f7ffa4f7fULL, 0xfa4f7ffa4f7ffa4fULL, },
+ { 0xe28d37e28d37e28dULL, 0x37e28d37e28d37e2ULL, }, /* 48 */
+ { 0xe38e38e38e38e38eULL, 0x38e38e38e38e38e3ULL, },
+ { 0x8d80e28d80e28d80ULL, 0xe28d80e28d80e28dULL, },
+ { 0x38e37f38e37f38e3ULL, 0x7f38e37f38e37f38ULL, },
+ { 0xaf8004af8004af80ULL, 0x04af8004af8004afULL, },
+ { 0x16c16b16c16b16c1ULL, 0x6b16c16b16c16b16ULL, },
+ { 0xc68070c68070c680ULL, 0x70c68070c68070c6ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0x1b70c61b70c61b70ULL, 0xc61b70c61b70c61bULL, }, /* 56 */
+ { 0x1c71c71c71c71c71ULL, 0xc71c71c71c71c71cULL, },
+ { 0xc61b80c61b80c61bULL, 0x80c61b80c61b80c6ULL, },
+ { 0x717f1c717f1c717fULL, 0x1c717f1c717f1c71ULL, },
+ { 0xe83d93e83d93e83dULL, 0x93e83d93e83d93e8ULL, },
+ { 0x4f7ffa4f7ffa4f7fULL, 0xfa4f7ffa4f7ffa4fULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0x387f8e387f8e387fULL, 0x8e387f8e387f8e38ULL, },
+ { 0x807fcc98507f7f7fULL, 0x7f7f167ffc7f8018ULL, }, /* 64 */
+ { 0x8328e62f75f51c48ULL, 0x5d5ec678137f0208ULL, },
+ { 0x807f9480e131e0c0ULL, 0x723fd15da97fd520ULL, },
+ { 0xf87ffc197f7f377fULL, 0xd8589336a77f92acULL, },
+ { 0x8328e62f75f51c48ULL, 0x5d5ec678137f0208ULL, },
+ { 0xf680007f7f808e10ULL, 0x24ee80342a7e7ff8ULL, },
+ { 0xa718ae0d06808088ULL, 0x39cf8119c06a7710ULL, },
+ { 0x6b0d167f7fc4a956ULL, 0x9fe880f2be7f349cULL, },
+ { 0x807f9480e131e0c0ULL, 0x723fd15da97fd520ULL, }, /* 72 */
+ { 0xa718ae0d06808088ULL, 0x39cf8119c06a7710ULL, },
+ { 0x807f8080809e8080ULL, 0x4eb08cfe80564a28ULL, },
+ { 0x1c7fc4f7170080ceULL, 0xb4c980d7806d07b4ULL, },
+ { 0xf87ffc197f7f377fULL, 0xd8589336a77f92acULL, },
+ { 0x6b0d167f7fc4a956ULL, 0x9fe880f2be7f349cULL, },
+};
+
+ gettimeofday(&start, NULL);
+
+ for (i = 0; i < PATTERN_INPUTS_SHORT_COUNT; i++) {
+ for (j = 0; j < PATTERN_INPUTS_SHORT_COUNT; j++) {
+ do_msa_ADDS_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_ADDS_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-add/test_msa_adds_s_d.c b/tests/tcg/mips/user/ase/msa/int-add/test_msa_adds_s_d.c
new file mode 100644
index 0000000..2719cee
--- /dev/null
+++ b/tests/tcg/mips/user/ase/msa/int-add/test_msa_adds_s_d.c
@@ -0,0 +1,151 @@
+/*
+ * Test program for MSA instruction ADDS_S.D
+ *
+ * Copyright (C) 2019 Wave Computing, Inc.
+ * 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.h"
+#include "../../../../include/test_utils.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 = "ADDS_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] = {
+ { 0xfffffffffffffffeULL, 0xfffffffffffffffeULL, }, /* 0 */
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0xaaaaaaaaaaaaaaa9ULL, 0xaaaaaaaaaaaaaaa9ULL, },
+ { 0x5555555555555554ULL, 0x5555555555555554ULL, },
+ { 0xcccccccccccccccbULL, 0xcccccccccccccccbULL, },
+ { 0x3333333333333332ULL, 0x3333333333333332ULL, },
+ { 0xe38e38e38e38e38dULL, 0x38e38e38e38e38e2ULL, },
+ { 0x1c71c71c71c71c70ULL, 0xc71c71c71c71c71bULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 8 */
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, },
+ { 0x5555555555555555ULL, 0x5555555555555555ULL, },
+ { 0xccccccccccccccccULL, 0xccccccccccccccccULL, },
+ { 0x3333333333333333ULL, 0x3333333333333333ULL, },
+ { 0xe38e38e38e38e38eULL, 0x38e38e38e38e38e3ULL, },
+ { 0x1c71c71c71c71c71ULL, 0xc71c71c71c71c71cULL, },
+ { 0xaaaaaaaaaaaaaaa9ULL, 0xaaaaaaaaaaaaaaa9ULL, }, /* 16 */
+ { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, },
+ { 0x8000000000000000ULL, 0x8000000000000000ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0x8000000000000000ULL, 0x8000000000000000ULL, },
+ { 0xddddddddddddddddULL, 0xddddddddddddddddULL, },
+ { 0x8e38e38e38e38e38ULL, 0xe38e38e38e38e38dULL, },
+ { 0xc71c71c71c71c71bULL, 0x8000000000000000ULL, },
+ { 0x5555555555555554ULL, 0x5555555555555554ULL, }, /* 24 */
+ { 0x5555555555555555ULL, 0x5555555555555555ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0x7fffffffffffffffULL, 0x7fffffffffffffffULL, },
+ { 0x2222222222222221ULL, 0x2222222222222221ULL, },
+ { 0x7fffffffffffffffULL, 0x7fffffffffffffffULL, },
+ { 0x38e38e38e38e38e3ULL, 0x7fffffffffffffffULL, },
+ { 0x71c71c71c71c71c6ULL, 0x1c71c71c71c71c71ULL, },
+ { 0xcccccccccccccccbULL, 0xcccccccccccccccbULL, }, /* 32 */
+ { 0xccccccccccccccccULL, 0xccccccccccccccccULL, },
+ { 0x8000000000000000ULL, 0x8000000000000000ULL, },
+ { 0x2222222222222221ULL, 0x2222222222222221ULL, },
+ { 0x9999999999999998ULL, 0x9999999999999998ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0xb05b05b05b05b05aULL, 0x05b05b05b05b05afULL, },
+ { 0xe93e93e93e93e93dULL, 0x93e93e93e93e93e8ULL, },
+ { 0x3333333333333332ULL, 0x3333333333333332ULL, }, /* 40 */
+ { 0x3333333333333333ULL, 0x3333333333333333ULL, },
+ { 0xddddddddddddddddULL, 0xddddddddddddddddULL, },
+ { 0x7fffffffffffffffULL, 0x7fffffffffffffffULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0x6666666666666666ULL, 0x6666666666666666ULL, },
+ { 0x16c16c16c16c16c1ULL, 0x6c16c16c16c16c16ULL, },
+ { 0x4fa4fa4fa4fa4fa4ULL, 0xfa4fa4fa4fa4fa4fULL, },
+ { 0xe38e38e38e38e38dULL, 0x38e38e38e38e38e2ULL, }, /* 48 */
+ { 0xe38e38e38e38e38eULL, 0x38e38e38e38e38e3ULL, },
+ { 0x8e38e38e38e38e38ULL, 0xe38e38e38e38e38dULL, },
+ { 0x38e38e38e38e38e3ULL, 0x7fffffffffffffffULL, },
+ { 0xb05b05b05b05b05aULL, 0x05b05b05b05b05afULL, },
+ { 0x16c16c16c16c16c1ULL, 0x6c16c16c16c16c16ULL, },
+ { 0xc71c71c71c71c71cULL, 0x71c71c71c71c71c6ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0x1c71c71c71c71c70ULL, 0xc71c71c71c71c71bULL, }, /* 56 */
+ { 0x1c71c71c71c71c71ULL, 0xc71c71c71c71c71cULL, },
+ { 0xc71c71c71c71c71bULL, 0x8000000000000000ULL, },
+ { 0x71c71c71c71c71c6ULL, 0x1c71c71c71c71c71ULL, },
+ { 0xe93e93e93e93e93dULL, 0x93e93e93e93e93e8ULL, },
+ { 0x4fa4fa4fa4fa4fa4ULL, 0xfa4fa4fa4fa4fa4fULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0x38e38e38e38e38e2ULL, 0x8e38e38e38e38e38ULL, },
+ { 0x8000000000000000ULL, 0x7fffffffffffffffULL, }, /* 64 */
+ { 0x8428e72f75f61c48ULL, 0x5e5ec67913bb0308ULL, },
+ { 0x8000000000000000ULL, 0x733fd25ea9a6d520ULL, },
+ { 0xf8b9fd198694378eULL, 0xd9589437a7be92acULL, },
+ { 0x8428e72f75f61c48ULL, 0x5e5ec67913bb0308ULL, },
+ { 0xf77c00c69b278e10ULL, 0x25ef76342a7ea5f8ULL, },
+ { 0xa818af0e07635288ULL, 0x3ad08219c06a7810ULL, },
+ { 0x6c0d16b0abc5a956ULL, 0xa0e943f2be82359cULL, },
+ { 0x8000000000000000ULL, 0x733fd25ea9a6d520ULL, }, /* 72 */
+ { 0xa818af0e07635288ULL, 0x3ad08219c06a7810ULL, },
+ { 0x8000000000000000ULL, 0x4fb18dff56564a28ULL, },
+ { 0x1ca9c4f818016dceULL, 0xb5ca4fd8546e07b4ULL, },
+ { 0xf8b9fd198694378eULL, 0xd9589437a7be92acULL, },
+ { 0x6c0d16b0abc5a956ULL, 0xa0e943f2be82359cULL, },
+};
+
+ gettimeofday(&start, NULL);
+
+ for (i = 0; i < PATTERN_INPUTS_SHORT_COUNT; i++) {
+ for (j = 0; j < PATTERN_INPUTS_SHORT_COUNT; j++) {
+ do_msa_ADDS_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_ADDS_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-add/test_msa_adds_s_h.c b/tests/tcg/mips/user/ase/msa/int-add/test_msa_adds_s_h.c
new file mode 100644
index 0000000..5274096
--- /dev/null
+++ b/tests/tcg/mips/user/ase/msa/int-add/test_msa_adds_s_h.c
@@ -0,0 +1,151 @@
+/*
+ * Test program for MSA instruction ADDS_S.H
+ *
+ * Copyright (C) 2019 Wave Computing, Inc.
+ * 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.h"
+#include "../../../../include/test_utils.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 = "ADDS_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] = {
+ { 0xfffefffefffefffeULL, 0xfffefffefffefffeULL, }, /* 0 */
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0xaaa9aaa9aaa9aaa9ULL, 0xaaa9aaa9aaa9aaa9ULL, },
+ { 0x5554555455545554ULL, 0x5554555455545554ULL, },
+ { 0xcccbcccbcccbcccbULL, 0xcccbcccbcccbcccbULL, },
+ { 0x3332333233323332ULL, 0x3332333233323332ULL, },
+ { 0xe38d38e28e37e38dULL, 0x38e28e37e38d38e2ULL, },
+ { 0x1c70c71b71c61c70ULL, 0xc71b71c61c70c71bULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 8 */
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, },
+ { 0x5555555555555555ULL, 0x5555555555555555ULL, },
+ { 0xccccccccccccccccULL, 0xccccccccccccccccULL, },
+ { 0x3333333333333333ULL, 0x3333333333333333ULL, },
+ { 0xe38e38e38e38e38eULL, 0x38e38e38e38e38e3ULL, },
+ { 0x1c71c71c71c71c71ULL, 0xc71c71c71c71c71cULL, },
+ { 0xaaa9aaa9aaa9aaa9ULL, 0xaaa9aaa9aaa9aaa9ULL, }, /* 16 */
+ { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, },
+ { 0x8000800080008000ULL, 0x8000800080008000ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0x8000800080008000ULL, 0x8000800080008000ULL, },
+ { 0xddddddddddddddddULL, 0xddddddddddddddddULL, },
+ { 0x8e38e38d80008e38ULL, 0xe38d80008e38e38dULL, },
+ { 0xc71b80001c71c71bULL, 0x80001c71c71b8000ULL, },
+ { 0x5554555455545554ULL, 0x5554555455545554ULL, }, /* 24 */
+ { 0x5555555555555555ULL, 0x5555555555555555ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0x7fff7fff7fff7fffULL, 0x7fff7fff7fff7fffULL, },
+ { 0x2221222122212221ULL, 0x2221222122212221ULL, },
+ { 0x7fff7fff7fff7fffULL, 0x7fff7fff7fff7fffULL, },
+ { 0x38e37fffe38d38e3ULL, 0x7fffe38d38e37fffULL, },
+ { 0x71c61c717fff71c6ULL, 0x1c717fff71c61c71ULL, },
+ { 0xcccbcccbcccbcccbULL, 0xcccbcccbcccbcccbULL, }, /* 32 */
+ { 0xccccccccccccccccULL, 0xccccccccccccccccULL, },
+ { 0x8000800080008000ULL, 0x8000800080008000ULL, },
+ { 0x2221222122212221ULL, 0x2221222122212221ULL, },
+ { 0x9998999899989998ULL, 0x9998999899989998ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0xb05a05af8000b05aULL, 0x05af8000b05a05afULL, },
+ { 0xe93d93e83e93e93dULL, 0x93e83e93e93d93e8ULL, },
+ { 0x3332333233323332ULL, 0x3332333233323332ULL, }, /* 40 */
+ { 0x3333333333333333ULL, 0x3333333333333333ULL, },
+ { 0xddddddddddddddddULL, 0xddddddddddddddddULL, },
+ { 0x7fff7fff7fff7fffULL, 0x7fff7fff7fff7fffULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0x6666666666666666ULL, 0x6666666666666666ULL, },
+ { 0x16c16c16c16b16c1ULL, 0x6c16c16b16c16c16ULL, },
+ { 0x4fa4fa4f7fff4fa4ULL, 0xfa4f7fff4fa4fa4fULL, },
+ { 0xe38d38e28e37e38dULL, 0x38e28e37e38d38e2ULL, }, /* 48 */
+ { 0xe38e38e38e38e38eULL, 0x38e38e38e38e38e3ULL, },
+ { 0x8e38e38d80008e38ULL, 0xe38d80008e38e38dULL, },
+ { 0x38e37fffe38d38e3ULL, 0x7fffe38d38e37fffULL, },
+ { 0xb05a05af8000b05aULL, 0x05af8000b05a05afULL, },
+ { 0x16c16c16c16b16c1ULL, 0x6c16c16b16c16c16ULL, },
+ { 0xc71c71c68000c71cULL, 0x71c68000c71c71c6ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0x1c70c71b71c61c70ULL, 0xc71b71c61c70c71bULL, }, /* 56 */
+ { 0x1c71c71c71c71c71ULL, 0xc71c71c71c71c71cULL, },
+ { 0xc71b80001c71c71bULL, 0x80001c71c71b8000ULL, },
+ { 0x71c61c717fff71c6ULL, 0x1c717fff71c61c71ULL, },
+ { 0xe93d93e83e93e93dULL, 0x93e83e93e93d93e8ULL, },
+ { 0x4fa4fa4f7fff4fa4ULL, 0xfa4f7fff4fa4fa4fULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0x38e28e387fff38e2ULL, 0x8e387fff38e28e38ULL, },
+ { 0x8000cd9850c47fffULL, 0x7fff16bcfcf68000ULL, }, /* 64 */
+ { 0x8428e72f75f51c48ULL, 0x5e5ec67813ba0308ULL, },
+ { 0x80009576e231e0c0ULL, 0x733fd25da9a6d520ULL, },
+ { 0xf8b9fd197fff378eULL, 0xd9589436a7bd92acULL, },
+ { 0x8428e72f75f51c48ULL, 0x5e5ec67813ba0308ULL, },
+ { 0xf77c00c67fff8e10ULL, 0x25ee80002a7e7fffULL, },
+ { 0xa818af0d07628000ULL, 0x3acf8219c06a7810ULL, },
+ { 0x6c0d16b07fffa956ULL, 0xa0e88000be81359cULL, },
+ { 0x80009576e231e0c0ULL, 0x733fd25da9a6d520ULL, }, /* 72 */
+ { 0xa818af0d07628000ULL, 0x3acf8219c06a7810ULL, },
+ { 0x8000800080008000ULL, 0x4fb08dfe80004a28ULL, },
+ { 0x1ca9c4f718008000ULL, 0xb5c98000800007b4ULL, },
+ { 0xf8b9fd197fff378eULL, 0xd9589436a7bd92acULL, },
+ { 0x6c0d16b07fffa956ULL, 0xa0e88000be81359cULL, },
+};
+
+ gettimeofday(&start, NULL);
+
+ for (i = 0; i < PATTERN_INPUTS_SHORT_COUNT; i++) {
+ for (j = 0; j < PATTERN_INPUTS_SHORT_COUNT; j++) {
+ do_msa_ADDS_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_ADDS_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-add/test_msa_adds_s_w.c b/tests/tcg/mips/user/ase/msa/int-add/test_msa_adds_s_w.c
new file mode 100644
index 0000000..c3a6292
--- /dev/null
+++ b/tests/tcg/mips/user/ase/msa/int-add/test_msa_adds_s_w.c
@@ -0,0 +1,151 @@
+/*
+ * Test program for MSA instruction ADDS_S.W
+ *
+ * Copyright (C) 2019 Wave Computing, Inc.
+ * 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.h"
+#include "../../../../include/test_utils.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 = "ADDS_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] = {
+ { 0xfffffffefffffffeULL, 0xfffffffefffffffeULL, }, /* 0 */
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0xaaaaaaa9aaaaaaa9ULL, 0xaaaaaaa9aaaaaaa9ULL, },
+ { 0x5555555455555554ULL, 0x5555555455555554ULL, },
+ { 0xcccccccbcccccccbULL, 0xcccccccbcccccccbULL, },
+ { 0x3333333233333332ULL, 0x3333333233333332ULL, },
+ { 0xe38e38e28e38e38dULL, 0x38e38e37e38e38e2ULL, },
+ { 0x1c71c71b71c71c70ULL, 0xc71c71c61c71c71bULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 8 */
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, },
+ { 0x5555555555555555ULL, 0x5555555555555555ULL, },
+ { 0xccccccccccccccccULL, 0xccccccccccccccccULL, },
+ { 0x3333333333333333ULL, 0x3333333333333333ULL, },
+ { 0xe38e38e38e38e38eULL, 0x38e38e38e38e38e3ULL, },
+ { 0x1c71c71c71c71c71ULL, 0xc71c71c71c71c71cULL, },
+ { 0xaaaaaaa9aaaaaaa9ULL, 0xaaaaaaa9aaaaaaa9ULL, }, /* 16 */
+ { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, },
+ { 0x8000000080000000ULL, 0x8000000080000000ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0x8000000080000000ULL, 0x8000000080000000ULL, },
+ { 0xddddddddddddddddULL, 0xddddddddddddddddULL, },
+ { 0x8e38e38d80000000ULL, 0xe38e38e28e38e38dULL, },
+ { 0xc71c71c61c71c71bULL, 0x80000000c71c71c6ULL, },
+ { 0x5555555455555554ULL, 0x5555555455555554ULL, }, /* 24 */
+ { 0x5555555555555555ULL, 0x5555555555555555ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0x7fffffff7fffffffULL, 0x7fffffff7fffffffULL, },
+ { 0x2222222122222221ULL, 0x2222222122222221ULL, },
+ { 0x7fffffff7fffffffULL, 0x7fffffff7fffffffULL, },
+ { 0x38e38e38e38e38e3ULL, 0x7fffffff38e38e38ULL, },
+ { 0x71c71c717fffffffULL, 0x1c71c71c71c71c71ULL, },
+ { 0xcccccccbcccccccbULL, 0xcccccccbcccccccbULL, }, /* 32 */
+ { 0xccccccccccccccccULL, 0xccccccccccccccccULL, },
+ { 0x8000000080000000ULL, 0x8000000080000000ULL, },
+ { 0x2222222122222221ULL, 0x2222222122222221ULL, },
+ { 0x9999999899999998ULL, 0x9999999899999998ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0xb05b05af80000000ULL, 0x05b05b04b05b05afULL, },
+ { 0xe93e93e83e93e93dULL, 0x93e93e93e93e93e8ULL, },
+ { 0x3333333233333332ULL, 0x3333333233333332ULL, }, /* 40 */
+ { 0x3333333333333333ULL, 0x3333333333333333ULL, },
+ { 0xddddddddddddddddULL, 0xddddddddddddddddULL, },
+ { 0x7fffffff7fffffffULL, 0x7fffffff7fffffffULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0x6666666666666666ULL, 0x6666666666666666ULL, },
+ { 0x16c16c16c16c16c1ULL, 0x6c16c16b16c16c16ULL, },
+ { 0x4fa4fa4f7fffffffULL, 0xfa4fa4fa4fa4fa4fULL, },
+ { 0xe38e38e28e38e38dULL, 0x38e38e37e38e38e2ULL, }, /* 48 */
+ { 0xe38e38e38e38e38eULL, 0x38e38e38e38e38e3ULL, },
+ { 0x8e38e38d80000000ULL, 0xe38e38e28e38e38dULL, },
+ { 0x38e38e38e38e38e3ULL, 0x7fffffff38e38e38ULL, },
+ { 0xb05b05af80000000ULL, 0x05b05b04b05b05afULL, },
+ { 0x16c16c16c16c16c1ULL, 0x6c16c16b16c16c16ULL, },
+ { 0xc71c71c680000000ULL, 0x71c71c70c71c71c6ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0x1c71c71b71c71c70ULL, 0xc71c71c61c71c71bULL, }, /* 56 */
+ { 0x1c71c71c71c71c71ULL, 0xc71c71c71c71c71cULL, },
+ { 0xc71c71c61c71c71bULL, 0x80000000c71c71c6ULL, },
+ { 0x71c71c717fffffffULL, 0x1c71c71c71c71c71ULL, },
+ { 0xe93e93e83e93e93dULL, 0x93e93e93e93e93e8ULL, },
+ { 0x4fa4fa4f7fffffffULL, 0xfa4fa4fa4fa4fa4fULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0x38e38e387fffffffULL, 0x8e38e38e38e38e38ULL, },
+ { 0x8000000050c4aa80ULL, 0x7ffffffffcf76018ULL, }, /* 64 */
+ { 0x8428e72f75f61c48ULL, 0x5e5ec67813bb0308ULL, },
+ { 0x80000000e231e0c0ULL, 0x733fd25da9a6d520ULL, },
+ { 0xf8b9fd197fffffffULL, 0xd9589436a7be92acULL, },
+ { 0x8428e72f75f61c48ULL, 0x5e5ec67813bb0308ULL, },
+ { 0xf77c00c67fffffffULL, 0x25ef76342a7ea5f8ULL, },
+ { 0xa818af0d07635288ULL, 0x3ad08219c06a7810ULL, },
+ { 0x6c0d16b07fffffffULL, 0xa0e943f2be82359cULL, },
+ { 0x80000000e231e0c0ULL, 0x733fd25da9a6d520ULL, }, /* 72 */
+ { 0xa818af0d07635288ULL, 0x3ad08219c06a7810ULL, },
+ { 0x8000000080000000ULL, 0x4fb18dfe80000000ULL, },
+ { 0x1ca9c4f718016dceULL, 0xb5ca4fd780000000ULL, },
+ { 0xf8b9fd197fffffffULL, 0xd9589436a7be92acULL, },
+ { 0x6c0d16b07fffffffULL, 0xa0e943f2be82359cULL, },
+};
+
+ gettimeofday(&start, NULL);
+
+ for (i = 0; i < PATTERN_INPUTS_SHORT_COUNT; i++) {
+ for (j = 0; j < PATTERN_INPUTS_SHORT_COUNT; j++) {
+ do_msa_ADDS_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_ADDS_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-add/test_msa_adds_u_b.c b/tests/tcg/mips/user/ase/msa/int-add/test_msa_adds_u_b.c
new file mode 100644
index 0000000..df5d85f
--- /dev/null
+++ b/tests/tcg/mips/user/ase/msa/int-add/test_msa_adds_u_b.c
@@ -0,0 +1,151 @@
+/*
+ * Test program for MSA instruction ADDS_U.B
+ *
+ * Copyright (C) 2019 Wave Computing, Inc.
+ * 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.h"
+#include "../../../../include/test_utils.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 = "ADDS_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] = {
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 0 */
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 8 */
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, },
+ { 0x5555555555555555ULL, 0x5555555555555555ULL, },
+ { 0xccccccccccccccccULL, 0xccccccccccccccccULL, },
+ { 0x3333333333333333ULL, 0x3333333333333333ULL, },
+ { 0xe38e38e38e38e38eULL, 0x38e38e38e38e38e3ULL, },
+ { 0x1c71c71c71c71c71ULL, 0xc71c71c71c71c71cULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 16 */
+ { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0xddddddddddddddddULL, 0xddddddddddddddddULL, },
+ { 0xffffe2ffffe2ffffULL, 0xe2ffffe2ffffe2ffULL, },
+ { 0xc6ffffc6ffffc6ffULL, 0xffc6ffffc6ffffc6ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 24 */
+ { 0x5555555555555555ULL, 0x5555555555555555ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0x8888888888888888ULL, 0x8888888888888888ULL, },
+ { 0xffe38dffe38dffe3ULL, 0x8dffe38dffe38dffULL, },
+ { 0x71c6ff71c6ff71c6ULL, 0xff71c6ff71c6ff71ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 32 */
+ { 0xccccccccccccccccULL, 0xccccccccccccccccULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0xe8ffffe8ffffe8ffULL, 0xffe8ffffe8ffffe8ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 40 */
+ { 0x3333333333333333ULL, 0x3333333333333333ULL, },
+ { 0xddddddddddddddddULL, 0xddddddddddddddddULL, },
+ { 0x8888888888888888ULL, 0x8888888888888888ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0x6666666666666666ULL, 0x6666666666666666ULL, },
+ { 0xffc16bffc16bffc1ULL, 0x6bffc16bffc16bffULL, },
+ { 0x4fa4fa4fa4fa4fa4ULL, 0xfa4fa4fa4fa4fa4fULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 48 */
+ { 0xe38e38e38e38e38eULL, 0x38e38e38e38e38e3ULL, },
+ { 0xffffe2ffffe2ffffULL, 0xe2ffffe2ffffe2ffULL, },
+ { 0xffe38dffe38dffe3ULL, 0x8dffe38dffe38dffULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0xffc16bffc16bffc1ULL, 0x6bffc16bffc16bffULL, },
+ { 0xffff70ffff70ffffULL, 0x70ffff70ffff70ffULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 56 */
+ { 0x1c71c71c71c71c71ULL, 0xc71c71c71c71c71cULL, },
+ { 0xc6ffffc6ffffc6ffULL, 0xffc6ffffc6ffffc6ULL, },
+ { 0x71c6ff71c6ff71c6ULL, 0xff71c6ff71c6ff71ULL, },
+ { 0xe8ffffe8ffffe8ffULL, 0xffe8ffffe8ffffe8ULL, },
+ { 0x4fa4fa4fa4fa4fa4ULL, 0xfa4fa4fa4fa4fa4fULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0x38e2ff38e2ff38e2ULL, 0xff38e2ff38e2ff38ULL, },
+ { 0xffd4ffff50c4aa80ULL, 0x96ce16bcfff6ff18ULL, }, /* 64 */
+ { 0xffffe6ff75f5ff48ULL, 0x5dffc678ffbaffffULL, },
+ { 0xffc4ffffe1ffe0c0ULL, 0x72ffd1ffffa6d520ULL, },
+ { 0xf8b9fcff8693ff8eULL, 0xd8ff93ffffbdffacULL, },
+ { 0xffffe6ff75f5ff48ULL, 0x5dffc678ffbaffffULL, },
+ { 0xffff00c69affff10ULL, 0x24ffff342a7ea4ffULL, },
+ { 0xffffaeffffffff88ULL, 0x39ffffffc06a77ffULL, },
+ { 0xffff16b0abc4ff56ULL, 0x9ffffff2be81ffffULL, },
+ { 0xffc4ffffe1ffe0c0ULL, 0x72ffd1ffffa6d520ULL, }, /* 72 */
+ { 0xffffaeffffffff88ULL, 0x39ffffffc06a77ffULL, },
+ { 0xffb4ffffffffffffULL, 0x4effffffff564a28ULL, },
+ { 0xffa9c4f7ffffffceULL, 0xb4ffffffff6dffb4ULL, },
+ { 0xf8b9fcff8693ff8eULL, 0xd8ff93ffffbdffacULL, },
+ { 0xffff16b0abc4ff56ULL, 0x9ffffff2be81ffffULL, },
+};
+
+ gettimeofday(&start, NULL);
+
+ for (i = 0; i < PATTERN_INPUTS_SHORT_COUNT; i++) {
+ for (j = 0; j < PATTERN_INPUTS_SHORT_COUNT; j++) {
+ do_msa_ADDS_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_ADDS_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-add/test_msa_adds_u_d.c b/tests/tcg/mips/user/ase/msa/int-add/test_msa_adds_u_d.c
new file mode 100644
index 0000000..10c665b
--- /dev/null
+++ b/tests/tcg/mips/user/ase/msa/int-add/test_msa_adds_u_d.c
@@ -0,0 +1,151 @@
+/*
+ * Test program for MSA instruction ADDS_U.D
+ *
+ * Copyright (C) 2019 Wave Computing, Inc.
+ * 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.h"
+#include "../../../../include/test_utils.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 = "ADDS_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] = {
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 0 */
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 8 */
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, },
+ { 0x5555555555555555ULL, 0x5555555555555555ULL, },
+ { 0xccccccccccccccccULL, 0xccccccccccccccccULL, },
+ { 0x3333333333333333ULL, 0x3333333333333333ULL, },
+ { 0xe38e38e38e38e38eULL, 0x38e38e38e38e38e3ULL, },
+ { 0x1c71c71c71c71c71ULL, 0xc71c71c71c71c71cULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 16 */
+ { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0xddddddddddddddddULL, 0xddddddddddddddddULL, },
+ { 0xffffffffffffffffULL, 0xe38e38e38e38e38dULL, },
+ { 0xc71c71c71c71c71bULL, 0xffffffffffffffffULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 24 */
+ { 0x5555555555555555ULL, 0x5555555555555555ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0x8888888888888888ULL, 0x8888888888888888ULL, },
+ { 0xffffffffffffffffULL, 0x8e38e38e38e38e38ULL, },
+ { 0x71c71c71c71c71c6ULL, 0xffffffffffffffffULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 32 */
+ { 0xccccccccccccccccULL, 0xccccccccccccccccULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0xe93e93e93e93e93dULL, 0xffffffffffffffffULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 40 */
+ { 0x3333333333333333ULL, 0x3333333333333333ULL, },
+ { 0xddddddddddddddddULL, 0xddddddddddddddddULL, },
+ { 0x8888888888888888ULL, 0x8888888888888888ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0x6666666666666666ULL, 0x6666666666666666ULL, },
+ { 0xffffffffffffffffULL, 0x6c16c16c16c16c16ULL, },
+ { 0x4fa4fa4fa4fa4fa4ULL, 0xfa4fa4fa4fa4fa4fULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 48 */
+ { 0xe38e38e38e38e38eULL, 0x38e38e38e38e38e3ULL, },
+ { 0xffffffffffffffffULL, 0xe38e38e38e38e38dULL, },
+ { 0xffffffffffffffffULL, 0x8e38e38e38e38e38ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0xffffffffffffffffULL, 0x6c16c16c16c16c16ULL, },
+ { 0xffffffffffffffffULL, 0x71c71c71c71c71c6ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 56 */
+ { 0x1c71c71c71c71c71ULL, 0xc71c71c71c71c71cULL, },
+ { 0xc71c71c71c71c71bULL, 0xffffffffffffffffULL, },
+ { 0x71c71c71c71c71c6ULL, 0xffffffffffffffffULL, },
+ { 0xe93e93e93e93e93dULL, 0xffffffffffffffffULL, },
+ { 0x4fa4fa4fa4fa4fa4ULL, 0xfa4fa4fa4fa4fa4fULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0x38e38e38e38e38e2ULL, 0xffffffffffffffffULL, },
+ { 0xffffffffffffffffULL, 0x96ce16bdfcf76018ULL, }, /* 64 */
+ { 0xffffffffffffffffULL, 0x5e5ec67913bb0308ULL, },
+ { 0xffffffffffffffffULL, 0x733fd25ea9a6d520ULL, },
+ { 0xf8b9fd198694378eULL, 0xd9589437a7be92acULL, },
+ { 0xffffffffffffffffULL, 0x5e5ec67913bb0308ULL, },
+ { 0xffffffffffffffffULL, 0x25ef76342a7ea5f8ULL, },
+ { 0xffffffffffffffffULL, 0x3ad08219c06a7810ULL, },
+ { 0xffffffffffffffffULL, 0xa0e943f2be82359cULL, },
+ { 0xffffffffffffffffULL, 0x733fd25ea9a6d520ULL, }, /* 72 */
+ { 0xffffffffffffffffULL, 0x3ad08219c06a7810ULL, },
+ { 0xffffffffffffffffULL, 0x4fb18dff56564a28ULL, },
+ { 0xffffffffffffffffULL, 0xb5ca4fd8546e07b4ULL, },
+ { 0xf8b9fd198694378eULL, 0xd9589437a7be92acULL, },
+ { 0xffffffffffffffffULL, 0xa0e943f2be82359cULL, },
+};
+
+ gettimeofday(&start, NULL);
+
+ for (i = 0; i < PATTERN_INPUTS_SHORT_COUNT; i++) {
+ for (j = 0; j < PATTERN_INPUTS_SHORT_COUNT; j++) {
+ do_msa_ADDS_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_ADDS_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-add/test_msa_adds_u_h.c b/tests/tcg/mips/user/ase/msa/int-add/test_msa_adds_u_h.c
new file mode 100644
index 0000000..1e32f00
--- /dev/null
+++ b/tests/tcg/mips/user/ase/msa/int-add/test_msa_adds_u_h.c
@@ -0,0 +1,151 @@
+/*
+ * Test program for MSA instruction ADDS_U.H
+ *
+ * Copyright (C) 2019 Wave Computing, Inc.
+ * 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.h"
+#include "../../../../include/test_utils.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 = "ADDS_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] = {
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 0 */
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 8 */
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, },
+ { 0x5555555555555555ULL, 0x5555555555555555ULL, },
+ { 0xccccccccccccccccULL, 0xccccccccccccccccULL, },
+ { 0x3333333333333333ULL, 0x3333333333333333ULL, },
+ { 0xe38e38e38e38e38eULL, 0x38e38e38e38e38e3ULL, },
+ { 0x1c71c71c71c71c71ULL, 0xc71c71c71c71c71cULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 16 */
+ { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0xddddddddddddddddULL, 0xddddddddddddddddULL, },
+ { 0xffffe38dffffffffULL, 0xe38dffffffffe38dULL, },
+ { 0xc71bffffffffc71bULL, 0xffffffffc71bffffULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 24 */
+ { 0x5555555555555555ULL, 0x5555555555555555ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0x8888888888888888ULL, 0x8888888888888888ULL, },
+ { 0xffff8e38e38dffffULL, 0x8e38e38dffff8e38ULL, },
+ { 0x71c6ffffc71c71c6ULL, 0xffffc71c71c6ffffULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 32 */
+ { 0xccccccccccccccccULL, 0xccccccccccccccccULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0xe93dffffffffe93dULL, 0xffffffffe93dffffULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 40 */
+ { 0x3333333333333333ULL, 0x3333333333333333ULL, },
+ { 0xddddddddddddddddULL, 0xddddddddddddddddULL, },
+ { 0x8888888888888888ULL, 0x8888888888888888ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0x6666666666666666ULL, 0x6666666666666666ULL, },
+ { 0xffff6c16c16bffffULL, 0x6c16c16bffff6c16ULL, },
+ { 0x4fa4fa4fa4fa4fa4ULL, 0xfa4fa4fa4fa4fa4fULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 48 */
+ { 0xe38e38e38e38e38eULL, 0x38e38e38e38e38e3ULL, },
+ { 0xffffe38dffffffffULL, 0xe38dffffffffe38dULL, },
+ { 0xffff8e38e38dffffULL, 0x8e38e38dffff8e38ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0xffff6c16c16bffffULL, 0x6c16c16bffff6c16ULL, },
+ { 0xffff71c6ffffffffULL, 0x71c6ffffffff71c6ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 56 */
+ { 0x1c71c71c71c71c71ULL, 0xc71c71c71c71c71cULL, },
+ { 0xc71bffffffffc71bULL, 0xffffffffc71bffffULL, },
+ { 0x71c6ffffc71c71c6ULL, 0xffffc71c71c6ffffULL, },
+ { 0xe93dffffffffe93dULL, 0xffffffffe93dffffULL, },
+ { 0x4fa4fa4fa4fa4fa4ULL, 0xfa4fa4fa4fa4fa4fULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0x38e2ffffe38e38e2ULL, 0xffffe38e38e2ffffULL, },
+ { 0xffffffff50c4aa80ULL, 0x96ce16bcffffffffULL, }, /* 64 */
+ { 0xffffe72f75f5ffffULL, 0x5e5ec678ffffffffULL, },
+ { 0xffffffffe231e0c0ULL, 0x733fd25dffffd520ULL, },
+ { 0xf8b9fd198693ffffULL, 0xd9589436ffffffffULL, },
+ { 0xffffe72f75f5ffffULL, 0x5e5ec678ffffffffULL, },
+ { 0xffff00c69b26ffffULL, 0x25eeffff2a7ea5f8ULL, },
+ { 0xffffaf0dffffffffULL, 0x3acfffffc06a7810ULL, },
+ { 0xffff16b0abc4ffffULL, 0xa0e8ffffbe81ffffULL, },
+ { 0xffffffffe231e0c0ULL, 0x733fd25dffffd520ULL, }, /* 72 */
+ { 0xffffaf0dffffffffULL, 0x3acfffffc06a7810ULL, },
+ { 0xffffffffffffffffULL, 0x4fb0ffffffff4a28ULL, },
+ { 0xffffc4f7ffffffffULL, 0xb5c9ffffffffffffULL, },
+ { 0xf8b9fd198693ffffULL, 0xd9589436ffffffffULL, },
+ { 0xffff16b0abc4ffffULL, 0xa0e8ffffbe81ffffULL, },
+};
+
+ gettimeofday(&start, NULL);
+
+ for (i = 0; i < PATTERN_INPUTS_SHORT_COUNT; i++) {
+ for (j = 0; j < PATTERN_INPUTS_SHORT_COUNT; j++) {
+ do_msa_ADDS_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_ADDS_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-add/test_msa_adds_u_w.c b/tests/tcg/mips/user/ase/msa/int-add/test_msa_adds_u_w.c
new file mode 100644
index 0000000..938d2da
--- /dev/null
+++ b/tests/tcg/mips/user/ase/msa/int-add/test_msa_adds_u_w.c
@@ -0,0 +1,151 @@
+/*
+ * Test program for MSA instruction ADDS_U.W
+ *
+ * Copyright (C) 2019 Wave Computing, Inc.
+ * 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.h"
+#include "../../../../include/test_utils.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 = "ADDS_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] = {
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 0 */
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 8 */
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, },
+ { 0x5555555555555555ULL, 0x5555555555555555ULL, },
+ { 0xccccccccccccccccULL, 0xccccccccccccccccULL, },
+ { 0x3333333333333333ULL, 0x3333333333333333ULL, },
+ { 0xe38e38e38e38e38eULL, 0x38e38e38e38e38e3ULL, },
+ { 0x1c71c71c71c71c71ULL, 0xc71c71c71c71c71cULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 16 */
+ { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0xddddddddddddddddULL, 0xddddddddddddddddULL, },
+ { 0xffffffffffffffffULL, 0xe38e38e2ffffffffULL, },
+ { 0xc71c71c6ffffffffULL, 0xffffffffc71c71c6ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 24 */
+ { 0x5555555555555555ULL, 0x5555555555555555ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0x8888888888888888ULL, 0x8888888888888888ULL, },
+ { 0xffffffffe38e38e3ULL, 0x8e38e38dffffffffULL, },
+ { 0x71c71c71c71c71c6ULL, 0xffffffff71c71c71ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 32 */
+ { 0xccccccccccccccccULL, 0xccccccccccccccccULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0xe93e93e8ffffffffULL, 0xffffffffe93e93e8ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 40 */
+ { 0x3333333333333333ULL, 0x3333333333333333ULL, },
+ { 0xddddddddddddddddULL, 0xddddddddddddddddULL, },
+ { 0x8888888888888888ULL, 0x8888888888888888ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0x6666666666666666ULL, 0x6666666666666666ULL, },
+ { 0xffffffffc16c16c1ULL, 0x6c16c16bffffffffULL, },
+ { 0x4fa4fa4fa4fa4fa4ULL, 0xfa4fa4fa4fa4fa4fULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 48 */
+ { 0xe38e38e38e38e38eULL, 0x38e38e38e38e38e3ULL, },
+ { 0xffffffffffffffffULL, 0xe38e38e2ffffffffULL, },
+ { 0xffffffffe38e38e3ULL, 0x8e38e38dffffffffULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0xffffffffc16c16c1ULL, 0x6c16c16bffffffffULL, },
+ { 0xffffffffffffffffULL, 0x71c71c70ffffffffULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 56 */
+ { 0x1c71c71c71c71c71ULL, 0xc71c71c71c71c71cULL, },
+ { 0xc71c71c6ffffffffULL, 0xffffffffc71c71c6ULL, },
+ { 0x71c71c71c71c71c6ULL, 0xffffffff71c71c71ULL, },
+ { 0xe93e93e8ffffffffULL, 0xffffffffe93e93e8ULL, },
+ { 0x4fa4fa4fa4fa4fa4ULL, 0xfa4fa4fa4fa4fa4fULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0x38e38e38e38e38e2ULL, 0xffffffff38e38e38ULL, },
+ { 0xffffffff50c4aa80ULL, 0x96ce16bcffffffffULL, }, /* 64 */
+ { 0xffffffff75f61c48ULL, 0x5e5ec678ffffffffULL, },
+ { 0xffffffffe231e0c0ULL, 0x733fd25dffffffffULL, },
+ { 0xf8b9fd198694378eULL, 0xd9589436ffffffffULL, },
+ { 0xffffffff75f61c48ULL, 0x5e5ec678ffffffffULL, },
+ { 0xffffffff9b278e10ULL, 0x25ef76342a7ea5f8ULL, },
+ { 0xffffffffffffffffULL, 0x3ad08219c06a7810ULL, },
+ { 0xffffffffabc5a956ULL, 0xa0e943f2be82359cULL, },
+ { 0xffffffffe231e0c0ULL, 0x733fd25dffffffffULL, }, /* 72 */
+ { 0xffffffffffffffffULL, 0x3ad08219c06a7810ULL, },
+ { 0xffffffffffffffffULL, 0x4fb18dfeffffffffULL, },
+ { 0xffffffffffffffffULL, 0xb5ca4fd7ffffffffULL, },
+ { 0xf8b9fd198694378eULL, 0xd9589436ffffffffULL, },
+ { 0xffffffffabc5a956ULL, 0xa0e943f2be82359cULL, },
+};
+
+ gettimeofday(&start, NULL);
+
+ for (i = 0; i < PATTERN_INPUTS_SHORT_COUNT; i++) {
+ for (j = 0; j < PATTERN_INPUTS_SHORT_COUNT; j++) {
+ do_msa_ADDS_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_ADDS_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-add/test_msa_addv_b.c b/tests/tcg/mips/user/ase/msa/int-add/test_msa_addv_b.c
new file mode 100644
index 0000000..5dba386
--- /dev/null
+++ b/tests/tcg/mips/user/ase/msa/int-add/test_msa_addv_b.c
@@ -0,0 +1,151 @@
+/*
+ * Test program for MSA instruction ADDV.B
+ *
+ * Copyright (C) 2019 Wave Computing, Inc.
+ * 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.h"
+#include "../../../../include/test_utils.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 = "ADDV.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] = {
+ { 0xfefefefefefefefeULL, 0xfefefefefefefefeULL, }, /* 0 */
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0xa9a9a9a9a9a9a9a9ULL, 0xa9a9a9a9a9a9a9a9ULL, },
+ { 0x5454545454545454ULL, 0x5454545454545454ULL, },
+ { 0xcbcbcbcbcbcbcbcbULL, 0xcbcbcbcbcbcbcbcbULL, },
+ { 0x3232323232323232ULL, 0x3232323232323232ULL, },
+ { 0xe28d37e28d37e28dULL, 0x37e28d37e28d37e2ULL, },
+ { 0x1b70c61b70c61b70ULL, 0xc61b70c61b70c61bULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 8 */
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, },
+ { 0x5555555555555555ULL, 0x5555555555555555ULL, },
+ { 0xccccccccccccccccULL, 0xccccccccccccccccULL, },
+ { 0x3333333333333333ULL, 0x3333333333333333ULL, },
+ { 0xe38e38e38e38e38eULL, 0x38e38e38e38e38e3ULL, },
+ { 0x1c71c71c71c71c71ULL, 0xc71c71c71c71c71cULL, },
+ { 0xa9a9a9a9a9a9a9a9ULL, 0xa9a9a9a9a9a9a9a9ULL, }, /* 16 */
+ { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, },
+ { 0x5454545454545454ULL, 0x5454545454545454ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0x7676767676767676ULL, 0x7676767676767676ULL, },
+ { 0xddddddddddddddddULL, 0xddddddddddddddddULL, },
+ { 0x8d38e28d38e28d38ULL, 0xe28d38e28d38e28dULL, },
+ { 0xc61b71c61b71c61bULL, 0x71c61b71c61b71c6ULL, },
+ { 0x5454545454545454ULL, 0x5454545454545454ULL, }, /* 24 */
+ { 0x5555555555555555ULL, 0x5555555555555555ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, },
+ { 0x2121212121212121ULL, 0x2121212121212121ULL, },
+ { 0x8888888888888888ULL, 0x8888888888888888ULL, },
+ { 0x38e38d38e38d38e3ULL, 0x8d38e38d38e38d38ULL, },
+ { 0x71c61c71c61c71c6ULL, 0x1c71c61c71c61c71ULL, },
+ { 0xcbcbcbcbcbcbcbcbULL, 0xcbcbcbcbcbcbcbcbULL, }, /* 32 */
+ { 0xccccccccccccccccULL, 0xccccccccccccccccULL, },
+ { 0x7676767676767676ULL, 0x7676767676767676ULL, },
+ { 0x2121212121212121ULL, 0x2121212121212121ULL, },
+ { 0x9898989898989898ULL, 0x9898989898989898ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0xaf5a04af5a04af5aULL, 0x04af5a04af5a04afULL, },
+ { 0xe83d93e83d93e83dULL, 0x93e83d93e83d93e8ULL, },
+ { 0x3232323232323232ULL, 0x3232323232323232ULL, }, /* 40 */
+ { 0x3333333333333333ULL, 0x3333333333333333ULL, },
+ { 0xddddddddddddddddULL, 0xddddddddddddddddULL, },
+ { 0x8888888888888888ULL, 0x8888888888888888ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0x6666666666666666ULL, 0x6666666666666666ULL, },
+ { 0x16c16b16c16b16c1ULL, 0x6b16c16b16c16b16ULL, },
+ { 0x4fa4fa4fa4fa4fa4ULL, 0xfa4fa4fa4fa4fa4fULL, },
+ { 0xe28d37e28d37e28dULL, 0x37e28d37e28d37e2ULL, }, /* 48 */
+ { 0xe38e38e38e38e38eULL, 0x38e38e38e38e38e3ULL, },
+ { 0x8d38e28d38e28d38ULL, 0xe28d38e28d38e28dULL, },
+ { 0x38e38d38e38d38e3ULL, 0x8d38e38d38e38d38ULL, },
+ { 0xaf5a04af5a04af5aULL, 0x04af5a04af5a04afULL, },
+ { 0x16c16b16c16b16c1ULL, 0x6b16c16b16c16b16ULL, },
+ { 0xc61c70c61c70c61cULL, 0x70c61c70c61c70c6ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0x1b70c61b70c61b70ULL, 0xc61b70c61b70c61bULL, }, /* 56 */
+ { 0x1c71c71c71c71c71ULL, 0xc71c71c71c71c71cULL, },
+ { 0xc61b71c61b71c61bULL, 0x71c61b71c61b71c6ULL, },
+ { 0x71c61c71c61c71c6ULL, 0x1c71c61c71c61c71ULL, },
+ { 0xe83d93e83d93e83dULL, 0x93e83d93e83d93e8ULL, },
+ { 0x4fa4fa4fa4fa4fa4ULL, 0xfa4fa4fa4fa4fa4fULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0x38e28e38e28e38e2ULL, 0x8e38e28e38e28e38ULL, },
+ { 0x10d4cc9850c4aa80ULL, 0x96ce16bcfcf66018ULL, }, /* 64 */
+ { 0x8328e62f75f51c48ULL, 0x5d5ec67813ba0208ULL, },
+ { 0x34c49476e131e0c0ULL, 0x723fd15da9a6d520ULL, },
+ { 0xf8b9fc198693378eULL, 0xd8589336a7bd92acULL, },
+ { 0x8328e62f75f51c48ULL, 0x5d5ec67813ba0208ULL, },
+ { 0xf67c00c69a268e10ULL, 0x24ee76342a7ea4f8ULL, },
+ { 0xa718ae0d06625288ULL, 0x39cf8119c06a7710ULL, },
+ { 0x6b0d16b0abc4a956ULL, 0x9fe843f2be81349cULL, },
+ { 0x34c49476e131e0c0ULL, 0x723fd15da9a6d520ULL, }, /* 72 */
+ { 0xa718ae0d06625288ULL, 0x39cf8119c06a7710ULL, },
+ { 0x58b45c54729e1600ULL, 0x4eb08cfe56564a28ULL, },
+ { 0x1ca9c4f717006dceULL, 0xb4c94ed7546d07b4ULL, },
+ { 0xf8b9fc198693378eULL, 0xd8589336a7bd92acULL, },
+ { 0x6b0d16b0abc4a956ULL, 0x9fe843f2be81349cULL, },
+};
+
+ gettimeofday(&start, NULL);
+
+ for (i = 0; i < PATTERN_INPUTS_SHORT_COUNT; i++) {
+ for (j = 0; j < PATTERN_INPUTS_SHORT_COUNT; j++) {
+ do_msa_ADDV_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_ADDV_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-add/test_msa_addv_d.c b/tests/tcg/mips/user/ase/msa/int-add/test_msa_addv_d.c
new file mode 100644
index 0000000..339878c
--- /dev/null
+++ b/tests/tcg/mips/user/ase/msa/int-add/test_msa_addv_d.c
@@ -0,0 +1,151 @@
+/*
+ * Test program for MSA instruction ADDV.D
+ *
+ * Copyright (C) 2019 Wave Computing, Inc.
+ * 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.h"
+#include "../../../../include/test_utils.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 = "ADDV.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] = {
+ { 0xfffffffffffffffeULL, 0xfffffffffffffffeULL, }, /* 0 */
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0xaaaaaaaaaaaaaaa9ULL, 0xaaaaaaaaaaaaaaa9ULL, },
+ { 0x5555555555555554ULL, 0x5555555555555554ULL, },
+ { 0xcccccccccccccccbULL, 0xcccccccccccccccbULL, },
+ { 0x3333333333333332ULL, 0x3333333333333332ULL, },
+ { 0xe38e38e38e38e38dULL, 0x38e38e38e38e38e2ULL, },
+ { 0x1c71c71c71c71c70ULL, 0xc71c71c71c71c71bULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 8 */
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, },
+ { 0x5555555555555555ULL, 0x5555555555555555ULL, },
+ { 0xccccccccccccccccULL, 0xccccccccccccccccULL, },
+ { 0x3333333333333333ULL, 0x3333333333333333ULL, },
+ { 0xe38e38e38e38e38eULL, 0x38e38e38e38e38e3ULL, },
+ { 0x1c71c71c71c71c71ULL, 0xc71c71c71c71c71cULL, },
+ { 0xaaaaaaaaaaaaaaa9ULL, 0xaaaaaaaaaaaaaaa9ULL, }, /* 16 */
+ { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, },
+ { 0x5555555555555554ULL, 0x5555555555555554ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0x7777777777777776ULL, 0x7777777777777776ULL, },
+ { 0xddddddddddddddddULL, 0xddddddddddddddddULL, },
+ { 0x8e38e38e38e38e38ULL, 0xe38e38e38e38e38dULL, },
+ { 0xc71c71c71c71c71bULL, 0x71c71c71c71c71c6ULL, },
+ { 0x5555555555555554ULL, 0x5555555555555554ULL, }, /* 24 */
+ { 0x5555555555555555ULL, 0x5555555555555555ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, },
+ { 0x2222222222222221ULL, 0x2222222222222221ULL, },
+ { 0x8888888888888888ULL, 0x8888888888888888ULL, },
+ { 0x38e38e38e38e38e3ULL, 0x8e38e38e38e38e38ULL, },
+ { 0x71c71c71c71c71c6ULL, 0x1c71c71c71c71c71ULL, },
+ { 0xcccccccccccccccbULL, 0xcccccccccccccccbULL, }, /* 32 */
+ { 0xccccccccccccccccULL, 0xccccccccccccccccULL, },
+ { 0x7777777777777776ULL, 0x7777777777777776ULL, },
+ { 0x2222222222222221ULL, 0x2222222222222221ULL, },
+ { 0x9999999999999998ULL, 0x9999999999999998ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0xb05b05b05b05b05aULL, 0x05b05b05b05b05afULL, },
+ { 0xe93e93e93e93e93dULL, 0x93e93e93e93e93e8ULL, },
+ { 0x3333333333333332ULL, 0x3333333333333332ULL, }, /* 40 */
+ { 0x3333333333333333ULL, 0x3333333333333333ULL, },
+ { 0xddddddddddddddddULL, 0xddddddddddddddddULL, },
+ { 0x8888888888888888ULL, 0x8888888888888888ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0x6666666666666666ULL, 0x6666666666666666ULL, },
+ { 0x16c16c16c16c16c1ULL, 0x6c16c16c16c16c16ULL, },
+ { 0x4fa4fa4fa4fa4fa4ULL, 0xfa4fa4fa4fa4fa4fULL, },
+ { 0xe38e38e38e38e38dULL, 0x38e38e38e38e38e2ULL, }, /* 48 */
+ { 0xe38e38e38e38e38eULL, 0x38e38e38e38e38e3ULL, },
+ { 0x8e38e38e38e38e38ULL, 0xe38e38e38e38e38dULL, },
+ { 0x38e38e38e38e38e3ULL, 0x8e38e38e38e38e38ULL, },
+ { 0xb05b05b05b05b05aULL, 0x05b05b05b05b05afULL, },
+ { 0x16c16c16c16c16c1ULL, 0x6c16c16c16c16c16ULL, },
+ { 0xc71c71c71c71c71cULL, 0x71c71c71c71c71c6ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0x1c71c71c71c71c70ULL, 0xc71c71c71c71c71bULL, }, /* 56 */
+ { 0x1c71c71c71c71c71ULL, 0xc71c71c71c71c71cULL, },
+ { 0xc71c71c71c71c71bULL, 0x71c71c71c71c71c6ULL, },
+ { 0x71c71c71c71c71c6ULL, 0x1c71c71c71c71c71ULL, },
+ { 0xe93e93e93e93e93dULL, 0x93e93e93e93e93e8ULL, },
+ { 0x4fa4fa4fa4fa4fa4ULL, 0xfa4fa4fa4fa4fa4fULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0x38e38e38e38e38e2ULL, 0x8e38e38e38e38e38ULL, },
+ { 0x10d5cd9850c4aa80ULL, 0x96ce16bdfcf76018ULL, }, /* 64 */
+ { 0x8428e72f75f61c48ULL, 0x5e5ec67913bb0308ULL, },
+ { 0x34c59576e231e0c0ULL, 0x733fd25ea9a6d520ULL, },
+ { 0xf8b9fd198694378eULL, 0xd9589437a7be92acULL, },
+ { 0x8428e72f75f61c48ULL, 0x5e5ec67913bb0308ULL, },
+ { 0xf77c00c69b278e10ULL, 0x25ef76342a7ea5f8ULL, },
+ { 0xa818af0e07635288ULL, 0x3ad08219c06a7810ULL, },
+ { 0x6c0d16b0abc5a956ULL, 0xa0e943f2be82359cULL, },
+ { 0x34c59576e231e0c0ULL, 0x733fd25ea9a6d520ULL, }, /* 72 */
+ { 0xa818af0e07635288ULL, 0x3ad08219c06a7810ULL, },
+ { 0x58b55d55739f1700ULL, 0x4fb18dff56564a28ULL, },
+ { 0x1ca9c4f818016dceULL, 0xb5ca4fd8546e07b4ULL, },
+ { 0xf8b9fd198694378eULL, 0xd9589437a7be92acULL, },
+ { 0x6c0d16b0abc5a956ULL, 0xa0e943f2be82359cULL, },
+};
+
+ gettimeofday(&start, NULL);
+
+ for (i = 0; i < PATTERN_INPUTS_SHORT_COUNT; i++) {
+ for (j = 0; j < PATTERN_INPUTS_SHORT_COUNT; j++) {
+ do_msa_ADDV_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_ADDV_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-add/test_msa_addv_h.c b/tests/tcg/mips/user/ase/msa/int-add/test_msa_addv_h.c
new file mode 100644
index 0000000..3add379
--- /dev/null
+++ b/tests/tcg/mips/user/ase/msa/int-add/test_msa_addv_h.c
@@ -0,0 +1,151 @@
+/*
+ * Test program for MSA instruction ADDV.H
+ *
+ * Copyright (C) 2019 Wave Computing, Inc.
+ * 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.h"
+#include "../../../../include/test_utils.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 = "ADDV.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] = {
+ { 0xfffefffefffefffeULL, 0xfffefffefffefffeULL, }, /* 0 */
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0xaaa9aaa9aaa9aaa9ULL, 0xaaa9aaa9aaa9aaa9ULL, },
+ { 0x5554555455545554ULL, 0x5554555455545554ULL, },
+ { 0xcccbcccbcccbcccbULL, 0xcccbcccbcccbcccbULL, },
+ { 0x3332333233323332ULL, 0x3332333233323332ULL, },
+ { 0xe38d38e28e37e38dULL, 0x38e28e37e38d38e2ULL, },
+ { 0x1c70c71b71c61c70ULL, 0xc71b71c61c70c71bULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 8 */
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, },
+ { 0x5555555555555555ULL, 0x5555555555555555ULL, },
+ { 0xccccccccccccccccULL, 0xccccccccccccccccULL, },
+ { 0x3333333333333333ULL, 0x3333333333333333ULL, },
+ { 0xe38e38e38e38e38eULL, 0x38e38e38e38e38e3ULL, },
+ { 0x1c71c71c71c71c71ULL, 0xc71c71c71c71c71cULL, },
+ { 0xaaa9aaa9aaa9aaa9ULL, 0xaaa9aaa9aaa9aaa9ULL, }, /* 16 */
+ { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, },
+ { 0x5554555455545554ULL, 0x5554555455545554ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0x7776777677767776ULL, 0x7776777677767776ULL, },
+ { 0xddddddddddddddddULL, 0xddddddddddddddddULL, },
+ { 0x8e38e38d38e28e38ULL, 0xe38d38e28e38e38dULL, },
+ { 0xc71b71c61c71c71bULL, 0x71c61c71c71b71c6ULL, },
+ { 0x5554555455545554ULL, 0x5554555455545554ULL, }, /* 24 */
+ { 0x5555555555555555ULL, 0x5555555555555555ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, },
+ { 0x2221222122212221ULL, 0x2221222122212221ULL, },
+ { 0x8888888888888888ULL, 0x8888888888888888ULL, },
+ { 0x38e38e38e38d38e3ULL, 0x8e38e38d38e38e38ULL, },
+ { 0x71c61c71c71c71c6ULL, 0x1c71c71c71c61c71ULL, },
+ { 0xcccbcccbcccbcccbULL, 0xcccbcccbcccbcccbULL, }, /* 32 */
+ { 0xccccccccccccccccULL, 0xccccccccccccccccULL, },
+ { 0x7776777677767776ULL, 0x7776777677767776ULL, },
+ { 0x2221222122212221ULL, 0x2221222122212221ULL, },
+ { 0x9998999899989998ULL, 0x9998999899989998ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0xb05a05af5b04b05aULL, 0x05af5b04b05a05afULL, },
+ { 0xe93d93e83e93e93dULL, 0x93e83e93e93d93e8ULL, },
+ { 0x3332333233323332ULL, 0x3332333233323332ULL, }, /* 40 */
+ { 0x3333333333333333ULL, 0x3333333333333333ULL, },
+ { 0xddddddddddddddddULL, 0xddddddddddddddddULL, },
+ { 0x8888888888888888ULL, 0x8888888888888888ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0x6666666666666666ULL, 0x6666666666666666ULL, },
+ { 0x16c16c16c16b16c1ULL, 0x6c16c16b16c16c16ULL, },
+ { 0x4fa4fa4fa4fa4fa4ULL, 0xfa4fa4fa4fa4fa4fULL, },
+ { 0xe38d38e28e37e38dULL, 0x38e28e37e38d38e2ULL, }, /* 48 */
+ { 0xe38e38e38e38e38eULL, 0x38e38e38e38e38e3ULL, },
+ { 0x8e38e38d38e28e38ULL, 0xe38d38e28e38e38dULL, },
+ { 0x38e38e38e38d38e3ULL, 0x8e38e38d38e38e38ULL, },
+ { 0xb05a05af5b04b05aULL, 0x05af5b04b05a05afULL, },
+ { 0x16c16c16c16b16c1ULL, 0x6c16c16b16c16c16ULL, },
+ { 0xc71c71c61c70c71cULL, 0x71c61c70c71c71c6ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0x1c70c71b71c61c70ULL, 0xc71b71c61c70c71bULL, }, /* 56 */
+ { 0x1c71c71c71c71c71ULL, 0xc71c71c71c71c71cULL, },
+ { 0xc71b71c61c71c71bULL, 0x71c61c71c71b71c6ULL, },
+ { 0x71c61c71c71c71c6ULL, 0x1c71c71c71c61c71ULL, },
+ { 0xe93d93e83e93e93dULL, 0x93e83e93e93d93e8ULL, },
+ { 0x4fa4fa4fa4fa4fa4ULL, 0xfa4fa4fa4fa4fa4fULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0x38e28e38e38e38e2ULL, 0x8e38e38e38e28e38ULL, },
+ { 0x10d4cd9850c4aa80ULL, 0x96ce16bcfcf66018ULL, }, /* 64 */
+ { 0x8428e72f75f51c48ULL, 0x5e5ec67813ba0308ULL, },
+ { 0x34c49576e231e0c0ULL, 0x733fd25da9a6d520ULL, },
+ { 0xf8b9fd198693378eULL, 0xd9589436a7bd92acULL, },
+ { 0x8428e72f75f51c48ULL, 0x5e5ec67813ba0308ULL, },
+ { 0xf77c00c69b268e10ULL, 0x25ee76342a7ea5f8ULL, },
+ { 0xa818af0d07625288ULL, 0x3acf8219c06a7810ULL, },
+ { 0x6c0d16b0abc4a956ULL, 0xa0e843f2be81359cULL, },
+ { 0x34c49576e231e0c0ULL, 0x733fd25da9a6d520ULL, }, /* 72 */
+ { 0xa818af0d07625288ULL, 0x3acf8219c06a7810ULL, },
+ { 0x58b45d54739e1700ULL, 0x4fb08dfe56564a28ULL, },
+ { 0x1ca9c4f718006dceULL, 0xb5c94fd7546d07b4ULL, },
+ { 0xf8b9fd198693378eULL, 0xd9589436a7bd92acULL, },
+ { 0x6c0d16b0abc4a956ULL, 0xa0e843f2be81359cULL, },
+};
+
+ gettimeofday(&start, NULL);
+
+ for (i = 0; i < PATTERN_INPUTS_SHORT_COUNT; i++) {
+ for (j = 0; j < PATTERN_INPUTS_SHORT_COUNT; j++) {
+ do_msa_ADDV_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_ADDV_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-add/test_msa_addv_w.c b/tests/tcg/mips/user/ase/msa/int-add/test_msa_addv_w.c
new file mode 100644
index 0000000..41f86ab
--- /dev/null
+++ b/tests/tcg/mips/user/ase/msa/int-add/test_msa_addv_w.c
@@ -0,0 +1,151 @@
+/*
+ * Test program for MSA instruction ADDV.W
+ *
+ * Copyright (C) 2019 Wave Computing, Inc.
+ * 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.h"
+#include "../../../../include/test_utils.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 = "ADDV.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] = {
+ { 0xfffffffefffffffeULL, 0xfffffffefffffffeULL, }, /* 0 */
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0xaaaaaaa9aaaaaaa9ULL, 0xaaaaaaa9aaaaaaa9ULL, },
+ { 0x5555555455555554ULL, 0x5555555455555554ULL, },
+ { 0xcccccccbcccccccbULL, 0xcccccccbcccccccbULL, },
+ { 0x3333333233333332ULL, 0x3333333233333332ULL, },
+ { 0xe38e38e28e38e38dULL, 0x38e38e37e38e38e2ULL, },
+ { 0x1c71c71b71c71c70ULL, 0xc71c71c61c71c71bULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 8 */
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, },
+ { 0x5555555555555555ULL, 0x5555555555555555ULL, },
+ { 0xccccccccccccccccULL, 0xccccccccccccccccULL, },
+ { 0x3333333333333333ULL, 0x3333333333333333ULL, },
+ { 0xe38e38e38e38e38eULL, 0x38e38e38e38e38e3ULL, },
+ { 0x1c71c71c71c71c71ULL, 0xc71c71c71c71c71cULL, },
+ { 0xaaaaaaa9aaaaaaa9ULL, 0xaaaaaaa9aaaaaaa9ULL, }, /* 16 */
+ { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, },
+ { 0x5555555455555554ULL, 0x5555555455555554ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0x7777777677777776ULL, 0x7777777677777776ULL, },
+ { 0xddddddddddddddddULL, 0xddddddddddddddddULL, },
+ { 0x8e38e38d38e38e38ULL, 0xe38e38e28e38e38dULL, },
+ { 0xc71c71c61c71c71bULL, 0x71c71c71c71c71c6ULL, },
+ { 0x5555555455555554ULL, 0x5555555455555554ULL, }, /* 24 */
+ { 0x5555555555555555ULL, 0x5555555555555555ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, },
+ { 0x2222222122222221ULL, 0x2222222122222221ULL, },
+ { 0x8888888888888888ULL, 0x8888888888888888ULL, },
+ { 0x38e38e38e38e38e3ULL, 0x8e38e38d38e38e38ULL, },
+ { 0x71c71c71c71c71c6ULL, 0x1c71c71c71c71c71ULL, },
+ { 0xcccccccbcccccccbULL, 0xcccccccbcccccccbULL, }, /* 32 */
+ { 0xccccccccccccccccULL, 0xccccccccccccccccULL, },
+ { 0x7777777677777776ULL, 0x7777777677777776ULL, },
+ { 0x2222222122222221ULL, 0x2222222122222221ULL, },
+ { 0x9999999899999998ULL, 0x9999999899999998ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0xb05b05af5b05b05aULL, 0x05b05b04b05b05afULL, },
+ { 0xe93e93e83e93e93dULL, 0x93e93e93e93e93e8ULL, },
+ { 0x3333333233333332ULL, 0x3333333233333332ULL, }, /* 40 */
+ { 0x3333333333333333ULL, 0x3333333333333333ULL, },
+ { 0xddddddddddddddddULL, 0xddddddddddddddddULL, },
+ { 0x8888888888888888ULL, 0x8888888888888888ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0x6666666666666666ULL, 0x6666666666666666ULL, },
+ { 0x16c16c16c16c16c1ULL, 0x6c16c16b16c16c16ULL, },
+ { 0x4fa4fa4fa4fa4fa4ULL, 0xfa4fa4fa4fa4fa4fULL, },
+ { 0xe38e38e28e38e38dULL, 0x38e38e37e38e38e2ULL, }, /* 48 */
+ { 0xe38e38e38e38e38eULL, 0x38e38e38e38e38e3ULL, },
+ { 0x8e38e38d38e38e38ULL, 0xe38e38e28e38e38dULL, },
+ { 0x38e38e38e38e38e3ULL, 0x8e38e38d38e38e38ULL, },
+ { 0xb05b05af5b05b05aULL, 0x05b05b04b05b05afULL, },
+ { 0x16c16c16c16c16c1ULL, 0x6c16c16b16c16c16ULL, },
+ { 0xc71c71c61c71c71cULL, 0x71c71c70c71c71c6ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0x1c71c71b71c71c70ULL, 0xc71c71c61c71c71bULL, }, /* 56 */
+ { 0x1c71c71c71c71c71ULL, 0xc71c71c71c71c71cULL, },
+ { 0xc71c71c61c71c71bULL, 0x71c71c71c71c71c6ULL, },
+ { 0x71c71c71c71c71c6ULL, 0x1c71c71c71c71c71ULL, },
+ { 0xe93e93e83e93e93dULL, 0x93e93e93e93e93e8ULL, },
+ { 0x4fa4fa4fa4fa4fa4ULL, 0xfa4fa4fa4fa4fa4fULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0x38e38e38e38e38e2ULL, 0x8e38e38e38e38e38ULL, },
+ { 0x10d5cd9850c4aa80ULL, 0x96ce16bcfcf76018ULL, }, /* 64 */
+ { 0x8428e72f75f61c48ULL, 0x5e5ec67813bb0308ULL, },
+ { 0x34c59576e231e0c0ULL, 0x733fd25da9a6d520ULL, },
+ { 0xf8b9fd198694378eULL, 0xd9589436a7be92acULL, },
+ { 0x8428e72f75f61c48ULL, 0x5e5ec67813bb0308ULL, },
+ { 0xf77c00c69b278e10ULL, 0x25ef76342a7ea5f8ULL, },
+ { 0xa818af0d07635288ULL, 0x3ad08219c06a7810ULL, },
+ { 0x6c0d16b0abc5a956ULL, 0xa0e943f2be82359cULL, },
+ { 0x34c59576e231e0c0ULL, 0x733fd25da9a6d520ULL, }, /* 72 */
+ { 0xa818af0d07635288ULL, 0x3ad08219c06a7810ULL, },
+ { 0x58b55d54739f1700ULL, 0x4fb18dfe56564a28ULL, },
+ { 0x1ca9c4f718016dceULL, 0xb5ca4fd7546e07b4ULL, },
+ { 0xf8b9fd198694378eULL, 0xd9589436a7be92acULL, },
+ { 0x6c0d16b0abc5a956ULL, 0xa0e943f2be82359cULL, },
+};
+
+ gettimeofday(&start, NULL);
+
+ for (i = 0; i < PATTERN_INPUTS_SHORT_COUNT; i++) {
+ for (j = 0; j < PATTERN_INPUTS_SHORT_COUNT; j++) {
+ do_msa_ADDV_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_ADDV_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_hadd_s_d.c b/tests/tcg/mips/user/ase/msa/int-add/test_msa_hadd_s_d.c
new file mode 100644
index 0000000..a6975e7
--- /dev/null
+++ b/tests/tcg/mips/user/ase/msa/int-add/test_msa_hadd_s_d.c
@@ -0,0 +1,151 @@
+/*
+ * Test program for MSA instruction HADD_S.D
+ *
+ * Copyright (C) 2019 Wave Computing, Inc.
+ * 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.h"
+#include "../../../../include/test_utils.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 = "HADD_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] = {
+ { 0xfffffffffffffffeULL, 0xfffffffffffffffeULL, }, /* 0 */
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0xffffffffaaaaaaa9ULL, 0xffffffffaaaaaaa9ULL, },
+ { 0x0000000055555554ULL, 0x0000000055555554ULL, },
+ { 0xffffffffcccccccbULL, 0xffffffffcccccccbULL, },
+ { 0x0000000033333332ULL, 0x0000000033333332ULL, },
+ { 0xffffffff8e38e38dULL, 0xffffffffe38e38e2ULL, },
+ { 0x0000000071c71c70ULL, 0x000000001c71c71bULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 8 */
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xffffffffaaaaaaaaULL, 0xffffffffaaaaaaaaULL, },
+ { 0x0000000055555555ULL, 0x0000000055555555ULL, },
+ { 0xffffffffccccccccULL, 0xffffffffccccccccULL, },
+ { 0x0000000033333333ULL, 0x0000000033333333ULL, },
+ { 0xffffffff8e38e38eULL, 0xffffffffe38e38e3ULL, },
+ { 0x0000000071c71c71ULL, 0x000000001c71c71cULL, },
+ { 0xffffffffaaaaaaa9ULL, 0xffffffffaaaaaaa9ULL, }, /* 16 */
+ { 0xffffffffaaaaaaaaULL, 0xffffffffaaaaaaaaULL, },
+ { 0xffffffff55555554ULL, 0xffffffff55555554ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0xffffffff77777776ULL, 0xffffffff77777776ULL, },
+ { 0xffffffffddddddddULL, 0xffffffffddddddddULL, },
+ { 0xffffffff38e38e38ULL, 0xffffffff8e38e38dULL, },
+ { 0x000000001c71c71bULL, 0xffffffffc71c71c6ULL, },
+ { 0x0000000055555554ULL, 0x0000000055555554ULL, }, /* 24 */
+ { 0x0000000055555555ULL, 0x0000000055555555ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0x00000000aaaaaaaaULL, 0x00000000aaaaaaaaULL, },
+ { 0x0000000022222221ULL, 0x0000000022222221ULL, },
+ { 0x0000000088888888ULL, 0x0000000088888888ULL, },
+ { 0xffffffffe38e38e3ULL, 0x0000000038e38e38ULL, },
+ { 0x00000000c71c71c6ULL, 0x0000000071c71c71ULL, },
+ { 0xffffffffcccccccbULL, 0xffffffffcccccccbULL, }, /* 32 */
+ { 0xffffffffccccccccULL, 0xffffffffccccccccULL, },
+ { 0xffffffff77777776ULL, 0xffffffff77777776ULL, },
+ { 0x0000000022222221ULL, 0x0000000022222221ULL, },
+ { 0xffffffff99999998ULL, 0xffffffff99999998ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0xffffffff5b05b05aULL, 0xffffffffb05b05afULL, },
+ { 0x000000003e93e93dULL, 0xffffffffe93e93e8ULL, },
+ { 0x0000000033333332ULL, 0x0000000033333332ULL, }, /* 40 */
+ { 0x0000000033333333ULL, 0x0000000033333333ULL, },
+ { 0xffffffffddddddddULL, 0xffffffffddddddddULL, },
+ { 0x0000000088888888ULL, 0x0000000088888888ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0x0000000066666666ULL, 0x0000000066666666ULL, },
+ { 0xffffffffc16c16c1ULL, 0x0000000016c16c16ULL, },
+ { 0x00000000a4fa4fa4ULL, 0x000000004fa4fa4fULL, },
+ { 0xffffffffe38e38e2ULL, 0x0000000038e38e37ULL, }, /* 48 */
+ { 0xffffffffe38e38e3ULL, 0x0000000038e38e38ULL, },
+ { 0xffffffff8e38e38dULL, 0xffffffffe38e38e2ULL, },
+ { 0x0000000038e38e38ULL, 0x000000008e38e38dULL, },
+ { 0xffffffffb05b05afULL, 0x0000000005b05b04ULL, },
+ { 0x0000000016c16c16ULL, 0x000000006c16c16bULL, },
+ { 0xffffffff71c71c71ULL, 0x000000001c71c71bULL, },
+ { 0x0000000055555554ULL, 0x0000000055555554ULL, },
+ { 0x000000001c71c71bULL, 0xffffffffc71c71c6ULL, }, /* 56 */
+ { 0x000000001c71c71cULL, 0xffffffffc71c71c7ULL, },
+ { 0xffffffffc71c71c6ULL, 0xffffffff71c71c71ULL, },
+ { 0x0000000071c71c71ULL, 0x000000001c71c71cULL, },
+ { 0xffffffffe93e93e8ULL, 0xffffffff93e93e93ULL, },
+ { 0x000000004fa4fa4fULL, 0xfffffffffa4fa4faULL, },
+ { 0xffffffffaaaaaaaaULL, 0xffffffffaaaaaaaaULL, },
+ { 0x000000008e38e38dULL, 0xffffffffe38e38e3ULL, },
+ { 0xffffffffb0cd3c0cULL, 0x0000000049e2bb6aULL, }, /* 64 */
+ { 0xffffffffd5feadd4ULL, 0x0000000060a65e5aULL, },
+ { 0xffffffff423a724cULL, 0xfffffffff6923072ULL, },
+ { 0xffffffffe69cc91aULL, 0xfffffffff4a9edfeULL, },
+ { 0x00000000242055a3ULL, 0x0000000011736b26ULL, },
+ { 0x000000004951c76bULL, 0x0000000028370e16ULL, },
+ { 0xffffffffb58d8be3ULL, 0xffffffffbe22e02eULL, },
+ { 0x0000000059efe2b1ULL, 0xffffffffbc3a9dbaULL, },
+ { 0xffffffffd4bd03eaULL, 0x000000002654770bULL, }, /* 72 */
+ { 0xfffffffff9ee75b2ULL, 0x000000003d1819fbULL, },
+ { 0xffffffff662a3a2aULL, 0xffffffffd303ec13ULL, },
+ { 0x000000000a8c90f8ULL, 0xffffffffd11ba99fULL, },
+ { 0x0000000098b16b8dULL, 0xffffffff8c6d38e4ULL, },
+ { 0x00000000bde2dd55ULL, 0xffffffffa330dbd4ULL, },
+};
+
+ gettimeofday(&start, NULL);
+
+ for (i = 0; i < PATTERN_INPUTS_SHORT_COUNT; i++) {
+ for (j = 0; j < PATTERN_INPUTS_SHORT_COUNT; j++) {
+ do_msa_HADD_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_HADD_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-add/test_msa_hadd_s_h.c b/tests/tcg/mips/user/ase/msa/int-add/test_msa_hadd_s_h.c
new file mode 100644
index 0000000..3b95551
--- /dev/null
+++ b/tests/tcg/mips/user/ase/msa/int-add/test_msa_hadd_s_h.c
@@ -0,0 +1,151 @@
+/*
+ * Test program for MSA instruction HADD_S.H
+ *
+ * Copyright (C) 2019 Wave Computing, Inc.
+ * 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.h"
+#include "../../../../include/test_utils.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 = "HADD_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] = {
+ { 0xfffefffefffefffeULL, 0xfffefffefffefffeULL, }, /* 0 */
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0xffa9ffa9ffa9ffa9ULL, 0xffa9ffa9ffa9ffa9ULL, },
+ { 0x0054005400540054ULL, 0x0054005400540054ULL, },
+ { 0xffcbffcbffcbffcbULL, 0xffcbffcbffcbffcbULL, },
+ { 0x0032003200320032ULL, 0x0032003200320032ULL, },
+ { 0xff8dffe20037ff8dULL, 0xffe20037ff8dffe2ULL, },
+ { 0x0070001bffc60070ULL, 0x001bffc60070001bULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 8 */
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xffaaffaaffaaffaaULL, 0xffaaffaaffaaffaaULL, },
+ { 0x0055005500550055ULL, 0x0055005500550055ULL, },
+ { 0xffccffccffccffccULL, 0xffccffccffccffccULL, },
+ { 0x0033003300330033ULL, 0x0033003300330033ULL, },
+ { 0xff8effe30038ff8eULL, 0xffe30038ff8effe3ULL, },
+ { 0x0071001cffc70071ULL, 0x001cffc70071001cULL, },
+ { 0xffa9ffa9ffa9ffa9ULL, 0xffa9ffa9ffa9ffa9ULL, }, /* 16 */
+ { 0xffaaffaaffaaffaaULL, 0xffaaffaaffaaffaaULL, },
+ { 0xff54ff54ff54ff54ULL, 0xff54ff54ff54ff54ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0xff76ff76ff76ff76ULL, 0xff76ff76ff76ff76ULL, },
+ { 0xffddffddffddffddULL, 0xffddffddffddffddULL, },
+ { 0xff38ff8dffe2ff38ULL, 0xff8dffe2ff38ff8dULL, },
+ { 0x001bffc6ff71001bULL, 0xffc6ff71001bffc6ULL, },
+ { 0x0054005400540054ULL, 0x0054005400540054ULL, }, /* 24 */
+ { 0x0055005500550055ULL, 0x0055005500550055ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0x00aa00aa00aa00aaULL, 0x00aa00aa00aa00aaULL, },
+ { 0x0021002100210021ULL, 0x0021002100210021ULL, },
+ { 0x0088008800880088ULL, 0x0088008800880088ULL, },
+ { 0xffe30038008dffe3ULL, 0x0038008dffe30038ULL, },
+ { 0x00c60071001c00c6ULL, 0x0071001c00c60071ULL, },
+ { 0xffcbffcbffcbffcbULL, 0xffcbffcbffcbffcbULL, }, /* 32 */
+ { 0xffccffccffccffccULL, 0xffccffccffccffccULL, },
+ { 0xff76ff76ff76ff76ULL, 0xff76ff76ff76ff76ULL, },
+ { 0x0021002100210021ULL, 0x0021002100210021ULL, },
+ { 0xff98ff98ff98ff98ULL, 0xff98ff98ff98ff98ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0xff5affaf0004ff5aULL, 0xffaf0004ff5affafULL, },
+ { 0x003dffe8ff93003dULL, 0xffe8ff93003dffe8ULL, },
+ { 0x0032003200320032ULL, 0x0032003200320032ULL, }, /* 40 */
+ { 0x0033003300330033ULL, 0x0033003300330033ULL, },
+ { 0xffddffddffddffddULL, 0xffddffddffddffddULL, },
+ { 0x0088008800880088ULL, 0x0088008800880088ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0x0066006600660066ULL, 0x0066006600660066ULL, },
+ { 0xffc10016006bffc1ULL, 0x0016006bffc10016ULL, },
+ { 0x00a4004ffffa00a4ULL, 0x004ffffa00a4004fULL, },
+ { 0xffe20037ff8dffe2ULL, 0x0037ff8dffe20037ULL, }, /* 48 */
+ { 0xffe30038ff8effe3ULL, 0x0038ff8effe30038ULL, },
+ { 0xff8dffe2ff38ff8dULL, 0xffe2ff38ff8dffe2ULL, },
+ { 0x0038008dffe30038ULL, 0x008dffe30038008dULL, },
+ { 0xffaf0004ff5affafULL, 0x0004ff5affaf0004ULL, },
+ { 0x0016006bffc10016ULL, 0x006bffc10016006bULL, },
+ { 0xff71001bffc6ff71ULL, 0x001bffc6ff71001bULL, },
+ { 0x00540054ff550054ULL, 0x0054ff5500540054ULL, },
+ { 0x001bffc60070001bULL, 0xffc60070001bffc6ULL, }, /* 56 */
+ { 0x001cffc70071001cULL, 0xffc70071001cffc7ULL, },
+ { 0xffc6ff71001bffc6ULL, 0xff71001bffc6ff71ULL, },
+ { 0x0071001c00c60071ULL, 0x001c00c60071001cULL, },
+ { 0xffe8ff93003dffe8ULL, 0xff93003dffe8ff93ULL, },
+ { 0x004ffffa00a4004fULL, 0xfffa00a4004ffffaULL, },
+ { 0xffaaffaa00a9ffaaULL, 0xffaa00a9ffaaffaaULL, },
+ { 0x008dffe30038008dULL, 0xffe30038008dffe3ULL, },
+ { 0xfff2ffb2008a0095ULL, 0x00b200690079ffbcULL, }, /* 64 */
+ { 0xff460049ffbb005dULL, 0x00420025003dffacULL, },
+ { 0xffe2ff90fff7ffd5ULL, 0x0023000a0029ffc4ULL, },
+ { 0xffd70033005900a3ULL, 0x003cffe30040ff50ULL, },
+ { 0x0065ffcc00af0007ULL, 0x007900190090005eULL, },
+ { 0xffb90063ffe0ffcfULL, 0x0009ffd50054004eULL, },
+ { 0x0055ffaa001cff47ULL, 0xffeaffba00400066ULL, },
+ { 0x004a004d007e0015ULL, 0x0003ff930057fff2ULL, },
+ { 0x0016ff7a001bffcbULL, 0x008e002400260031ULL, }, /* 72 */
+ { 0xff6a0011ff4cff93ULL, 0x001effe0ffea0021ULL, },
+ { 0x0006ff58ff88ff0bULL, 0xffffffc5ffd60039ULL, },
+ { 0xfffbfffbffeaffd9ULL, 0x0018ff9effedffc5ULL, },
+ { 0x00daffe200c00022ULL, 0xfff4ffe60024ffeeULL, },
+ { 0x002e0079fff1ffeaULL, 0xff84ffa2ffe8ffdeULL, },
+};
+
+ gettimeofday(&start, NULL);
+
+ for (i = 0; i < PATTERN_INPUTS_SHORT_COUNT; i++) {
+ for (j = 0; j < PATTERN_INPUTS_SHORT_COUNT; j++) {
+ do_msa_HADD_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_HADD_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-add/test_msa_hadd_s_w.c b/tests/tcg/mips/user/ase/msa/int-add/test_msa_hadd_s_w.c
new file mode 100644
index 0000000..7a940b2
--- /dev/null
+++ b/tests/tcg/mips/user/ase/msa/int-add/test_msa_hadd_s_w.c
@@ -0,0 +1,151 @@
+/*
+ * Test program for MSA instruction HADD_S.W
+ *
+ * Copyright (C) 2019 Wave Computing, Inc.
+ * 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.h"
+#include "../../../../include/test_utils.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 = "HADD_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] = {
+ { 0xfffffffefffffffeULL, 0xfffffffefffffffeULL, }, /* 0 */
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0xffffaaa9ffffaaa9ULL, 0xffffaaa9ffffaaa9ULL, },
+ { 0x0000555400005554ULL, 0x0000555400005554ULL, },
+ { 0xffffcccbffffcccbULL, 0xffffcccbffffcccbULL, },
+ { 0x0000333200003332ULL, 0x0000333200003332ULL, },
+ { 0x000038e2ffffe38dULL, 0xffff8e37000038e2ULL, },
+ { 0xffffc71b00001c70ULL, 0x000071c6ffffc71bULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 8 */
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xffffaaaaffffaaaaULL, 0xffffaaaaffffaaaaULL, },
+ { 0x0000555500005555ULL, 0x0000555500005555ULL, },
+ { 0xffffccccffffccccULL, 0xffffccccffffccccULL, },
+ { 0x0000333300003333ULL, 0x0000333300003333ULL, },
+ { 0x000038e3ffffe38eULL, 0xffff8e38000038e3ULL, },
+ { 0xffffc71c00001c71ULL, 0x000071c7ffffc71cULL, },
+ { 0xffffaaa9ffffaaa9ULL, 0xffffaaa9ffffaaa9ULL, }, /* 16 */
+ { 0xffffaaaaffffaaaaULL, 0xffffaaaaffffaaaaULL, },
+ { 0xffff5554ffff5554ULL, 0xffff5554ffff5554ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0xffff7776ffff7776ULL, 0xffff7776ffff7776ULL, },
+ { 0xffffddddffffddddULL, 0xffffddddffffddddULL, },
+ { 0xffffe38dffff8e38ULL, 0xffff38e2ffffe38dULL, },
+ { 0xffff71c6ffffc71bULL, 0x00001c71ffff71c6ULL, },
+ { 0x0000555400005554ULL, 0x0000555400005554ULL, }, /* 24 */
+ { 0x0000555500005555ULL, 0x0000555500005555ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0x0000aaaa0000aaaaULL, 0x0000aaaa0000aaaaULL, },
+ { 0x0000222100002221ULL, 0x0000222100002221ULL, },
+ { 0x0000888800008888ULL, 0x0000888800008888ULL, },
+ { 0x00008e38000038e3ULL, 0xffffe38d00008e38ULL, },
+ { 0x00001c71000071c6ULL, 0x0000c71c00001c71ULL, },
+ { 0xffffcccbffffcccbULL, 0xffffcccbffffcccbULL, }, /* 32 */
+ { 0xffffccccffffccccULL, 0xffffccccffffccccULL, },
+ { 0xffff7776ffff7776ULL, 0xffff7776ffff7776ULL, },
+ { 0x0000222100002221ULL, 0x0000222100002221ULL, },
+ { 0xffff9998ffff9998ULL, 0xffff9998ffff9998ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0x000005afffffb05aULL, 0xffff5b04000005afULL, },
+ { 0xffff93e8ffffe93dULL, 0x00003e93ffff93e8ULL, },
+ { 0x0000333200003332ULL, 0x0000333200003332ULL, }, /* 40 */
+ { 0x0000333300003333ULL, 0x0000333300003333ULL, },
+ { 0xffffddddffffddddULL, 0xffffddddffffddddULL, },
+ { 0x0000888800008888ULL, 0x0000888800008888ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0x0000666600006666ULL, 0x0000666600006666ULL, },
+ { 0x00006c16000016c1ULL, 0xffffc16b00006c16ULL, },
+ { 0xfffffa4f00004fa4ULL, 0x0000a4fafffffa4fULL, },
+ { 0xffffe38dffff8e37ULL, 0x000038e2ffffe38dULL, }, /* 48 */
+ { 0xffffe38effff8e38ULL, 0x000038e3ffffe38eULL, },
+ { 0xffff8e38ffff38e2ULL, 0xffffe38dffff8e38ULL, },
+ { 0x000038e3ffffe38dULL, 0x00008e38000038e3ULL, },
+ { 0xffffb05affff5b04ULL, 0x000005afffffb05aULL, },
+ { 0x000016c1ffffc16bULL, 0x00006c16000016c1ULL, },
+ { 0x00001c71ffff71c6ULL, 0xffffc71b00001c71ULL, },
+ { 0xffffaaaaffffaaa9ULL, 0x0000aaaaffffaaaaULL, },
+ { 0x00001c70000071c6ULL, 0xffffc71b00001c70ULL, }, /* 56 */
+ { 0x00001c71000071c7ULL, 0xffffc71c00001c71ULL, },
+ { 0xffffc71b00001c71ULL, 0xffff71c6ffffc71bULL, },
+ { 0x000071c60000c71cULL, 0x00001c71000071c6ULL, },
+ { 0xffffe93d00003e93ULL, 0xffff93e8ffffe93dULL, },
+ { 0x00004fa40000a4faULL, 0xfffffa4f00004fa4ULL, },
+ { 0x0000555400005555ULL, 0xffff555400005554ULL, },
+ { 0xffffe38d00008e38ULL, 0x000038e3ffffe38dULL, },
+ { 0xffff6f3600007da2ULL, 0x000056c5ffffae87ULL, }, /* 64 */
+ { 0xffff88cdffffef6aULL, 0x0000068100005177ULL, },
+ { 0xffff3714ffffb3e2ULL, 0x000012660000238fULL, },
+ { 0xffff9eb700000ab0ULL, 0xffffd43fffffe11bULL, },
+ { 0xffffe28a0000a2d3ULL, 0x00001e55ffffc54bULL, },
+ { 0xfffffc210000149bULL, 0xffffce110000683bULL, },
+ { 0xffffaa68ffffd913ULL, 0xffffd9f600003a53ULL, },
+ { 0x0000120b00002fe1ULL, 0xffff9bcffffff7dfULL, },
+ { 0xffff932600000f0fULL, 0x00003336ffff5b37ULL, }, /* 72 */
+ { 0xffffacbdffff80d7ULL, 0xffffe2f2fffffe27ULL, },
+ { 0xffff5b04ffff454fULL, 0xffffeed7ffffd03fULL, },
+ { 0xffffc2a7ffff9c1dULL, 0xffffb0b0ffff8dcbULL, },
+ { 0x0000571b0000b371ULL, 0xffff994fffff594eULL, },
+ { 0x000070b200002539ULL, 0xffff490bfffffc3eULL, },
+};
+
+ gettimeofday(&start, NULL);
+
+ for (i = 0; i < PATTERN_INPUTS_SHORT_COUNT; i++) {
+ for (j = 0; j < PATTERN_INPUTS_SHORT_COUNT; j++) {
+ do_msa_HADD_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_HADD_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-add/test_msa_hadd_u_d.c b/tests/tcg/mips/user/ase/msa/int-add/test_msa_hadd_u_d.c
new file mode 100644
index 0000000..d4cbe44
--- /dev/null
+++ b/tests/tcg/mips/user/ase/msa/int-add/test_msa_hadd_u_d.c
@@ -0,0 +1,151 @@
+/*
+ * Test program for MSA instruction HADD_U.D
+ *
+ * Copyright (C) 2019 Wave Computing, Inc.
+ * 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.h"
+#include "../../../../include/test_utils.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 = "HADD_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] = {
+ { 0x00000001fffffffeULL, 0x00000001fffffffeULL, }, /* 0 */
+ { 0x00000000ffffffffULL, 0x00000000ffffffffULL, },
+ { 0x00000001aaaaaaa9ULL, 0x00000001aaaaaaa9ULL, },
+ { 0x0000000155555554ULL, 0x0000000155555554ULL, },
+ { 0x00000001cccccccbULL, 0x00000001cccccccbULL, },
+ { 0x0000000133333332ULL, 0x0000000133333332ULL, },
+ { 0x000000018e38e38dULL, 0x00000001e38e38e2ULL, },
+ { 0x0000000171c71c70ULL, 0x000000011c71c71bULL, },
+ { 0x00000000ffffffffULL, 0x00000000ffffffffULL, }, /* 8 */
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x00000000aaaaaaaaULL, 0x00000000aaaaaaaaULL, },
+ { 0x0000000055555555ULL, 0x0000000055555555ULL, },
+ { 0x00000000ccccccccULL, 0x00000000ccccccccULL, },
+ { 0x0000000033333333ULL, 0x0000000033333333ULL, },
+ { 0x000000008e38e38eULL, 0x00000000e38e38e3ULL, },
+ { 0x0000000071c71c71ULL, 0x000000001c71c71cULL, },
+ { 0x00000001aaaaaaa9ULL, 0x00000001aaaaaaa9ULL, }, /* 16 */
+ { 0x00000000aaaaaaaaULL, 0x00000000aaaaaaaaULL, },
+ { 0x0000000155555554ULL, 0x0000000155555554ULL, },
+ { 0x00000000ffffffffULL, 0x00000000ffffffffULL, },
+ { 0x0000000177777776ULL, 0x0000000177777776ULL, },
+ { 0x00000000ddddddddULL, 0x00000000ddddddddULL, },
+ { 0x0000000138e38e38ULL, 0x000000018e38e38dULL, },
+ { 0x000000011c71c71bULL, 0x00000000c71c71c6ULL, },
+ { 0x0000000155555554ULL, 0x0000000155555554ULL, }, /* 24 */
+ { 0x0000000055555555ULL, 0x0000000055555555ULL, },
+ { 0x00000000ffffffffULL, 0x00000000ffffffffULL, },
+ { 0x00000000aaaaaaaaULL, 0x00000000aaaaaaaaULL, },
+ { 0x0000000122222221ULL, 0x0000000122222221ULL, },
+ { 0x0000000088888888ULL, 0x0000000088888888ULL, },
+ { 0x00000000e38e38e3ULL, 0x0000000138e38e38ULL, },
+ { 0x00000000c71c71c6ULL, 0x0000000071c71c71ULL, },
+ { 0x00000001cccccccbULL, 0x00000001cccccccbULL, }, /* 32 */
+ { 0x00000000ccccccccULL, 0x00000000ccccccccULL, },
+ { 0x0000000177777776ULL, 0x0000000177777776ULL, },
+ { 0x0000000122222221ULL, 0x0000000122222221ULL, },
+ { 0x0000000199999998ULL, 0x0000000199999998ULL, },
+ { 0x00000000ffffffffULL, 0x00000000ffffffffULL, },
+ { 0x000000015b05b05aULL, 0x00000001b05b05afULL, },
+ { 0x000000013e93e93dULL, 0x00000000e93e93e8ULL, },
+ { 0x0000000133333332ULL, 0x0000000133333332ULL, }, /* 40 */
+ { 0x0000000033333333ULL, 0x0000000033333333ULL, },
+ { 0x00000000ddddddddULL, 0x00000000ddddddddULL, },
+ { 0x0000000088888888ULL, 0x0000000088888888ULL, },
+ { 0x00000000ffffffffULL, 0x00000000ffffffffULL, },
+ { 0x0000000066666666ULL, 0x0000000066666666ULL, },
+ { 0x00000000c16c16c1ULL, 0x0000000116c16c16ULL, },
+ { 0x00000000a4fa4fa4ULL, 0x000000004fa4fa4fULL, },
+ { 0x00000001e38e38e2ULL, 0x0000000138e38e37ULL, }, /* 48 */
+ { 0x00000000e38e38e3ULL, 0x0000000038e38e38ULL, },
+ { 0x000000018e38e38dULL, 0x00000000e38e38e2ULL, },
+ { 0x0000000138e38e38ULL, 0x000000008e38e38dULL, },
+ { 0x00000001b05b05afULL, 0x0000000105b05b04ULL, },
+ { 0x0000000116c16c16ULL, 0x000000006c16c16bULL, },
+ { 0x0000000171c71c71ULL, 0x000000011c71c71bULL, },
+ { 0x0000000155555554ULL, 0x0000000055555554ULL, },
+ { 0x000000011c71c71bULL, 0x00000001c71c71c6ULL, }, /* 56 */
+ { 0x000000001c71c71cULL, 0x00000000c71c71c7ULL, },
+ { 0x00000000c71c71c6ULL, 0x0000000171c71c71ULL, },
+ { 0x0000000071c71c71ULL, 0x000000011c71c71cULL, },
+ { 0x00000000e93e93e8ULL, 0x0000000193e93e93ULL, },
+ { 0x000000004fa4fa4fULL, 0x00000000fa4fa4faULL, },
+ { 0x00000000aaaaaaaaULL, 0x00000001aaaaaaaaULL, },
+ { 0x000000008e38e38dULL, 0x00000000e38e38e3ULL, },
+ { 0x00000000b0cd3c0cULL, 0x0000000149e2bb6aULL, }, /* 64 */
+ { 0x00000000d5feadd4ULL, 0x0000000060a65e5aULL, },
+ { 0x00000001423a724cULL, 0x00000000f6923072ULL, },
+ { 0x00000000e69cc91aULL, 0x00000000f4a9edfeULL, },
+ { 0x00000001242055a3ULL, 0x0000000111736b26ULL, },
+ { 0x000000014951c76bULL, 0x0000000028370e16ULL, },
+ { 0x00000001b58d8be3ULL, 0x00000000be22e02eULL, },
+ { 0x0000000159efe2b1ULL, 0x00000000bc3a9dbaULL, },
+ { 0x00000000d4bd03eaULL, 0x000000012654770bULL, }, /* 72 */
+ { 0x00000000f9ee75b2ULL, 0x000000003d1819fbULL, },
+ { 0x00000001662a3a2aULL, 0x00000000d303ec13ULL, },
+ { 0x000000010a8c90f8ULL, 0x00000000d11ba99fULL, },
+ { 0x0000000098b16b8dULL, 0x000000018c6d38e4ULL, },
+ { 0x00000000bde2dd55ULL, 0x00000000a330dbd4ULL, },
+};
+
+ gettimeofday(&start, NULL);
+
+ for (i = 0; i < PATTERN_INPUTS_SHORT_COUNT; i++) {
+ for (j = 0; j < PATTERN_INPUTS_SHORT_COUNT; j++) {
+ do_msa_HADD_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_HADD_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-add/test_msa_hadd_u_h.c b/tests/tcg/mips/user/ase/msa/int-add/test_msa_hadd_u_h.c
new file mode 100644
index 0000000..ca25057
--- /dev/null
+++ b/tests/tcg/mips/user/ase/msa/int-add/test_msa_hadd_u_h.c
@@ -0,0 +1,151 @@
+/*
+ * Test program for MSA instruction HADD_U.H
+ *
+ * Copyright (C) 2019 Wave Computing, Inc.
+ * 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.h"
+#include "../../../../include/test_utils.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 = "HADD_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] = {
+ { 0x01fe01fe01fe01feULL, 0x01fe01fe01fe01feULL, }, /* 0 */
+ { 0x00ff00ff00ff00ffULL, 0x00ff00ff00ff00ffULL, },
+ { 0x01a901a901a901a9ULL, 0x01a901a901a901a9ULL, },
+ { 0x0154015401540154ULL, 0x0154015401540154ULL, },
+ { 0x01cb01cb01cb01cbULL, 0x01cb01cb01cb01cbULL, },
+ { 0x0132013201320132ULL, 0x0132013201320132ULL, },
+ { 0x018d01e20137018dULL, 0x01e20137018d01e2ULL, },
+ { 0x0170011b01c60170ULL, 0x011b01c60170011bULL, },
+ { 0x00ff00ff00ff00ffULL, 0x00ff00ff00ff00ffULL, }, /* 8 */
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x00aa00aa00aa00aaULL, 0x00aa00aa00aa00aaULL, },
+ { 0x0055005500550055ULL, 0x0055005500550055ULL, },
+ { 0x00cc00cc00cc00ccULL, 0x00cc00cc00cc00ccULL, },
+ { 0x0033003300330033ULL, 0x0033003300330033ULL, },
+ { 0x008e00e30038008eULL, 0x00e30038008e00e3ULL, },
+ { 0x0071001c00c70071ULL, 0x001c00c70071001cULL, },
+ { 0x01a901a901a901a9ULL, 0x01a901a901a901a9ULL, }, /* 16 */
+ { 0x00aa00aa00aa00aaULL, 0x00aa00aa00aa00aaULL, },
+ { 0x0154015401540154ULL, 0x0154015401540154ULL, },
+ { 0x00ff00ff00ff00ffULL, 0x00ff00ff00ff00ffULL, },
+ { 0x0176017601760176ULL, 0x0176017601760176ULL, },
+ { 0x00dd00dd00dd00ddULL, 0x00dd00dd00dd00ddULL, },
+ { 0x0138018d00e20138ULL, 0x018d00e20138018dULL, },
+ { 0x011b00c60171011bULL, 0x00c60171011b00c6ULL, },
+ { 0x0154015401540154ULL, 0x0154015401540154ULL, }, /* 24 */
+ { 0x0055005500550055ULL, 0x0055005500550055ULL, },
+ { 0x00ff00ff00ff00ffULL, 0x00ff00ff00ff00ffULL, },
+ { 0x00aa00aa00aa00aaULL, 0x00aa00aa00aa00aaULL, },
+ { 0x0121012101210121ULL, 0x0121012101210121ULL, },
+ { 0x0088008800880088ULL, 0x0088008800880088ULL, },
+ { 0x00e30138008d00e3ULL, 0x0138008d00e30138ULL, },
+ { 0x00c60071011c00c6ULL, 0x0071011c00c60071ULL, },
+ { 0x01cb01cb01cb01cbULL, 0x01cb01cb01cb01cbULL, }, /* 32 */
+ { 0x00cc00cc00cc00ccULL, 0x00cc00cc00cc00ccULL, },
+ { 0x0176017601760176ULL, 0x0176017601760176ULL, },
+ { 0x0121012101210121ULL, 0x0121012101210121ULL, },
+ { 0x0198019801980198ULL, 0x0198019801980198ULL, },
+ { 0x00ff00ff00ff00ffULL, 0x00ff00ff00ff00ffULL, },
+ { 0x015a01af0104015aULL, 0x01af0104015a01afULL, },
+ { 0x013d00e80193013dULL, 0x00e80193013d00e8ULL, },
+ { 0x0132013201320132ULL, 0x0132013201320132ULL, }, /* 40 */
+ { 0x0033003300330033ULL, 0x0033003300330033ULL, },
+ { 0x00dd00dd00dd00ddULL, 0x00dd00dd00dd00ddULL, },
+ { 0x0088008800880088ULL, 0x0088008800880088ULL, },
+ { 0x00ff00ff00ff00ffULL, 0x00ff00ff00ff00ffULL, },
+ { 0x0066006600660066ULL, 0x0066006600660066ULL, },
+ { 0x00c10116006b00c1ULL, 0x0116006b00c10116ULL, },
+ { 0x00a4004f00fa00a4ULL, 0x004f00fa00a4004fULL, },
+ { 0x01e20137018d01e2ULL, 0x0137018d01e20137ULL, }, /* 48 */
+ { 0x00e30038008e00e3ULL, 0x0038008e00e30038ULL, },
+ { 0x018d00e20138018dULL, 0x00e20138018d00e2ULL, },
+ { 0x0138008d00e30138ULL, 0x008d00e30138008dULL, },
+ { 0x01af0104015a01afULL, 0x0104015a01af0104ULL, },
+ { 0x0116006b00c10116ULL, 0x006b00c10116006bULL, },
+ { 0x0171011b00c60171ULL, 0x011b00c60171011bULL, },
+ { 0x0154005401550154ULL, 0x0054015501540054ULL, },
+ { 0x011b01c60170011bULL, 0x01c60170011b01c6ULL, }, /* 56 */
+ { 0x001c00c70071001cULL, 0x00c70071001c00c7ULL, },
+ { 0x00c60171011b00c6ULL, 0x0171011b00c60171ULL, },
+ { 0x0071011c00c60071ULL, 0x011c00c60071011cULL, },
+ { 0x00e80193013d00e8ULL, 0x0193013d00e80193ULL, },
+ { 0x004f00fa00a4004fULL, 0x00fa00a4004f00faULL, },
+ { 0x00aa01aa00a900aaULL, 0x01aa00a900aa01aaULL, },
+ { 0x008d00e30138008dULL, 0x00e30138008d00e3ULL, },
+ { 0x00f201b2008a0095ULL, 0x00b20069017900bcULL, }, /* 64 */
+ { 0x0146014900bb005dULL, 0x01420025013d01acULL, },
+ { 0x00e2019000f700d5ULL, 0x0123010a012900c4ULL, },
+ { 0x00d70133005900a3ULL, 0x013c00e301400150ULL, },
+ { 0x016500cc00af0107ULL, 0x007901190090005eULL, },
+ { 0x01b9006300e000cfULL, 0x010900d50054014eULL, },
+ { 0x015500aa011c0147ULL, 0x00ea01ba00400066ULL, },
+ { 0x014a004d007e0115ULL, 0x01030193005700f2ULL, },
+ { 0x0116017a011b00cbULL, 0x008e012401260031ULL, }, /* 72 */
+ { 0x016a0111014c0093ULL, 0x011e00e000ea0121ULL, },
+ { 0x010601580188010bULL, 0x00ff01c500d60039ULL, },
+ { 0x00fb00fb00ea00d9ULL, 0x0118019e00ed00c5ULL, },
+ { 0x00da00e200c00122ULL, 0x00f400e6012400eeULL, },
+ { 0x012e007900f100eaULL, 0x018400a200e801deULL, },
+};
+
+ gettimeofday(&start, NULL);
+
+ for (i = 0; i < PATTERN_INPUTS_SHORT_COUNT; i++) {
+ for (j = 0; j < PATTERN_INPUTS_SHORT_COUNT; j++) {
+ do_msa_HADD_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_HADD_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-add/test_msa_hadd_u_w.c b/tests/tcg/mips/user/ase/msa/int-add/test_msa_hadd_u_w.c
new file mode 100644
index 0000000..b302727
--- /dev/null
+++ b/tests/tcg/mips/user/ase/msa/int-add/test_msa_hadd_u_w.c
@@ -0,0 +1,151 @@
+/*
+ * Test program for MSA instruction HADD_U.W
+ *
+ * Copyright (C) 2019 Wave Computing, Inc.
+ * 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.h"
+#include "../../../../include/test_utils.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 = "HADD_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] = {
+ { 0x0001fffe0001fffeULL, 0x0001fffe0001fffeULL, }, /* 0 */
+ { 0x0000ffff0000ffffULL, 0x0000ffff0000ffffULL, },
+ { 0x0001aaa90001aaa9ULL, 0x0001aaa90001aaa9ULL, },
+ { 0x0001555400015554ULL, 0x0001555400015554ULL, },
+ { 0x0001cccb0001cccbULL, 0x0001cccb0001cccbULL, },
+ { 0x0001333200013332ULL, 0x0001333200013332ULL, },
+ { 0x000138e20001e38dULL, 0x00018e37000138e2ULL, },
+ { 0x0001c71b00011c70ULL, 0x000171c60001c71bULL, },
+ { 0x0000ffff0000ffffULL, 0x0000ffff0000ffffULL, }, /* 8 */
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000aaaa0000aaaaULL, 0x0000aaaa0000aaaaULL, },
+ { 0x0000555500005555ULL, 0x0000555500005555ULL, },
+ { 0x0000cccc0000ccccULL, 0x0000cccc0000ccccULL, },
+ { 0x0000333300003333ULL, 0x0000333300003333ULL, },
+ { 0x000038e30000e38eULL, 0x00008e38000038e3ULL, },
+ { 0x0000c71c00001c71ULL, 0x000071c70000c71cULL, },
+ { 0x0001aaa90001aaa9ULL, 0x0001aaa90001aaa9ULL, }, /* 16 */
+ { 0x0000aaaa0000aaaaULL, 0x0000aaaa0000aaaaULL, },
+ { 0x0001555400015554ULL, 0x0001555400015554ULL, },
+ { 0x0000ffff0000ffffULL, 0x0000ffff0000ffffULL, },
+ { 0x0001777600017776ULL, 0x0001777600017776ULL, },
+ { 0x0000dddd0000ddddULL, 0x0000dddd0000ddddULL, },
+ { 0x0000e38d00018e38ULL, 0x000138e20000e38dULL, },
+ { 0x000171c60000c71bULL, 0x00011c71000171c6ULL, },
+ { 0x0001555400015554ULL, 0x0001555400015554ULL, }, /* 24 */
+ { 0x0000555500005555ULL, 0x0000555500005555ULL, },
+ { 0x0000ffff0000ffffULL, 0x0000ffff0000ffffULL, },
+ { 0x0000aaaa0000aaaaULL, 0x0000aaaa0000aaaaULL, },
+ { 0x0001222100012221ULL, 0x0001222100012221ULL, },
+ { 0x0000888800008888ULL, 0x0000888800008888ULL, },
+ { 0x00008e38000138e3ULL, 0x0000e38d00008e38ULL, },
+ { 0x00011c71000071c6ULL, 0x0000c71c00011c71ULL, },
+ { 0x0001cccb0001cccbULL, 0x0001cccb0001cccbULL, }, /* 32 */
+ { 0x0000cccc0000ccccULL, 0x0000cccc0000ccccULL, },
+ { 0x0001777600017776ULL, 0x0001777600017776ULL, },
+ { 0x0001222100012221ULL, 0x0001222100012221ULL, },
+ { 0x0001999800019998ULL, 0x0001999800019998ULL, },
+ { 0x0000ffff0000ffffULL, 0x0000ffff0000ffffULL, },
+ { 0x000105af0001b05aULL, 0x00015b04000105afULL, },
+ { 0x000193e80000e93dULL, 0x00013e93000193e8ULL, },
+ { 0x0001333200013332ULL, 0x0001333200013332ULL, }, /* 40 */
+ { 0x0000333300003333ULL, 0x0000333300003333ULL, },
+ { 0x0000dddd0000ddddULL, 0x0000dddd0000ddddULL, },
+ { 0x0000888800008888ULL, 0x0000888800008888ULL, },
+ { 0x0000ffff0000ffffULL, 0x0000ffff0000ffffULL, },
+ { 0x0000666600006666ULL, 0x0000666600006666ULL, },
+ { 0x00006c16000116c1ULL, 0x0000c16b00006c16ULL, },
+ { 0x0000fa4f00004fa4ULL, 0x0000a4fa0000fa4fULL, },
+ { 0x0001e38d00018e37ULL, 0x000138e20001e38dULL, }, /* 48 */
+ { 0x0000e38e00008e38ULL, 0x000038e30000e38eULL, },
+ { 0x00018e38000138e2ULL, 0x0000e38d00018e38ULL, },
+ { 0x000138e30000e38dULL, 0x00008e38000138e3ULL, },
+ { 0x0001b05a00015b04ULL, 0x000105af0001b05aULL, },
+ { 0x000116c10000c16bULL, 0x00006c16000116c1ULL, },
+ { 0x00011c71000171c6ULL, 0x0000c71b00011c71ULL, },
+ { 0x0001aaaa0000aaa9ULL, 0x0000aaaa0001aaaaULL, },
+ { 0x00011c70000171c6ULL, 0x0001c71b00011c70ULL, }, /* 56 */
+ { 0x00001c71000071c7ULL, 0x0000c71c00001c71ULL, },
+ { 0x0000c71b00011c71ULL, 0x000171c60000c71bULL, },
+ { 0x000071c60000c71cULL, 0x00011c71000071c6ULL, },
+ { 0x0000e93d00013e93ULL, 0x000193e80000e93dULL, },
+ { 0x00004fa40000a4faULL, 0x0000fa4f00004fa4ULL, },
+ { 0x0000555400015555ULL, 0x0001555400005554ULL, },
+ { 0x0000e38d00008e38ULL, 0x000138e30000e38dULL, },
+ { 0x00016f3600007da2ULL, 0x000056c50001ae87ULL, }, /* 64 */
+ { 0x000088cd0000ef6aULL, 0x0001068100015177ULL, },
+ { 0x000137140000b3e2ULL, 0x000112660001238fULL, },
+ { 0x00009eb700010ab0ULL, 0x0000d43f0001e11bULL, },
+ { 0x0001e28a0000a2d3ULL, 0x00001e550000c54bULL, },
+ { 0x0000fc210001149bULL, 0x0000ce110000683bULL, },
+ { 0x0001aa680000d913ULL, 0x0000d9f600003a53ULL, },
+ { 0x0001120b00012fe1ULL, 0x00009bcf0000f7dfULL, },
+ { 0x0001932600010f0fULL, 0x0000333600015b37ULL, }, /* 72 */
+ { 0x0000acbd000180d7ULL, 0x0000e2f20000fe27ULL, },
+ { 0x00015b040001454fULL, 0x0000eed70000d03fULL, },
+ { 0x0000c2a700019c1dULL, 0x0000b0b000018dcbULL, },
+ { 0x0001571b0000b371ULL, 0x0000994f0001594eULL, },
+ { 0x000070b200012539ULL, 0x0001490b0000fc3eULL, },
+};
+
+ gettimeofday(&start, NULL);
+
+ for (i = 0; i < PATTERN_INPUTS_SHORT_COUNT; i++) {
+ for (j = 0; j < PATTERN_INPUTS_SHORT_COUNT; j++) {
+ do_msa_HADD_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_HADD_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-compare/test_msa_ceq_b.c b/tests/tcg/mips/user/ase/msa/int-compare/test_msa_ceq_b.c
new file mode 100644
index 0000000..b47b42e
--- /dev/null
+++ b/tests/tcg/mips/user/ase/msa/int-compare/test_msa_ceq_b.c
@@ -0,0 +1,153 @@
+/*
+ * Test program for MSA instruction CEQ.B
+ *
+ * Copyright (C) 2018 Wave Computing, Inc.
+ * Copyright (C) 2018 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.h"
+#include "../../../../include/test_utils.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 = "CEQ.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 */
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, }, /* 8 */
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, }, /* 16 */
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, }, /* 24 */
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, }, /* 32 */
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, }, /* 40 */
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, }, /* 48 */
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, }, /* 56 */
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 64 */
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, }, /* 72 */
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ };
+
+ gettimeofday(&start, NULL);
+
+ for (i = 0; i < PATTERN_INPUTS_SHORT_COUNT; i++) {
+ for (j = 0; j < PATTERN_INPUTS_SHORT_COUNT; j++) {
+ do_msa_CEQ_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_CEQ_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-compare/test_msa_ceq_d.c b/tests/tcg/mips/user/ase/msa/int-compare/test_msa_ceq_d.c
new file mode 100644
index 0000000..e169bdc
--- /dev/null
+++ b/tests/tcg/mips/user/ase/msa/int-compare/test_msa_ceq_d.c
@@ -0,0 +1,153 @@
+/*
+ * Test program for MSA instruction CEQ.D
+ *
+ * Copyright (C) 2018 Wave Computing, Inc.
+ * Copyright (C) 2018 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.h"
+#include "../../../../include/test_utils.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 = "CEQ.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, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, }, /* 8 */
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, }, /* 16 */
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, }, /* 24 */
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, }, /* 32 */
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, }, /* 40 */
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, }, /* 48 */
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, }, /* 56 */
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 64 */
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, }, /* 72 */
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ };
+
+ gettimeofday(&start, NULL);
+
+ for (i = 0; i < PATTERN_INPUTS_SHORT_COUNT; i++) {
+ for (j = 0; j < PATTERN_INPUTS_SHORT_COUNT; j++) {
+ do_msa_CEQ_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_CEQ_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-compare/test_msa_ceq_h.c b/tests/tcg/mips/user/ase/msa/int-compare/test_msa_ceq_h.c
new file mode 100644
index 0000000..9f03cb0
--- /dev/null
+++ b/tests/tcg/mips/user/ase/msa/int-compare/test_msa_ceq_h.c
@@ -0,0 +1,153 @@
+/*
+ * Test program for MSA instruction CEQ.H
+ *
+ * Copyright (C) 2018 Wave Computing, Inc.
+ * Copyright (C) 2018 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.h"
+#include "../../../../include/test_utils.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 = "CEQ.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 */
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, }, /* 8 */
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, }, /* 16 */
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, }, /* 24 */
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, }, /* 32 */
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, }, /* 40 */
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, }, /* 48 */
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, }, /* 56 */
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 64 */
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, }, /* 72 */
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ };
+
+ gettimeofday(&start, NULL);
+
+ for (i = 0; i < PATTERN_INPUTS_SHORT_COUNT; i++) {
+ for (j = 0; j < PATTERN_INPUTS_SHORT_COUNT; j++) {
+ do_msa_CEQ_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_CEQ_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-compare/test_msa_ceq_w.c b/tests/tcg/mips/user/ase/msa/int-compare/test_msa_ceq_w.c
new file mode 100644
index 0000000..a927d96
--- /dev/null
+++ b/tests/tcg/mips/user/ase/msa/int-compare/test_msa_ceq_w.c
@@ -0,0 +1,153 @@
+/*
+ * Test program for MSA instruction CEQ.W
+ *
+ * Copyright (C) 2018 Wave Computing, Inc.
+ * Copyright (C) 2018 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.h"
+#include "../../../../include/test_utils.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 = "CEQ.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, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, }, /* 8 */
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, }, /* 16 */
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, }, /* 24 */
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, }, /* 32 */
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, }, /* 40 */
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, }, /* 48 */
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, }, /* 56 */
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 64 */
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, }, /* 72 */
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ };
+
+ gettimeofday(&start, NULL);
+
+ for (i = 0; i < PATTERN_INPUTS_SHORT_COUNT; i++) {
+ for (j = 0; j < PATTERN_INPUTS_SHORT_COUNT; j++) {
+ do_msa_CEQ_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_CEQ_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-compare/test_msa_cle_s_b.c b/tests/tcg/mips/user/ase/msa/int-compare/test_msa_cle_s_b.c
new file mode 100644
index 0000000..1c1cb3b
--- /dev/null
+++ b/tests/tcg/mips/user/ase/msa/int-compare/test_msa_cle_s_b.c
@@ -0,0 +1,153 @@
+/*
+ * Test program for MSA instruction CLE_S.B
+ *
+ * Copyright (C) 2018 Wave Computing, Inc.
+ * Copyright (C) 2018 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.h"
+#include "../../../../include/test_utils.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 = "CLE_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] = {
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 0 */
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0x0000ff0000ff0000ULL, 0xff0000ff0000ff00ULL, },
+ { 0xffff00ffff00ffffULL, 0x00ffff00ffff00ffULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, }, /* 8 */
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0x0000ff0000ff0000ULL, 0xff0000ff0000ff00ULL, },
+ { 0xffff00ffff00ffffULL, 0x00ffff00ffff00ffULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 16 */
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0xff00ffff00ffff00ULL, 0xffff00ffff00ffffULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, }, /* 24 */
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x00ff0000ff0000ffULL, 0x0000ff0000ff0000ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 32 */
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0xff00ffff00ffff00ULL, 0xffff00ffff00ffffULL, },
+ { 0xffff00ffff00ffffULL, 0x00ffff00ffff00ffULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, }, /* 40 */
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0x0000ff0000ff0000ULL, 0xff0000ff0000ff00ULL, },
+ { 0x00ff0000ff0000ffULL, 0x0000ff0000ff0000ULL, },
+ { 0xffff00ffff00ffffULL, 0x00ffff00ffff00ffULL, }, /* 48 */
+ { 0xffff00ffff00ffffULL, 0x00ffff00ffff00ffULL, },
+ { 0x00ff0000ff0000ffULL, 0x0000ff0000ff0000ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0x00ff0000ff0000ffULL, 0x0000ff0000ff0000ULL, },
+ { 0xffff00ffff00ffffULL, 0x00ffff00ffff00ffULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0xffff00ffff00ffffULL, 0x00ffff00ffff00ffULL, },
+ { 0x0000ff0000ff0000ULL, 0xff0000ff0000ff00ULL, }, /* 56 */
+ { 0x0000ff0000ff0000ULL, 0xff0000ff0000ff00ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xff00ffff00ffff00ULL, 0xffff00ffff00ffffULL, },
+ { 0x0000ff0000ff0000ULL, 0xff0000ff0000ff00ULL, },
+ { 0xff00ffff00ffff00ULL, 0xffff00ffff00ffffULL, },
+ { 0x0000ff0000ff0000ULL, 0xff0000ff0000ff00ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 64 */
+ { 0xff00ffffff000000ULL, 0x00000000ff00ff00ULL, },
+ { 0xff00000000000000ULL, 0x000000000000ffffULL, },
+ { 0xff00ffffff0000ffULL, 0x000000000000ff00ULL, },
+ { 0x00ff000000ffffffULL, 0xffffffff00ff00ffULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0x00ff000000ff0000ULL, 0xff00ff00000000ffULL, },
+ { 0xffffff00ffffffffULL, 0x0000000000ff0000ULL, },
+ { 0x00ffffffffffffffULL, 0xffffffffffff0000ULL, }, /* 72 */
+ { 0xff00ffffff00ffffULL, 0x00ff00ffffffff00ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0xff00ffffffffffffULL, 0x00ff000000ff0000ULL, },
+ { 0x00ff000000ffff00ULL, 0xffffffffffff00ffULL, },
+ { 0x000000ff00000000ULL, 0xffffffffff00ffffULL, },
+ { 0x00ff000000000000ULL, 0xff00ffffff00ffffULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ };
+
+ gettimeofday(&start, NULL);
+
+ for (i = 0; i < PATTERN_INPUTS_SHORT_COUNT; i++) {
+ for (j = 0; j < PATTERN_INPUTS_SHORT_COUNT; j++) {
+ do_msa_CLE_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_CLE_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-compare/test_msa_cle_s_d.c b/tests/tcg/mips/user/ase/msa/int-compare/test_msa_cle_s_d.c
new file mode 100644
index 0000000..b51907c
--- /dev/null
+++ b/tests/tcg/mips/user/ase/msa/int-compare/test_msa_cle_s_d.c
@@ -0,0 +1,153 @@
+/*
+ * Test program for MSA instruction CLE_S.D
+ *
+ * Copyright (C) 2018 Wave Computing, Inc.
+ * Copyright (C) 2018 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.h"
+#include "../../../../include/test_utils.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 = "CLE_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] = {
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 0 */
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0x0000000000000000ULL, 0xffffffffffffffffULL, },
+ { 0xffffffffffffffffULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, }, /* 8 */
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0x0000000000000000ULL, 0xffffffffffffffffULL, },
+ { 0xffffffffffffffffULL, 0x0000000000000000ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 16 */
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, }, /* 24 */
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 32 */
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0xffffffffffffffffULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, }, /* 40 */
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0x0000000000000000ULL, 0xffffffffffffffffULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xffffffffffffffffULL, 0x0000000000000000ULL, }, /* 48 */
+ { 0xffffffffffffffffULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xffffffffffffffffULL, 0x0000000000000000ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0xffffffffffffffffULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0xffffffffffffffffULL, }, /* 56 */
+ { 0x0000000000000000ULL, 0xffffffffffffffffULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0x0000000000000000ULL, 0xffffffffffffffffULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0x0000000000000000ULL, 0xffffffffffffffffULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 64 */
+ { 0xffffffffffffffffULL, 0x0000000000000000ULL, },
+ { 0xffffffffffffffffULL, 0x0000000000000000ULL, },
+ { 0xffffffffffffffffULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0xffffffffffffffffULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0x0000000000000000ULL, 0xffffffffffffffffULL, },
+ { 0xffffffffffffffffULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0xffffffffffffffffULL, }, /* 72 */
+ { 0xffffffffffffffffULL, 0x0000000000000000ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0xffffffffffffffffULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0xffffffffffffffffULL, },
+ { 0x0000000000000000ULL, 0xffffffffffffffffULL, },
+ { 0x0000000000000000ULL, 0xffffffffffffffffULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ };
+
+ gettimeofday(&start, NULL);
+
+ for (i = 0; i < PATTERN_INPUTS_SHORT_COUNT; i++) {
+ for (j = 0; j < PATTERN_INPUTS_SHORT_COUNT; j++) {
+ do_msa_CLE_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_CLE_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-compare/test_msa_cle_s_h.c b/tests/tcg/mips/user/ase/msa/int-compare/test_msa_cle_s_h.c
new file mode 100644
index 0000000..20ebbfb
--- /dev/null
+++ b/tests/tcg/mips/user/ase/msa/int-compare/test_msa_cle_s_h.c
@@ -0,0 +1,153 @@
+/*
+ * Test program for MSA instruction CLE_S.H
+ *
+ * Copyright (C) 2018 Wave Computing, Inc.
+ * Copyright (C) 2018 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.h"
+#include "../../../../include/test_utils.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 = "CLE_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] = {
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 0 */
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0x0000ffff00000000ULL, 0xffff00000000ffffULL, },
+ { 0xffff0000ffffffffULL, 0x0000ffffffff0000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, }, /* 8 */
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0x0000ffff00000000ULL, 0xffff00000000ffffULL, },
+ { 0xffff0000ffffffffULL, 0x0000ffffffff0000ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 16 */
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0xffffffff0000ffffULL, 0xffff0000ffffffffULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, }, /* 24 */
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x00000000ffff0000ULL, 0x0000ffff00000000ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 32 */
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0xffffffff0000ffffULL, 0xffff0000ffffffffULL, },
+ { 0xffff0000ffffffffULL, 0x0000ffffffff0000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, }, /* 40 */
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0x0000ffff00000000ULL, 0xffff00000000ffffULL, },
+ { 0x00000000ffff0000ULL, 0x0000ffff00000000ULL, },
+ { 0xffff0000ffffffffULL, 0x0000ffffffff0000ULL, }, /* 48 */
+ { 0xffff0000ffffffffULL, 0x0000ffffffff0000ULL, },
+ { 0x00000000ffff0000ULL, 0x0000ffff00000000ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0x00000000ffff0000ULL, 0x0000ffff00000000ULL, },
+ { 0xffff0000ffffffffULL, 0x0000ffffffff0000ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0xffff0000ffffffffULL, 0x0000ffffffff0000ULL, },
+ { 0x0000ffff00000000ULL, 0xffff00000000ffffULL, }, /* 56 */
+ { 0x0000ffff00000000ULL, 0xffff00000000ffffULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xffffffff0000ffffULL, 0xffff0000ffffffffULL, },
+ { 0x0000ffff00000000ULL, 0xffff00000000ffffULL, },
+ { 0xffffffff0000ffffULL, 0xffff0000ffffffffULL, },
+ { 0x0000ffff00000000ULL, 0xffff00000000ffffULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 64 */
+ { 0xffffffffffff0000ULL, 0x00000000ffffffffULL, },
+ { 0xffff000000000000ULL, 0x000000000000ffffULL, },
+ { 0xffffffffffff0000ULL, 0x000000000000ffffULL, },
+ { 0x000000000000ffffULL, 0xffffffff00000000ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0x0000000000000000ULL, 0xffffffff00000000ULL, },
+ { 0xffffffffffffffffULL, 0x0000000000000000ULL, },
+ { 0x0000ffffffffffffULL, 0xffffffffffff0000ULL, }, /* 72 */
+ { 0xffffffffffffffffULL, 0x00000000ffffffffULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0xffffffffffffffffULL, 0x0000000000000000ULL, },
+ { 0x000000000000ffffULL, 0xffffffffffff0000ULL, },
+ { 0x0000000000000000ULL, 0xffffffffffffffffULL, },
+ { 0x0000000000000000ULL, 0xffffffffffffffffULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ };
+
+ gettimeofday(&start, NULL);
+
+ for (i = 0; i < PATTERN_INPUTS_SHORT_COUNT; i++) {
+ for (j = 0; j < PATTERN_INPUTS_SHORT_COUNT; j++) {
+ do_msa_CLE_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_CLE_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-compare/test_msa_cle_s_w.c b/tests/tcg/mips/user/ase/msa/int-compare/test_msa_cle_s_w.c
new file mode 100644
index 0000000..4a78cce
--- /dev/null
+++ b/tests/tcg/mips/user/ase/msa/int-compare/test_msa_cle_s_w.c
@@ -0,0 +1,153 @@
+/*
+ * Test program for MSA instruction CLE_S.W
+ *
+ * Copyright (C) 2018 Wave Computing, Inc.
+ * Copyright (C) 2018 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.h"
+#include "../../../../include/test_utils.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 = "CLE_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] = {
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 0 */
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0x0000000000000000ULL, 0xffffffff00000000ULL, },
+ { 0xffffffffffffffffULL, 0x00000000ffffffffULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, }, /* 8 */
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0x0000000000000000ULL, 0xffffffff00000000ULL, },
+ { 0xffffffffffffffffULL, 0x00000000ffffffffULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 16 */
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0xffffffff00000000ULL, 0xffffffffffffffffULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, }, /* 24 */
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x00000000ffffffffULL, 0x0000000000000000ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 32 */
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0xffffffff00000000ULL, 0xffffffffffffffffULL, },
+ { 0xffffffffffffffffULL, 0x00000000ffffffffULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, }, /* 40 */
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0x0000000000000000ULL, 0xffffffff00000000ULL, },
+ { 0x00000000ffffffffULL, 0x0000000000000000ULL, },
+ { 0xffffffffffffffffULL, 0x00000000ffffffffULL, }, /* 48 */
+ { 0xffffffffffffffffULL, 0x00000000ffffffffULL, },
+ { 0x00000000ffffffffULL, 0x0000000000000000ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0x00000000ffffffffULL, 0x0000000000000000ULL, },
+ { 0xffffffffffffffffULL, 0x00000000ffffffffULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0xffffffffffffffffULL, 0x00000000ffffffffULL, },
+ { 0x0000000000000000ULL, 0xffffffff00000000ULL, }, /* 56 */
+ { 0x0000000000000000ULL, 0xffffffff00000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xffffffff00000000ULL, 0xffffffffffffffffULL, },
+ { 0x0000000000000000ULL, 0xffffffff00000000ULL, },
+ { 0xffffffff00000000ULL, 0xffffffffffffffffULL, },
+ { 0x0000000000000000ULL, 0xffffffff00000000ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 64 */
+ { 0xffffffffffffffffULL, 0x00000000ffffffffULL, },
+ { 0xffffffff00000000ULL, 0x0000000000000000ULL, },
+ { 0xffffffffffffffffULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0xffffffff00000000ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0x0000000000000000ULL, 0xffffffff00000000ULL, },
+ { 0xffffffffffffffffULL, 0x0000000000000000ULL, },
+ { 0x00000000ffffffffULL, 0xffffffffffffffffULL, }, /* 72 */
+ { 0xffffffffffffffffULL, 0x00000000ffffffffULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0xffffffffffffffffULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0xffffffffffffffffULL, },
+ { 0x0000000000000000ULL, 0xffffffffffffffffULL, },
+ { 0x0000000000000000ULL, 0xffffffffffffffffULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ };
+
+ gettimeofday(&start, NULL);
+
+ for (i = 0; i < PATTERN_INPUTS_SHORT_COUNT; i++) {
+ for (j = 0; j < PATTERN_INPUTS_SHORT_COUNT; j++) {
+ do_msa_CLE_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_CLE_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-compare/test_msa_cle_u_b.c b/tests/tcg/mips/user/ase/msa/int-compare/test_msa_cle_u_b.c
new file mode 100644
index 0000000..9990a5b
--- /dev/null
+++ b/tests/tcg/mips/user/ase/msa/int-compare/test_msa_cle_u_b.c
@@ -0,0 +1,153 @@
+/*
+ * Test program for MSA instruction CLE_U.B
+ *
+ * Copyright (C) 2018 Wave Computing, Inc.
+ * Copyright (C) 2018 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.h"
+#include "../../../../include/test_utils.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 = "CLE_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] = {
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 0 */
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 8 */
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 16 */
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xff0000ff0000ff00ULL, 0x00ff0000ff0000ffULL, },
+ { 0x0000ff0000ff0000ULL, 0xff0000ff0000ff00ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 24 */
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xffff00ffff00ffffULL, 0x00ffff00ffff00ffULL, },
+ { 0x00ffff00ffff00ffULL, 0xff00ffff00ffff00ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 32 */
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xff0000ff0000ff00ULL, 0x00ff0000ff0000ffULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 40 */
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0x00ffff00ffff00ffULL, 0xff00ffff00ffff00ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 48 */
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x00ffff00ffff00ffULL, 0xff00ffff00ffff00ULL, },
+ { 0x0000ff0000ff0000ULL, 0xff0000ff0000ff00ULL, },
+ { 0x00ffff00ffff00ffULL, 0xff00ffff00ffff00ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0x0000ff0000ff0000ULL, 0xff0000ff0000ff00ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 56 */
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xffff00ffff00ffffULL, 0x00ffff00ffff00ffULL, },
+ { 0xff0000ff0000ff00ULL, 0x00ff0000ff0000ffULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0xff0000ff0000ff00ULL, 0x00ff0000ff0000ffULL, },
+ { 0xffff00ffff00ffffULL, 0x00ffff00ffff00ffULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 64 */
+ { 0xffff0000ffffff00ULL, 0x00ffff00000000ffULL, },
+ { 0xff000000ffffffffULL, 0x00ffffff000000ffULL, },
+ { 0x00000000ff00ffffULL, 0xffffffff0000ffffULL, },
+ { 0x0000ffff000000ffULL, 0xff0000ffffffff00ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0x0000ffffffff00ffULL, 0xff00ffffff000000ULL, },
+ { 0x0000ff00ff00ffffULL, 0xff0000ffffffff00ULL, },
+ { 0x00ffffff00000000ULL, 0xff000000ffffff00ULL, }, /* 72 */
+ { 0xffff00000000ff00ULL, 0x00ff000000ffffffULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0x000000000000ff00ULL, 0xffff000000ffffffULL, },
+ { 0xffffffff00ff0000ULL, 0x00000000ffff0000ULL, },
+ { 0xffff00ff00ff0000ULL, 0x00ffff00000000ffULL, },
+ { 0xffffffffffff00ffULL, 0x0000ffffff000000ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ };
+
+ gettimeofday(&start, NULL);
+
+ for (i = 0; i < PATTERN_INPUTS_SHORT_COUNT; i++) {
+ for (j = 0; j < PATTERN_INPUTS_SHORT_COUNT; j++) {
+ do_msa_CLE_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_CLE_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-compare/test_msa_cle_u_d.c b/tests/tcg/mips/user/ase/msa/int-compare/test_msa_cle_u_d.c
new file mode 100644
index 0000000..cde86d8
--- /dev/null
+++ b/tests/tcg/mips/user/ase/msa/int-compare/test_msa_cle_u_d.c
@@ -0,0 +1,153 @@
+/*
+ * Test program for MSA instruction CLE_U.D
+ *
+ * Copyright (C) 2018 Wave Computing, Inc.
+ * Copyright (C) 2018 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.h"
+#include "../../../../include/test_utils.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 = "CLE_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] = {
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 0 */
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 8 */
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 16 */
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xffffffffffffffffULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0xffffffffffffffffULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 24 */
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xffffffffffffffffULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0xffffffffffffffffULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 32 */
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xffffffffffffffffULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 40 */
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0x0000000000000000ULL, 0xffffffffffffffffULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 48 */
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0xffffffffffffffffULL, },
+ { 0x0000000000000000ULL, 0xffffffffffffffffULL, },
+ { 0x0000000000000000ULL, 0xffffffffffffffffULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0x0000000000000000ULL, 0xffffffffffffffffULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 56 */
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xffffffffffffffffULL, 0x0000000000000000ULL, },
+ { 0xffffffffffffffffULL, 0x0000000000000000ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0xffffffffffffffffULL, 0x0000000000000000ULL, },
+ { 0xffffffffffffffffULL, 0x0000000000000000ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 64 */
+ { 0xffffffffffffffffULL, 0x0000000000000000ULL, },
+ { 0xffffffffffffffffULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0xffffffffffffffffULL, },
+ { 0x0000000000000000ULL, 0xffffffffffffffffULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0x0000000000000000ULL, 0xffffffffffffffffULL, },
+ { 0x0000000000000000ULL, 0xffffffffffffffffULL, },
+ { 0x0000000000000000ULL, 0xffffffffffffffffULL, }, /* 72 */
+ { 0xffffffffffffffffULL, 0x0000000000000000ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0x0000000000000000ULL, 0xffffffffffffffffULL, },
+ { 0xffffffffffffffffULL, 0x0000000000000000ULL, },
+ { 0xffffffffffffffffULL, 0x0000000000000000ULL, },
+ { 0xffffffffffffffffULL, 0x0000000000000000ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ };
+
+ gettimeofday(&start, NULL);
+
+ for (i = 0; i < PATTERN_INPUTS_SHORT_COUNT; i++) {
+ for (j = 0; j < PATTERN_INPUTS_SHORT_COUNT; j++) {
+ do_msa_CLE_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_CLE_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-compare/test_msa_cle_u_h.c b/tests/tcg/mips/user/ase/msa/int-compare/test_msa_cle_u_h.c
new file mode 100644
index 0000000..70e4b48
--- /dev/null
+++ b/tests/tcg/mips/user/ase/msa/int-compare/test_msa_cle_u_h.c
@@ -0,0 +1,153 @@
+/*
+ * Test program for MSA instruction CLE_U.H
+ *
+ * Copyright (C) 2018 Wave Computing, Inc.
+ * Copyright (C) 2018 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.h"
+#include "../../../../include/test_utils.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 = "CLE_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] = {
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 0 */
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 8 */
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 16 */
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xffff00000000ffffULL, 0x00000000ffff0000ULL, },
+ { 0x0000ffff00000000ULL, 0xffff00000000ffffULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 24 */
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xffff0000ffffffffULL, 0x0000ffffffff0000ULL, },
+ { 0x0000ffffffff0000ULL, 0xffffffff0000ffffULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 32 */
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xffff00000000ffffULL, 0x00000000ffff0000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 40 */
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0x0000ffffffff0000ULL, 0xffffffff0000ffffULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 48 */
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000ffffffff0000ULL, 0xffffffff0000ffffULL, },
+ { 0x0000ffff00000000ULL, 0xffff00000000ffffULL, },
+ { 0x0000ffffffff0000ULL, 0xffffffff0000ffffULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0x0000ffff00000000ULL, 0xffff00000000ffffULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 56 */
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xffff0000ffffffffULL, 0x0000ffffffff0000ULL, },
+ { 0xffff00000000ffffULL, 0x00000000ffff0000ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0xffff00000000ffffULL, 0x00000000ffff0000ULL, },
+ { 0xffff0000ffffffffULL, 0x0000ffffffff0000ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 64 */
+ { 0xffff0000ffffffffULL, 0x0000ffff00000000ULL, },
+ { 0xffff0000ffffffffULL, 0x0000ffff00000000ULL, },
+ { 0x00000000ffffffffULL, 0xffffffff0000ffffULL, },
+ { 0x0000ffff00000000ULL, 0xffff0000ffffffffULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0x0000ffffffff0000ULL, 0xffffffffffff0000ULL, },
+ { 0x0000ffffffffffffULL, 0xffff0000ffffffffULL, },
+ { 0x0000ffff00000000ULL, 0xffff0000ffffffffULL, }, /* 72 */
+ { 0xffff00000000ffffULL, 0x000000000000ffffULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0x000000000000ffffULL, 0xffff00000000ffffULL, },
+ { 0xffffffff00000000ULL, 0x00000000ffff0000ULL, },
+ { 0xffff000000000000ULL, 0x0000ffff00000000ULL, },
+ { 0xffffffffffff0000ULL, 0x0000ffffffff0000ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ };
+
+ gettimeofday(&start, NULL);
+
+ for (i = 0; i < PATTERN_INPUTS_SHORT_COUNT; i++) {
+ for (j = 0; j < PATTERN_INPUTS_SHORT_COUNT; j++) {
+ do_msa_CLE_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_CLE_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-compare/test_msa_cle_u_w.c b/tests/tcg/mips/user/ase/msa/int-compare/test_msa_cle_u_w.c
new file mode 100644
index 0000000..f38feac
--- /dev/null
+++ b/tests/tcg/mips/user/ase/msa/int-compare/test_msa_cle_u_w.c
@@ -0,0 +1,153 @@
+/*
+ * Test program for MSA instruction CLE_U.W
+ *
+ * Copyright (C) 2018 Wave Computing, Inc.
+ * Copyright (C) 2018 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.h"
+#include "../../../../include/test_utils.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 = "CLE_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] = {
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 0 */
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 8 */
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 16 */
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xffffffff00000000ULL, 0x00000000ffffffffULL, },
+ { 0x0000000000000000ULL, 0xffffffff00000000ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 24 */
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xffffffffffffffffULL, 0x00000000ffffffffULL, },
+ { 0x00000000ffffffffULL, 0xffffffff00000000ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 32 */
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xffffffff00000000ULL, 0x00000000ffffffffULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 40 */
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0x00000000ffffffffULL, 0xffffffff00000000ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 48 */
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x00000000ffffffffULL, 0xffffffff00000000ULL, },
+ { 0x0000000000000000ULL, 0xffffffff00000000ULL, },
+ { 0x00000000ffffffffULL, 0xffffffff00000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0x0000000000000000ULL, 0xffffffff00000000ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 56 */
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xffffffffffffffffULL, 0x00000000ffffffffULL, },
+ { 0xffffffff00000000ULL, 0x00000000ffffffffULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0xffffffff00000000ULL, 0x00000000ffffffffULL, },
+ { 0xffffffffffffffffULL, 0x00000000ffffffffULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 64 */
+ { 0xffffffffffffffffULL, 0x0000000000000000ULL, },
+ { 0xffffffffffffffffULL, 0x0000000000000000ULL, },
+ { 0x00000000ffffffffULL, 0xffffffff00000000ULL, },
+ { 0x0000000000000000ULL, 0xffffffffffffffffULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0x00000000ffffffffULL, 0xffffffffffffffffULL, },
+ { 0x00000000ffffffffULL, 0xffffffffffffffffULL, },
+ { 0x0000000000000000ULL, 0xffffffffffffffffULL, }, /* 72 */
+ { 0xffffffff00000000ULL, 0x0000000000000000ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0x0000000000000000ULL, 0xffffffff00000000ULL, },
+ { 0xffffffff00000000ULL, 0x00000000ffffffffULL, },
+ { 0xffffffff00000000ULL, 0x0000000000000000ULL, },
+ { 0xffffffffffffffffULL, 0x00000000ffffffffULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ };
+
+ gettimeofday(&start, NULL);
+
+ for (i = 0; i < PATTERN_INPUTS_SHORT_COUNT; i++) {
+ for (j = 0; j < PATTERN_INPUTS_SHORT_COUNT; j++) {
+ do_msa_CLE_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_CLE_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-compare/test_msa_clt_s_b.c b/tests/tcg/mips/user/ase/msa/int-compare/test_msa_clt_s_b.c
new file mode 100644
index 0000000..b81b569
--- /dev/null
+++ b/tests/tcg/mips/user/ase/msa/int-compare/test_msa_clt_s_b.c
@@ -0,0 +1,153 @@
+/*
+ * Test program for MSA instruction CLT_S.B
+ *
+ * Copyright (C) 2018 Wave Computing, Inc.
+ * Copyright (C) 2018 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.h"
+#include "../../../../include/test_utils.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 = "CLT_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, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0x0000ff0000ff0000ULL, 0xff0000ff0000ff00ULL, },
+ { 0xffff00ffff00ffffULL, 0x00ffff00ffff00ffULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, }, /* 8 */
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0x0000ff0000ff0000ULL, 0xff0000ff0000ff00ULL, },
+ { 0xffff00ffff00ffffULL, 0x00ffff00ffff00ffULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 16 */
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0xff00ffff00ffff00ULL, 0xffff00ffff00ffffULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, }, /* 24 */
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x00ff0000ff0000ffULL, 0x0000ff0000ff0000ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 32 */
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0xff00ffff00ffff00ULL, 0xffff00ffff00ffffULL, },
+ { 0xffff00ffff00ffffULL, 0x00ffff00ffff00ffULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, }, /* 40 */
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000ff0000ff0000ULL, 0xff0000ff0000ff00ULL, },
+ { 0x00ff0000ff0000ffULL, 0x0000ff0000ff0000ULL, },
+ { 0xffff00ffff00ffffULL, 0x00ffff00ffff00ffULL, }, /* 48 */
+ { 0xffff00ffff00ffffULL, 0x00ffff00ffff00ffULL, },
+ { 0x00ff0000ff0000ffULL, 0x0000ff0000ff0000ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0x00ff0000ff0000ffULL, 0x0000ff0000ff0000ULL, },
+ { 0xffff00ffff00ffffULL, 0x00ffff00ffff00ffULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xffff00ffff00ffffULL, 0x00ffff00ffff00ffULL, },
+ { 0x0000ff0000ff0000ULL, 0xff0000ff0000ff00ULL, }, /* 56 */
+ { 0x0000ff0000ff0000ULL, 0xff0000ff0000ff00ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xff00ffff00ffff00ULL, 0xffff00ffff00ffffULL, },
+ { 0x0000ff0000ff0000ULL, 0xff0000ff0000ff00ULL, },
+ { 0xff00ffff00ffff00ULL, 0xffff00ffff00ffffULL, },
+ { 0x0000ff0000ff0000ULL, 0xff0000ff0000ff00ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, }, /* 64 */
+ { 0xff00ffffff000000ULL, 0x00000000ff00ff00ULL, },
+ { 0xff00000000000000ULL, 0x000000000000ffffULL, },
+ { 0xff00ffffff0000ffULL, 0x000000000000ff00ULL, },
+ { 0x00ff000000ffffffULL, 0xffffffff00ff00ffULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x00ff000000ff0000ULL, 0xff00ff00000000ffULL, },
+ { 0xffffff00ffffffffULL, 0x0000000000ff0000ULL, },
+ { 0x00ffffffffffffffULL, 0xffffffffffff0000ULL, }, /* 72 */
+ { 0xff00ffffff00ffffULL, 0x00ff00ffffffff00ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xff00ffffffffffffULL, 0x00ff000000ff0000ULL, },
+ { 0x00ff000000ffff00ULL, 0xffffffffffff00ffULL, },
+ { 0x000000ff00000000ULL, 0xffffffffff00ffffULL, },
+ { 0x00ff000000000000ULL, 0xff00ffffff00ffffULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ };
+
+ gettimeofday(&start, NULL);
+
+ for (i = 0; i < PATTERN_INPUTS_SHORT_COUNT; i++) {
+ for (j = 0; j < PATTERN_INPUTS_SHORT_COUNT; j++) {
+ do_msa_CLT_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_CLT_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-compare/test_msa_clt_s_d.c b/tests/tcg/mips/user/ase/msa/int-compare/test_msa_clt_s_d.c
new file mode 100644
index 0000000..393457a
--- /dev/null
+++ b/tests/tcg/mips/user/ase/msa/int-compare/test_msa_clt_s_d.c
@@ -0,0 +1,153 @@
+/*
+ * Test program for MSA instruction CLT_S.D
+ *
+ * Copyright (C) 2018 Wave Computing, Inc.
+ * Copyright (C) 2018 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.h"
+#include "../../../../include/test_utils.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 = "CLT_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, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0x0000000000000000ULL, 0xffffffffffffffffULL, },
+ { 0xffffffffffffffffULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, }, /* 8 */
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0x0000000000000000ULL, 0xffffffffffffffffULL, },
+ { 0xffffffffffffffffULL, 0x0000000000000000ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 16 */
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, }, /* 24 */
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 32 */
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0xffffffffffffffffULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, }, /* 40 */
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0xffffffffffffffffULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xffffffffffffffffULL, 0x0000000000000000ULL, }, /* 48 */
+ { 0xffffffffffffffffULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xffffffffffffffffULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xffffffffffffffffULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0xffffffffffffffffULL, }, /* 56 */
+ { 0x0000000000000000ULL, 0xffffffffffffffffULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0x0000000000000000ULL, 0xffffffffffffffffULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0x0000000000000000ULL, 0xffffffffffffffffULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, }, /* 64 */
+ { 0xffffffffffffffffULL, 0x0000000000000000ULL, },
+ { 0xffffffffffffffffULL, 0x0000000000000000ULL, },
+ { 0xffffffffffffffffULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0xffffffffffffffffULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0xffffffffffffffffULL, },
+ { 0xffffffffffffffffULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0xffffffffffffffffULL, }, /* 72 */
+ { 0xffffffffffffffffULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xffffffffffffffffULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0xffffffffffffffffULL, },
+ { 0x0000000000000000ULL, 0xffffffffffffffffULL, },
+ { 0x0000000000000000ULL, 0xffffffffffffffffULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ };
+
+ gettimeofday(&start, NULL);
+
+ for (i = 0; i < PATTERN_INPUTS_SHORT_COUNT; i++) {
+ for (j = 0; j < PATTERN_INPUTS_SHORT_COUNT; j++) {
+ do_msa_CLT_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_CLT_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-compare/test_msa_clt_s_h.c b/tests/tcg/mips/user/ase/msa/int-compare/test_msa_clt_s_h.c
new file mode 100644
index 0000000..56860d7
--- /dev/null
+++ b/tests/tcg/mips/user/ase/msa/int-compare/test_msa_clt_s_h.c
@@ -0,0 +1,153 @@
+/*
+ * Test program for MSA instruction CLT_S.H
+ *
+ * Copyright (C) 2018 Wave Computing, Inc.
+ * Copyright (C) 2018 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.h"
+#include "../../../../include/test_utils.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 = "CLT_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, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0x0000ffff00000000ULL, 0xffff00000000ffffULL, },
+ { 0xffff0000ffffffffULL, 0x0000ffffffff0000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, }, /* 8 */
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0x0000ffff00000000ULL, 0xffff00000000ffffULL, },
+ { 0xffff0000ffffffffULL, 0x0000ffffffff0000ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 16 */
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0xffffffff0000ffffULL, 0xffff0000ffffffffULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, }, /* 24 */
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x00000000ffff0000ULL, 0x0000ffff00000000ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 32 */
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0xffffffff0000ffffULL, 0xffff0000ffffffffULL, },
+ { 0xffff0000ffffffffULL, 0x0000ffffffff0000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, }, /* 40 */
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000ffff00000000ULL, 0xffff00000000ffffULL, },
+ { 0x00000000ffff0000ULL, 0x0000ffff00000000ULL, },
+ { 0xffff0000ffffffffULL, 0x0000ffffffff0000ULL, }, /* 48 */
+ { 0xffff0000ffffffffULL, 0x0000ffffffff0000ULL, },
+ { 0x00000000ffff0000ULL, 0x0000ffff00000000ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0x00000000ffff0000ULL, 0x0000ffff00000000ULL, },
+ { 0xffff0000ffffffffULL, 0x0000ffffffff0000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xffff0000ffffffffULL, 0x0000ffffffff0000ULL, },
+ { 0x0000ffff00000000ULL, 0xffff00000000ffffULL, }, /* 56 */
+ { 0x0000ffff00000000ULL, 0xffff00000000ffffULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xffffffff0000ffffULL, 0xffff0000ffffffffULL, },
+ { 0x0000ffff00000000ULL, 0xffff00000000ffffULL, },
+ { 0xffffffff0000ffffULL, 0xffff0000ffffffffULL, },
+ { 0x0000ffff00000000ULL, 0xffff00000000ffffULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, }, /* 64 */
+ { 0xffffffffffff0000ULL, 0x00000000ffffffffULL, },
+ { 0xffff000000000000ULL, 0x000000000000ffffULL, },
+ { 0xffffffffffff0000ULL, 0x000000000000ffffULL, },
+ { 0x000000000000ffffULL, 0xffffffff00000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0xffffffff00000000ULL, },
+ { 0xffffffffffffffffULL, 0x0000000000000000ULL, },
+ { 0x0000ffffffffffffULL, 0xffffffffffff0000ULL, }, /* 72 */
+ { 0xffffffffffffffffULL, 0x00000000ffffffffULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xffffffffffffffffULL, 0x0000000000000000ULL, },
+ { 0x000000000000ffffULL, 0xffffffffffff0000ULL, },
+ { 0x0000000000000000ULL, 0xffffffffffffffffULL, },
+ { 0x0000000000000000ULL, 0xffffffffffffffffULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ };
+
+ gettimeofday(&start, NULL);
+
+ for (i = 0; i < PATTERN_INPUTS_SHORT_COUNT; i++) {
+ for (j = 0; j < PATTERN_INPUTS_SHORT_COUNT; j++) {
+ do_msa_CLT_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_CLT_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-compare/test_msa_clt_s_w.c b/tests/tcg/mips/user/ase/msa/int-compare/test_msa_clt_s_w.c
new file mode 100644
index 0000000..346b293
--- /dev/null
+++ b/tests/tcg/mips/user/ase/msa/int-compare/test_msa_clt_s_w.c
@@ -0,0 +1,153 @@
+/*
+ * Test program for MSA instruction CLT_S.W
+ *
+ * Copyright (C) 2018 Wave Computing, Inc.
+ * Copyright (C) 2018 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.h"
+#include "../../../../include/test_utils.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 = "CLT_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, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0x0000000000000000ULL, 0xffffffff00000000ULL, },
+ { 0xffffffffffffffffULL, 0x00000000ffffffffULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, }, /* 8 */
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0x0000000000000000ULL, 0xffffffff00000000ULL, },
+ { 0xffffffffffffffffULL, 0x00000000ffffffffULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 16 */
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0xffffffff00000000ULL, 0xffffffffffffffffULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, }, /* 24 */
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x00000000ffffffffULL, 0x0000000000000000ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 32 */
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0xffffffff00000000ULL, 0xffffffffffffffffULL, },
+ { 0xffffffffffffffffULL, 0x00000000ffffffffULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, }, /* 40 */
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0xffffffff00000000ULL, },
+ { 0x00000000ffffffffULL, 0x0000000000000000ULL, },
+ { 0xffffffffffffffffULL, 0x00000000ffffffffULL, }, /* 48 */
+ { 0xffffffffffffffffULL, 0x00000000ffffffffULL, },
+ { 0x00000000ffffffffULL, 0x0000000000000000ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0x00000000ffffffffULL, 0x0000000000000000ULL, },
+ { 0xffffffffffffffffULL, 0x00000000ffffffffULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xffffffffffffffffULL, 0x00000000ffffffffULL, },
+ { 0x0000000000000000ULL, 0xffffffff00000000ULL, }, /* 56 */
+ { 0x0000000000000000ULL, 0xffffffff00000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xffffffff00000000ULL, 0xffffffffffffffffULL, },
+ { 0x0000000000000000ULL, 0xffffffff00000000ULL, },
+ { 0xffffffff00000000ULL, 0xffffffffffffffffULL, },
+ { 0x0000000000000000ULL, 0xffffffff00000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, }, /* 64 */
+ { 0xffffffffffffffffULL, 0x00000000ffffffffULL, },
+ { 0xffffffff00000000ULL, 0x0000000000000000ULL, },
+ { 0xffffffffffffffffULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0xffffffff00000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0xffffffff00000000ULL, },
+ { 0xffffffffffffffffULL, 0x0000000000000000ULL, },
+ { 0x00000000ffffffffULL, 0xffffffffffffffffULL, }, /* 72 */
+ { 0xffffffffffffffffULL, 0x00000000ffffffffULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xffffffffffffffffULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0xffffffffffffffffULL, },
+ { 0x0000000000000000ULL, 0xffffffffffffffffULL, },
+ { 0x0000000000000000ULL, 0xffffffffffffffffULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ };
+
+ gettimeofday(&start, NULL);
+
+ for (i = 0; i < PATTERN_INPUTS_SHORT_COUNT; i++) {
+ for (j = 0; j < PATTERN_INPUTS_SHORT_COUNT; j++) {
+ do_msa_CLT_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_CLT_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-compare/test_msa_clt_u_b.c b/tests/tcg/mips/user/ase/msa/int-compare/test_msa_clt_u_b.c
new file mode 100644
index 0000000..be79646
--- /dev/null
+++ b/tests/tcg/mips/user/ase/msa/int-compare/test_msa_clt_u_b.c
@@ -0,0 +1,153 @@
+/*
+ * Test program for MSA instruction CLT_U.B
+ *
+ * Copyright (C) 2018 Wave Computing, Inc.
+ * Copyright (C) 2018 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.h"
+#include "../../../../include/test_utils.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 = "CLT_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 */
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 8 */
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 16 */
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xff0000ff0000ff00ULL, 0x00ff0000ff0000ffULL, },
+ { 0x0000ff0000ff0000ULL, 0xff0000ff0000ff00ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 24 */
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xffff00ffff00ffffULL, 0x00ffff00ffff00ffULL, },
+ { 0x00ffff00ffff00ffULL, 0xff00ffff00ffff00ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 32 */
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xff0000ff0000ff00ULL, 0x00ff0000ff0000ffULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 40 */
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0x00ffff00ffff00ffULL, 0xff00ffff00ffff00ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 48 */
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x00ffff00ffff00ffULL, 0xff00ffff00ffff00ULL, },
+ { 0x0000ff0000ff0000ULL, 0xff0000ff0000ff00ULL, },
+ { 0x00ffff00ffff00ffULL, 0xff00ffff00ffff00ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000ff0000ff0000ULL, 0xff0000ff0000ff00ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 56 */
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xffff00ffff00ffffULL, 0x00ffff00ffff00ffULL, },
+ { 0xff0000ff0000ff00ULL, 0x00ff0000ff0000ffULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0xff0000ff0000ff00ULL, 0x00ff0000ff0000ffULL, },
+ { 0xffff00ffff00ffffULL, 0x00ffff00ffff00ffULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, }, /* 64 */
+ { 0xffff0000ffffff00ULL, 0x00ffff00000000ffULL, },
+ { 0xff000000ffffffffULL, 0x00ffffff000000ffULL, },
+ { 0x00000000ff00ffffULL, 0xffffffff0000ffffULL, },
+ { 0x0000ffff000000ffULL, 0xff0000ffffffff00ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000ffffffff00ffULL, 0xff00ffffff000000ULL, },
+ { 0x0000ff00ff00ffffULL, 0xff0000ffffffff00ULL, },
+ { 0x00ffffff00000000ULL, 0xff000000ffffff00ULL, }, /* 72 */
+ { 0xffff00000000ff00ULL, 0x00ff000000ffffffULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x000000000000ff00ULL, 0xffff000000ffffffULL, },
+ { 0xffffffff00ff0000ULL, 0x00000000ffff0000ULL, },
+ { 0xffff00ff00ff0000ULL, 0x00ffff00000000ffULL, },
+ { 0xffffffffffff00ffULL, 0x0000ffffff000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ };
+
+ gettimeofday(&start, NULL);
+
+ for (i = 0; i < PATTERN_INPUTS_SHORT_COUNT; i++) {
+ for (j = 0; j < PATTERN_INPUTS_SHORT_COUNT; j++) {
+ do_msa_CLT_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_CLT_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-compare/test_msa_clt_u_d.c b/tests/tcg/mips/user/ase/msa/int-compare/test_msa_clt_u_d.c
new file mode 100644
index 0000000..afbe490
--- /dev/null
+++ b/tests/tcg/mips/user/ase/msa/int-compare/test_msa_clt_u_d.c
@@ -0,0 +1,153 @@
+/*
+ * Test program for MSA instruction CLT_U.D
+ *
+ * Copyright (C) 2018 Wave Computing, Inc.
+ * Copyright (C) 2018 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.h"
+#include "../../../../include/test_utils.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 = "CLT_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 */
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 8 */
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 16 */
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xffffffffffffffffULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0xffffffffffffffffULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 24 */
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xffffffffffffffffULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0xffffffffffffffffULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 32 */
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xffffffffffffffffULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 40 */
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0x0000000000000000ULL, 0xffffffffffffffffULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 48 */
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0xffffffffffffffffULL, },
+ { 0x0000000000000000ULL, 0xffffffffffffffffULL, },
+ { 0x0000000000000000ULL, 0xffffffffffffffffULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0xffffffffffffffffULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 56 */
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xffffffffffffffffULL, 0x0000000000000000ULL, },
+ { 0xffffffffffffffffULL, 0x0000000000000000ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0xffffffffffffffffULL, 0x0000000000000000ULL, },
+ { 0xffffffffffffffffULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, }, /* 64 */
+ { 0xffffffffffffffffULL, 0x0000000000000000ULL, },
+ { 0xffffffffffffffffULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0xffffffffffffffffULL, },
+ { 0x0000000000000000ULL, 0xffffffffffffffffULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0xffffffffffffffffULL, },
+ { 0x0000000000000000ULL, 0xffffffffffffffffULL, },
+ { 0x0000000000000000ULL, 0xffffffffffffffffULL, }, /* 72 */
+ { 0xffffffffffffffffULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0xffffffffffffffffULL, },
+ { 0xffffffffffffffffULL, 0x0000000000000000ULL, },
+ { 0xffffffffffffffffULL, 0x0000000000000000ULL, },
+ { 0xffffffffffffffffULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ };
+
+ gettimeofday(&start, NULL);
+
+ for (i = 0; i < PATTERN_INPUTS_SHORT_COUNT; i++) {
+ for (j = 0; j < PATTERN_INPUTS_SHORT_COUNT; j++) {
+ do_msa_CLT_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_CLT_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-compare/test_msa_clt_u_h.c b/tests/tcg/mips/user/ase/msa/int-compare/test_msa_clt_u_h.c
new file mode 100644
index 0000000..126597a
--- /dev/null
+++ b/tests/tcg/mips/user/ase/msa/int-compare/test_msa_clt_u_h.c
@@ -0,0 +1,153 @@
+/*
+ * Test program for MSA instruction CLT_U.H
+ *
+ * Copyright (C) 2018 Wave Computing, Inc.
+ * Copyright (C) 2018 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.h"
+#include "../../../../include/test_utils.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 = "CLT_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 */
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 8 */
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 16 */
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xffff00000000ffffULL, 0x00000000ffff0000ULL, },
+ { 0x0000ffff00000000ULL, 0xffff00000000ffffULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 24 */
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xffff0000ffffffffULL, 0x0000ffffffff0000ULL, },
+ { 0x0000ffffffff0000ULL, 0xffffffff0000ffffULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 32 */
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xffff00000000ffffULL, 0x00000000ffff0000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 40 */
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0x0000ffffffff0000ULL, 0xffffffff0000ffffULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 48 */
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000ffffffff0000ULL, 0xffffffff0000ffffULL, },
+ { 0x0000ffff00000000ULL, 0xffff00000000ffffULL, },
+ { 0x0000ffffffff0000ULL, 0xffffffff0000ffffULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000ffff00000000ULL, 0xffff00000000ffffULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 56 */
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xffff0000ffffffffULL, 0x0000ffffffff0000ULL, },
+ { 0xffff00000000ffffULL, 0x00000000ffff0000ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0xffff00000000ffffULL, 0x00000000ffff0000ULL, },
+ { 0xffff0000ffffffffULL, 0x0000ffffffff0000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, }, /* 64 */
+ { 0xffff0000ffffffffULL, 0x0000ffff00000000ULL, },
+ { 0xffff0000ffffffffULL, 0x0000ffff00000000ULL, },
+ { 0x00000000ffffffffULL, 0xffffffff0000ffffULL, },
+ { 0x0000ffff00000000ULL, 0xffff0000ffffffffULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000ffffffff0000ULL, 0xffffffffffff0000ULL, },
+ { 0x0000ffffffffffffULL, 0xffff0000ffffffffULL, },
+ { 0x0000ffff00000000ULL, 0xffff0000ffffffffULL, }, /* 72 */
+ { 0xffff00000000ffffULL, 0x000000000000ffffULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x000000000000ffffULL, 0xffff00000000ffffULL, },
+ { 0xffffffff00000000ULL, 0x00000000ffff0000ULL, },
+ { 0xffff000000000000ULL, 0x0000ffff00000000ULL, },
+ { 0xffffffffffff0000ULL, 0x0000ffffffff0000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ };
+
+ gettimeofday(&start, NULL);
+
+ for (i = 0; i < PATTERN_INPUTS_SHORT_COUNT; i++) {
+ for (j = 0; j < PATTERN_INPUTS_SHORT_COUNT; j++) {
+ do_msa_CLT_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_CLT_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-compare/test_msa_clt_u_w.c b/tests/tcg/mips/user/ase/msa/int-compare/test_msa_clt_u_w.c
new file mode 100644
index 0000000..b405929
--- /dev/null
+++ b/tests/tcg/mips/user/ase/msa/int-compare/test_msa_clt_u_w.c
@@ -0,0 +1,153 @@
+/*
+ * Test program for MSA instruction CLT_U.W
+ *
+ * Copyright (C) 2018 Wave Computing, Inc.
+ * Copyright (C) 2018 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.h"
+#include "../../../../include/test_utils.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 = "CLT_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 */
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 8 */
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 16 */
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xffffffff00000000ULL, 0x00000000ffffffffULL, },
+ { 0x0000000000000000ULL, 0xffffffff00000000ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 24 */
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xffffffffffffffffULL, 0x00000000ffffffffULL, },
+ { 0x00000000ffffffffULL, 0xffffffff00000000ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 32 */
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xffffffff00000000ULL, 0x00000000ffffffffULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 40 */
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0x00000000ffffffffULL, 0xffffffff00000000ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 48 */
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x00000000ffffffffULL, 0xffffffff00000000ULL, },
+ { 0x0000000000000000ULL, 0xffffffff00000000ULL, },
+ { 0x00000000ffffffffULL, 0xffffffff00000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0xffffffff00000000ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 56 */
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xffffffffffffffffULL, 0x00000000ffffffffULL, },
+ { 0xffffffff00000000ULL, 0x00000000ffffffffULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0xffffffff00000000ULL, 0x00000000ffffffffULL, },
+ { 0xffffffffffffffffULL, 0x00000000ffffffffULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, }, /* 64 */
+ { 0xffffffffffffffffULL, 0x0000000000000000ULL, },
+ { 0xffffffffffffffffULL, 0x0000000000000000ULL, },
+ { 0x00000000ffffffffULL, 0xffffffff00000000ULL, },
+ { 0x0000000000000000ULL, 0xffffffffffffffffULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x00000000ffffffffULL, 0xffffffffffffffffULL, },
+ { 0x00000000ffffffffULL, 0xffffffffffffffffULL, },
+ { 0x0000000000000000ULL, 0xffffffffffffffffULL, }, /* 72 */
+ { 0xffffffff00000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0xffffffff00000000ULL, },
+ { 0xffffffff00000000ULL, 0x00000000ffffffffULL, },
+ { 0xffffffff00000000ULL, 0x0000000000000000ULL, },
+ { 0xffffffffffffffffULL, 0x00000000ffffffffULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ };
+
+ gettimeofday(&start, NULL);
+
+ for (i = 0; i < PATTERN_INPUTS_SHORT_COUNT; i++) {
+ for (j = 0; j < PATTERN_INPUTS_SHORT_COUNT; j++) {
+ do_msa_CLT_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_CLT_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-max-min/test_msa_max_a_b.c b/tests/tcg/mips/user/ase/msa/int-max-min/test_msa_max_a_b.c
new file mode 100644
index 0000000..b7a9a61
--- /dev/null
+++ b/tests/tcg/mips/user/ase/msa/int-max-min/test_msa_max_a_b.c
@@ -0,0 +1,153 @@
+/*
+ * Test program for MSA instruction MAX_A.B
+ *
+ * Copyright (C) 2018 Wave Computing, Inc.
+ * Copyright (C) 2018 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.h"
+#include "../../../../include/test_utils.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 = "MAX_A.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, },
+ { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, },
+ { 0x5555555555555555ULL, 0x5555555555555555ULL, },
+ { 0xccccccccccccccccULL, 0xccccccccccccccccULL, },
+ { 0x3333333333333333ULL, 0x3333333333333333ULL, },
+ { 0xe38e38e38e38e38eULL, 0x38e38e38e38e38e3ULL, },
+ { 0x1c71c71c71c71c71ULL, 0xc71c71c71c71c71cULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 8 */
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, },
+ { 0x5555555555555555ULL, 0x5555555555555555ULL, },
+ { 0xccccccccccccccccULL, 0xccccccccccccccccULL, },
+ { 0x3333333333333333ULL, 0x3333333333333333ULL, },
+ { 0xe38e38e38e38e38eULL, 0x38e38e38e38e38e3ULL, },
+ { 0x1c71c71c71c71c71ULL, 0xc71c71c71c71c71cULL, },
+ { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, }, /* 16 */
+ { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, },
+ { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, },
+ { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, },
+ { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, },
+ { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, },
+ { 0xaa8eaaaa8eaaaa8eULL, 0xaaaa8eaaaa8eaaaaULL, },
+ { 0xaa71aaaa71aaaa71ULL, 0xaaaa71aaaa71aaaaULL, },
+ { 0x5555555555555555ULL, 0x5555555555555555ULL, }, /* 24 */
+ { 0x5555555555555555ULL, 0x5555555555555555ULL, },
+ { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, },
+ { 0x5555555555555555ULL, 0x5555555555555555ULL, },
+ { 0x5555555555555555ULL, 0x5555555555555555ULL, },
+ { 0x5555555555555555ULL, 0x5555555555555555ULL, },
+ { 0x558e55558e55558eULL, 0x55558e55558e5555ULL, },
+ { 0x5571555571555571ULL, 0x5555715555715555ULL, },
+ { 0xccccccccccccccccULL, 0xccccccccccccccccULL, }, /* 32 */
+ { 0xccccccccccccccccULL, 0xccccccccccccccccULL, },
+ { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, },
+ { 0x5555555555555555ULL, 0x5555555555555555ULL, },
+ { 0xccccccccccccccccULL, 0xccccccccccccccccULL, },
+ { 0xccccccccccccccccULL, 0xccccccccccccccccULL, },
+ { 0xcc8e38cc8e38cc8eULL, 0x38cc8e38cc8e38ccULL, },
+ { 0xcc71c7cc71c7cc71ULL, 0xc7cc71c7cc71c7ccULL, },
+ { 0x3333333333333333ULL, 0x3333333333333333ULL, }, /* 40 */
+ { 0x3333333333333333ULL, 0x3333333333333333ULL, },
+ { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, },
+ { 0x5555555555555555ULL, 0x5555555555555555ULL, },
+ { 0xccccccccccccccccULL, 0xccccccccccccccccULL, },
+ { 0x3333333333333333ULL, 0x3333333333333333ULL, },
+ { 0x338e38338e38338eULL, 0x38338e38338e3833ULL, },
+ { 0x3371c73371c73371ULL, 0xc73371c73371c733ULL, },
+ { 0xe38e38e38e38e38eULL, 0x38e38e38e38e38e3ULL, }, /* 48 */
+ { 0xe38e38e38e38e38eULL, 0x38e38e38e38e38e3ULL, },
+ { 0xaa8eaaaa8eaaaa8eULL, 0xaaaa8eaaaa8eaaaaULL, },
+ { 0x558e55558e55558eULL, 0x55558e55558e5555ULL, },
+ { 0xcc8e38cc8e38cc8eULL, 0x38cc8e38cc8e38ccULL, },
+ { 0x338e38338e38338eULL, 0x38338e38338e3833ULL, },
+ { 0xe38e38e38e38e38eULL, 0x38e38e38e38e38e3ULL, },
+ { 0xe38ec7e38ec7e38eULL, 0xc7e38ec7e38ec7e3ULL, },
+ { 0x1c71c71c71c71c71ULL, 0xc71c71c71c71c71cULL, }, /* 56 */
+ { 0x1c71c71c71c71c71ULL, 0xc71c71c71c71c71cULL, },
+ { 0xaa71aaaa71aaaa71ULL, 0xaaaa71aaaa71aaaaULL, },
+ { 0x5571555571555571ULL, 0x5555715555715555ULL, },
+ { 0xcc71c7cc71c7cc71ULL, 0xc7cc71c7cc71c7ccULL, },
+ { 0x3371c73371c73371ULL, 0xc73371c73371c733ULL, },
+ { 0xe38ec7e38ec7e38eULL, 0xc7e38ec7e38ec7e3ULL, },
+ { 0x1c71c71c71c71c71ULL, 0xc71c71c71c71c71cULL, },
+ { 0x886ae6cc28625540ULL, 0x4b670b5efe7bb00cULL, }, /* 64 */
+ { 0x886ae6634d935540ULL, 0x4b67bb5e157b520cULL, },
+ { 0x886aaeaab9628b80ULL, 0x4b67c65eab7bb014ULL, },
+ { 0x886ae64d5e62554eULL, 0x8d67885ea97bb0a0ULL, },
+ { 0x886ae6634d935540ULL, 0x4b67bb5e157b520cULL, },
+ { 0xfbbe00634d93c708ULL, 0x12f7bb1a153f52fcULL, },
+ { 0xac5aae634d938b80ULL, 0x27d8bb1aab3f5214ULL, },
+ { 0x704f16635e93c74eULL, 0x8df188d8a94252a0ULL, },
+ { 0x886aaeaab9628b80ULL, 0x4b67c65eab7bb014ULL, }, /* 72 */
+ { 0xac5aae634d938b80ULL, 0x27d8bb1aab3f5214ULL, },
+ { 0xac5aaeaab9cf8b80ULL, 0x27d8c6ffab2b2514ULL, },
+ { 0x705aaeaa5e318b80ULL, 0x8dd888d8a94225a0ULL, },
+ { 0x886ae64d5e62554eULL, 0x8d67885ea97bb0a0ULL, },
+ { 0x704f16635e93c74eULL, 0x8df188d8a94252a0ULL, },
+ { 0x705aaeaa5ecf8b80ULL, 0x8dd888d8a94225a0ULL, },
+ { 0x704f164d5e31e24eULL, 0x8df188d8a942e2a0ULL, },
+ };
+
+ gettimeofday(&start, NULL);
+
+ for (i = 0; i < PATTERN_INPUTS_SHORT_COUNT; i++) {
+ for (j = 0; j < PATTERN_INPUTS_SHORT_COUNT; j++) {
+ do_msa_MAX_A_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_MAX_A_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-max-min/test_msa_max_a_d.c b/tests/tcg/mips/user/ase/msa/int-max-min/test_msa_max_a_d.c
new file mode 100644
index 0000000..dfffaf5
--- /dev/null
+++ b/tests/tcg/mips/user/ase/msa/int-max-min/test_msa_max_a_d.c
@@ -0,0 +1,153 @@
+/*
+ * Test program for MSA instruction MAX_A.D
+ *
+ * Copyright (C) 2018 Wave Computing, Inc.
+ * Copyright (C) 2018 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.h"
+#include "../../../../include/test_utils.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 = "MAX_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 */
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, },
+ { 0x5555555555555555ULL, 0x5555555555555555ULL, },
+ { 0xccccccccccccccccULL, 0xccccccccccccccccULL, },
+ { 0x3333333333333333ULL, 0x3333333333333333ULL, },
+ { 0xe38e38e38e38e38eULL, 0x38e38e38e38e38e3ULL, },
+ { 0x1c71c71c71c71c71ULL, 0xc71c71c71c71c71cULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 8 */
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, },
+ { 0x5555555555555555ULL, 0x5555555555555555ULL, },
+ { 0xccccccccccccccccULL, 0xccccccccccccccccULL, },
+ { 0x3333333333333333ULL, 0x3333333333333333ULL, },
+ { 0xe38e38e38e38e38eULL, 0x38e38e38e38e38e3ULL, },
+ { 0x1c71c71c71c71c71ULL, 0xc71c71c71c71c71cULL, },
+ { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, }, /* 16 */
+ { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, },
+ { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, },
+ { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, },
+ { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, },
+ { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, },
+ { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, },
+ { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, },
+ { 0x5555555555555555ULL, 0x5555555555555555ULL, }, /* 24 */
+ { 0x5555555555555555ULL, 0x5555555555555555ULL, },
+ { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, },
+ { 0x5555555555555555ULL, 0x5555555555555555ULL, },
+ { 0x5555555555555555ULL, 0x5555555555555555ULL, },
+ { 0x5555555555555555ULL, 0x5555555555555555ULL, },
+ { 0x5555555555555555ULL, 0x5555555555555555ULL, },
+ { 0x5555555555555555ULL, 0x5555555555555555ULL, },
+ { 0xccccccccccccccccULL, 0xccccccccccccccccULL, }, /* 32 */
+ { 0xccccccccccccccccULL, 0xccccccccccccccccULL, },
+ { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, },
+ { 0x5555555555555555ULL, 0x5555555555555555ULL, },
+ { 0xccccccccccccccccULL, 0xccccccccccccccccULL, },
+ { 0xccccccccccccccccULL, 0xccccccccccccccccULL, },
+ { 0xccccccccccccccccULL, 0x38e38e38e38e38e3ULL, },
+ { 0xccccccccccccccccULL, 0xc71c71c71c71c71cULL, },
+ { 0x3333333333333333ULL, 0x3333333333333333ULL, }, /* 40 */
+ { 0x3333333333333333ULL, 0x3333333333333333ULL, },
+ { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, },
+ { 0x5555555555555555ULL, 0x5555555555555555ULL, },
+ { 0xccccccccccccccccULL, 0xccccccccccccccccULL, },
+ { 0x3333333333333333ULL, 0x3333333333333333ULL, },
+ { 0x3333333333333333ULL, 0x38e38e38e38e38e3ULL, },
+ { 0x3333333333333333ULL, 0xc71c71c71c71c71cULL, },
+ { 0xe38e38e38e38e38eULL, 0x38e38e38e38e38e3ULL, }, /* 48 */
+ { 0xe38e38e38e38e38eULL, 0x38e38e38e38e38e3ULL, },
+ { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, },
+ { 0x5555555555555555ULL, 0x5555555555555555ULL, },
+ { 0xccccccccccccccccULL, 0x38e38e38e38e38e3ULL, },
+ { 0x3333333333333333ULL, 0x38e38e38e38e38e3ULL, },
+ { 0xe38e38e38e38e38eULL, 0x38e38e38e38e38e3ULL, },
+ { 0xe38e38e38e38e38eULL, 0xc71c71c71c71c71cULL, },
+ { 0x1c71c71c71c71c71ULL, 0xc71c71c71c71c71cULL, }, /* 56 */
+ { 0x1c71c71c71c71c71ULL, 0xc71c71c71c71c71cULL, },
+ { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, },
+ { 0x5555555555555555ULL, 0x5555555555555555ULL, },
+ { 0xccccccccccccccccULL, 0xc71c71c71c71c71cULL, },
+ { 0x3333333333333333ULL, 0xc71c71c71c71c71cULL, },
+ { 0xe38e38e38e38e38eULL, 0xc71c71c71c71c71cULL, },
+ { 0x1c71c71c71c71c71ULL, 0xc71c71c71c71c71cULL, },
+ { 0x886ae6cc28625540ULL, 0x4b670b5efe7bb00cULL, }, /* 64 */
+ { 0x886ae6cc28625540ULL, 0x4b670b5efe7bb00cULL, },
+ { 0x886ae6cc28625540ULL, 0x4b670b5efe7bb00cULL, },
+ { 0x886ae6cc28625540ULL, 0x8df188d8a942e2a0ULL, },
+ { 0x886ae6cc28625540ULL, 0x4b670b5efe7bb00cULL, },
+ { 0xfbbe00634d93c708ULL, 0x12f7bb1a153f52fcULL, },
+ { 0xac5aaeaab9cf8b80ULL, 0x27d8c6ffab2b2514ULL, },
+ { 0x704f164d5e31e24eULL, 0x8df188d8a942e2a0ULL, },
+ { 0x886ae6cc28625540ULL, 0x4b670b5efe7bb00cULL, }, /* 72 */
+ { 0xac5aaeaab9cf8b80ULL, 0x27d8c6ffab2b2514ULL, },
+ { 0xac5aaeaab9cf8b80ULL, 0x27d8c6ffab2b2514ULL, },
+ { 0x704f164d5e31e24eULL, 0x8df188d8a942e2a0ULL, },
+ { 0x886ae6cc28625540ULL, 0x8df188d8a942e2a0ULL, },
+ { 0x704f164d5e31e24eULL, 0x8df188d8a942e2a0ULL, },
+ { 0x704f164d5e31e24eULL, 0x8df188d8a942e2a0ULL, },
+ { 0x704f164d5e31e24eULL, 0x8df188d8a942e2a0ULL, },
+ };
+
+ gettimeofday(&start, NULL);
+
+ for (i = 0; i < PATTERN_INPUTS_SHORT_COUNT; i++) {
+ for (j = 0; j < PATTERN_INPUTS_SHORT_COUNT; j++) {
+ do_msa_MAX_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_MAX_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/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
new file mode 100644
index 0000000..e0c1bd4
--- /dev/null
+++ b/tests/tcg/mips/user/ase/msa/int-max-min/test_msa_max_a_h.c
@@ -0,0 +1,153 @@
+/*
+ * Test program for MSA instruction MAX_A.H
+ *
+ * Copyright (C) 2018 Wave Computing, Inc.
+ * Copyright (C) 2018 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.h"
+#include "../../../../include/test_utils.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 = "MAX_A.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, },
+ { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, },
+ { 0x5555555555555555ULL, 0x5555555555555555ULL, },
+ { 0xccccccccccccccccULL, 0xccccccccccccccccULL, },
+ { 0x3333333333333333ULL, 0x3333333333333333ULL, },
+ { 0xe38e38e38e38e38eULL, 0x38e38e38e38e38e3ULL, },
+ { 0x1c71c71c71c71c71ULL, 0xc71c71c71c71c71cULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 8 */
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, },
+ { 0x5555555555555555ULL, 0x5555555555555555ULL, },
+ { 0xccccccccccccccccULL, 0xccccccccccccccccULL, },
+ { 0x3333333333333333ULL, 0x3333333333333333ULL, },
+ { 0xe38e38e38e38e38eULL, 0x38e38e38e38e38e3ULL, },
+ { 0x1c71c71c71c71c71ULL, 0xc71c71c71c71c71cULL, },
+ { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, }, /* 16 */
+ { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, },
+ { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, },
+ { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, },
+ { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, },
+ { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, },
+ { 0xaaaaaaaa8e38aaaaULL, 0xaaaa8e38aaaaaaaaULL, },
+ { 0xaaaaaaaa71c7aaaaULL, 0xaaaa71c7aaaaaaaaULL, },
+ { 0x5555555555555555ULL, 0x5555555555555555ULL, }, /* 24 */
+ { 0x5555555555555555ULL, 0x5555555555555555ULL, },
+ { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, },
+ { 0x5555555555555555ULL, 0x5555555555555555ULL, },
+ { 0x5555555555555555ULL, 0x5555555555555555ULL, },
+ { 0x5555555555555555ULL, 0x5555555555555555ULL, },
+ { 0x555555558e385555ULL, 0x55558e3855555555ULL, },
+ { 0x5555555571c75555ULL, 0x555571c755555555ULL, },
+ { 0xccccccccccccccccULL, 0xccccccccccccccccULL, }, /* 32 */
+ { 0xccccccccccccccccULL, 0xccccccccccccccccULL, },
+ { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, },
+ { 0x5555555555555555ULL, 0x5555555555555555ULL, },
+ { 0xccccccccccccccccULL, 0xccccccccccccccccULL, },
+ { 0xccccccccccccccccULL, 0xccccccccccccccccULL, },
+ { 0xcccc38e38e38ccccULL, 0x38e38e38cccc38e3ULL, },
+ { 0xccccc71c71c7ccccULL, 0xc71c71c7ccccc71cULL, },
+ { 0x3333333333333333ULL, 0x3333333333333333ULL, }, /* 40 */
+ { 0x3333333333333333ULL, 0x3333333333333333ULL, },
+ { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, },
+ { 0x5555555555555555ULL, 0x5555555555555555ULL, },
+ { 0xccccccccccccccccULL, 0xccccccccccccccccULL, },
+ { 0x3333333333333333ULL, 0x3333333333333333ULL, },
+ { 0x333338e38e383333ULL, 0x38e38e38333338e3ULL, },
+ { 0x3333c71c71c73333ULL, 0xc71c71c73333c71cULL, },
+ { 0xe38e38e38e38e38eULL, 0x38e38e38e38e38e3ULL, }, /* 48 */
+ { 0xe38e38e38e38e38eULL, 0x38e38e38e38e38e3ULL, },
+ { 0xaaaaaaaa8e38aaaaULL, 0xaaaa8e38aaaaaaaaULL, },
+ { 0x555555558e385555ULL, 0x55558e3855555555ULL, },
+ { 0xcccc38e38e38ccccULL, 0x38e38e38cccc38e3ULL, },
+ { 0x333338e38e383333ULL, 0x38e38e38333338e3ULL, },
+ { 0xe38e38e38e38e38eULL, 0x38e38e38e38e38e3ULL, },
+ { 0xe38ec71c8e38e38eULL, 0xc71c8e38e38ec71cULL, },
+ { 0x1c71c71c71c71c71ULL, 0xc71c71c71c71c71cULL, }, /* 56 */
+ { 0x1c71c71c71c71c71ULL, 0xc71c71c71c71c71cULL, },
+ { 0xaaaaaaaa71c7aaaaULL, 0xaaaa71c7aaaaaaaaULL, },
+ { 0x5555555571c75555ULL, 0x555571c755555555ULL, },
+ { 0xccccc71c71c7ccccULL, 0xc71c71c7ccccc71cULL, },
+ { 0x3333c71c71c73333ULL, 0xc71c71c73333c71cULL, },
+ { 0xe38ec71c8e38e38eULL, 0xc71c8e38e38ec71cULL, },
+ { 0x1c71c71c71c71c71ULL, 0xc71c71c71c71c71cULL, },
+ { 0x886ae6cc28625540ULL, 0x4b670b5efe7bb00cULL, }, /* 64 */
+ { 0x886ae6cc4d935540ULL, 0x4b67bb1a153f52fcULL, },
+ { 0x886aaeaab9cf8b80ULL, 0x4b67c6ffab2bb00cULL, },
+ { 0x886ae6cc5e315540ULL, 0x8df188d8a942b00cULL, },
+ { 0x886ae6cc4d935540ULL, 0x4b67bb1a153f52fcULL, },
+ { 0xfbbe00634d93c708ULL, 0x12f7bb1a153f52fcULL, },
+ { 0xac5aaeaa4d938b80ULL, 0x27d8bb1aab2b52fcULL, },
+ { 0x704f164d5e31c708ULL, 0x8df188d8a94252fcULL, },
+ { 0x886aaeaab9cf8b80ULL, 0x4b67c6ffab2bb00cULL, }, /* 72 */
+ { 0xac5aaeaa4d938b80ULL, 0x27d8bb1aab2b52fcULL, },
+ { 0xac5aaeaab9cf8b80ULL, 0x27d8c6ffab2b2514ULL, },
+ { 0x704faeaa5e318b80ULL, 0x8df188d8a9422514ULL, },
+ { 0x886ae6cc5e315540ULL, 0x8df188d8a942b00cULL, },
+ { 0x704f164d5e31c708ULL, 0x8df188d8a94252fcULL, },
+ { 0x704faeaa5e318b80ULL, 0x8df188d8a9422514ULL, },
+ { 0x704f164d5e31e24eULL, 0x8df188d8a942e2a0ULL, },
+ };
+
+ gettimeofday(&start, NULL);
+
+ for (i = 0; i < PATTERN_INPUTS_SHORT_COUNT; i++) {
+ for (j = 0; j < PATTERN_INPUTS_SHORT_COUNT; j++) {
+ do_msa_MAX_A_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_MAX_A_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-max-min/test_msa_max_a_w.c b/tests/tcg/mips/user/ase/msa/int-max-min/test_msa_max_a_w.c
new file mode 100644
index 0000000..40c30c5
--- /dev/null
+++ b/tests/tcg/mips/user/ase/msa/int-max-min/test_msa_max_a_w.c
@@ -0,0 +1,153 @@
+/*
+ * Test program for MSA instruction MAX_A.W
+ *
+ * Copyright (C) 2018 Wave Computing, Inc.
+ * Copyright (C) 2018 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.h"
+#include "../../../../include/test_utils.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 = "MAX_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 */
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, },
+ { 0x5555555555555555ULL, 0x5555555555555555ULL, },
+ { 0xccccccccccccccccULL, 0xccccccccccccccccULL, },
+ { 0x3333333333333333ULL, 0x3333333333333333ULL, },
+ { 0xe38e38e38e38e38eULL, 0x38e38e38e38e38e3ULL, },
+ { 0x1c71c71c71c71c71ULL, 0xc71c71c71c71c71cULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 8 */
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, },
+ { 0x5555555555555555ULL, 0x5555555555555555ULL, },
+ { 0xccccccccccccccccULL, 0xccccccccccccccccULL, },
+ { 0x3333333333333333ULL, 0x3333333333333333ULL, },
+ { 0xe38e38e38e38e38eULL, 0x38e38e38e38e38e3ULL, },
+ { 0x1c71c71c71c71c71ULL, 0xc71c71c71c71c71cULL, },
+ { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, }, /* 16 */
+ { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, },
+ { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, },
+ { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, },
+ { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, },
+ { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, },
+ { 0xaaaaaaaa8e38e38eULL, 0xaaaaaaaaaaaaaaaaULL, },
+ { 0xaaaaaaaa71c71c71ULL, 0xaaaaaaaaaaaaaaaaULL, },
+ { 0x5555555555555555ULL, 0x5555555555555555ULL, }, /* 24 */
+ { 0x5555555555555555ULL, 0x5555555555555555ULL, },
+ { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, },
+ { 0x5555555555555555ULL, 0x5555555555555555ULL, },
+ { 0x5555555555555555ULL, 0x5555555555555555ULL, },
+ { 0x5555555555555555ULL, 0x5555555555555555ULL, },
+ { 0x555555558e38e38eULL, 0x5555555555555555ULL, },
+ { 0x5555555571c71c71ULL, 0x5555555555555555ULL, },
+ { 0xccccccccccccccccULL, 0xccccccccccccccccULL, }, /* 32 */
+ { 0xccccccccccccccccULL, 0xccccccccccccccccULL, },
+ { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, },
+ { 0x5555555555555555ULL, 0x5555555555555555ULL, },
+ { 0xccccccccccccccccULL, 0xccccccccccccccccULL, },
+ { 0xccccccccccccccccULL, 0xccccccccccccccccULL, },
+ { 0xcccccccc8e38e38eULL, 0x38e38e38ccccccccULL, },
+ { 0xcccccccc71c71c71ULL, 0xc71c71c7ccccccccULL, },
+ { 0x3333333333333333ULL, 0x3333333333333333ULL, }, /* 40 */
+ { 0x3333333333333333ULL, 0x3333333333333333ULL, },
+ { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, },
+ { 0x5555555555555555ULL, 0x5555555555555555ULL, },
+ { 0xccccccccccccccccULL, 0xccccccccccccccccULL, },
+ { 0x3333333333333333ULL, 0x3333333333333333ULL, },
+ { 0x333333338e38e38eULL, 0x38e38e3833333333ULL, },
+ { 0x3333333371c71c71ULL, 0xc71c71c733333333ULL, },
+ { 0xe38e38e38e38e38eULL, 0x38e38e38e38e38e3ULL, }, /* 48 */
+ { 0xe38e38e38e38e38eULL, 0x38e38e38e38e38e3ULL, },
+ { 0xaaaaaaaa8e38e38eULL, 0xaaaaaaaaaaaaaaaaULL, },
+ { 0x555555558e38e38eULL, 0x5555555555555555ULL, },
+ { 0xcccccccc8e38e38eULL, 0x38e38e38ccccccccULL, },
+ { 0x333333338e38e38eULL, 0x38e38e3833333333ULL, },
+ { 0xe38e38e38e38e38eULL, 0x38e38e38e38e38e3ULL, },
+ { 0xe38e38e38e38e38eULL, 0xc71c71c7e38e38e3ULL, },
+ { 0x1c71c71c71c71c71ULL, 0xc71c71c71c71c71cULL, }, /* 56 */
+ { 0x1c71c71c71c71c71ULL, 0xc71c71c71c71c71cULL, },
+ { 0xaaaaaaaa71c71c71ULL, 0xaaaaaaaaaaaaaaaaULL, },
+ { 0x5555555571c71c71ULL, 0x5555555555555555ULL, },
+ { 0xcccccccc71c71c71ULL, 0xc71c71c7ccccccccULL, },
+ { 0x3333333371c71c71ULL, 0xc71c71c733333333ULL, },
+ { 0xe38e38e38e38e38eULL, 0xc71c71c7e38e38e3ULL, },
+ { 0x1c71c71c71c71c71ULL, 0xc71c71c71c71c71cULL, },
+ { 0x886ae6cc28625540ULL, 0x4b670b5efe7bb00cULL, }, /* 64 */
+ { 0x886ae6cc4d93c708ULL, 0x4b670b5e153f52fcULL, },
+ { 0x886ae6ccb9cf8b80ULL, 0x4b670b5eab2b2514ULL, },
+ { 0x886ae6cc5e31e24eULL, 0x8df188d8a942e2a0ULL, },
+ { 0x886ae6cc4d93c708ULL, 0x4b670b5e153f52fcULL, },
+ { 0xfbbe00634d93c708ULL, 0x12f7bb1a153f52fcULL, },
+ { 0xac5aaeaa4d93c708ULL, 0x27d8c6ffab2b2514ULL, },
+ { 0x704f164d5e31e24eULL, 0x8df188d8a942e2a0ULL, },
+ { 0x886ae6ccb9cf8b80ULL, 0x4b670b5eab2b2514ULL, }, /* 72 */
+ { 0xac5aaeaa4d93c708ULL, 0x27d8c6ffab2b2514ULL, },
+ { 0xac5aaeaab9cf8b80ULL, 0x27d8c6ffab2b2514ULL, },
+ { 0x704f164d5e31e24eULL, 0x8df188d8a942e2a0ULL, },
+ { 0x886ae6cc5e31e24eULL, 0x8df188d8a942e2a0ULL, },
+ { 0x704f164d5e31e24eULL, 0x8df188d8a942e2a0ULL, },
+ { 0x704f164d5e31e24eULL, 0x8df188d8a942e2a0ULL, },
+ { 0x704f164d5e31e24eULL, 0x8df188d8a942e2a0ULL, },
+ };
+
+ gettimeofday(&start, NULL);
+
+ for (i = 0; i < PATTERN_INPUTS_SHORT_COUNT; i++) {
+ for (j = 0; j < PATTERN_INPUTS_SHORT_COUNT; j++) {
+ do_msa_MAX_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_MAX_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/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
new file mode 100644
index 0000000..ab50eee
--- /dev/null
+++ b/tests/tcg/mips/user/ase/msa/int-max-min/test_msa_max_s_b.c
@@ -0,0 +1,153 @@
+/*
+ * Test program for MSA instruction MAX_S.B
+ *
+ * Copyright (C) 2018 Wave Computing, Inc.
+ * Copyright (C) 2018 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.h"
+#include "../../../../include/test_utils.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 = "MAX_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] = {
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 0 */
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0x5555555555555555ULL, 0x5555555555555555ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0x3333333333333333ULL, 0x3333333333333333ULL, },
+ { 0xffff38ffff38ffffULL, 0x38ffff38ffff38ffULL, },
+ { 0x1c71ff1c71ff1c71ULL, 0xff1c71ff1c71ff1cULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, }, /* 8 */
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x5555555555555555ULL, 0x5555555555555555ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x3333333333333333ULL, 0x3333333333333333ULL, },
+ { 0x0000380000380000ULL, 0x3800003800003800ULL, },
+ { 0x1c71001c71001c71ULL, 0x001c71001c71001cULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 16 */
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, },
+ { 0x5555555555555555ULL, 0x5555555555555555ULL, },
+ { 0xccccccccccccccccULL, 0xccccccccccccccccULL, },
+ { 0x3333333333333333ULL, 0x3333333333333333ULL, },
+ { 0xe3aa38e3aa38e3aaULL, 0x38e3aa38e3aa38e3ULL, },
+ { 0x1c71c71c71c71c71ULL, 0xc71c71c71c71c71cULL, },
+ { 0x5555555555555555ULL, 0x5555555555555555ULL, }, /* 24 */
+ { 0x5555555555555555ULL, 0x5555555555555555ULL, },
+ { 0x5555555555555555ULL, 0x5555555555555555ULL, },
+ { 0x5555555555555555ULL, 0x5555555555555555ULL, },
+ { 0x5555555555555555ULL, 0x5555555555555555ULL, },
+ { 0x5555555555555555ULL, 0x5555555555555555ULL, },
+ { 0x5555555555555555ULL, 0x5555555555555555ULL, },
+ { 0x5571555571555571ULL, 0x5555715555715555ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 32 */
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xccccccccccccccccULL, 0xccccccccccccccccULL, },
+ { 0x5555555555555555ULL, 0x5555555555555555ULL, },
+ { 0xccccccccccccccccULL, 0xccccccccccccccccULL, },
+ { 0x3333333333333333ULL, 0x3333333333333333ULL, },
+ { 0xe3cc38e3cc38e3ccULL, 0x38e3cc38e3cc38e3ULL, },
+ { 0x1c71cc1c71cc1c71ULL, 0xcc1c71cc1c71cc1cULL, },
+ { 0x3333333333333333ULL, 0x3333333333333333ULL, }, /* 40 */
+ { 0x3333333333333333ULL, 0x3333333333333333ULL, },
+ { 0x3333333333333333ULL, 0x3333333333333333ULL, },
+ { 0x5555555555555555ULL, 0x5555555555555555ULL, },
+ { 0x3333333333333333ULL, 0x3333333333333333ULL, },
+ { 0x3333333333333333ULL, 0x3333333333333333ULL, },
+ { 0x3333383333383333ULL, 0x3833333833333833ULL, },
+ { 0x3371333371333371ULL, 0x3333713333713333ULL, },
+ { 0xffff38ffff38ffffULL, 0x38ffff38ffff38ffULL, }, /* 48 */
+ { 0x0000380000380000ULL, 0x3800003800003800ULL, },
+ { 0xe3aa38e3aa38e3aaULL, 0x38e3aa38e3aa38e3ULL, },
+ { 0x5555555555555555ULL, 0x5555555555555555ULL, },
+ { 0xe3cc38e3cc38e3ccULL, 0x38e3cc38e3cc38e3ULL, },
+ { 0x3333383333383333ULL, 0x3833333833333833ULL, },
+ { 0xe38e38e38e38e38eULL, 0x38e38e38e38e38e3ULL, },
+ { 0x1c71381c71381c71ULL, 0x381c71381c71381cULL, },
+ { 0x1c71ff1c71ff1c71ULL, 0xff1c71ff1c71ff1cULL, }, /* 56 */
+ { 0x1c71001c71001c71ULL, 0x001c71001c71001cULL, },
+ { 0x1c71c71c71c71c71ULL, 0xc71c71c71c71c71cULL, },
+ { 0x5571555571555571ULL, 0x5555715555715555ULL, },
+ { 0x1c71cc1c71cc1c71ULL, 0xcc1c71cc1c71cc1cULL, },
+ { 0x3371333371333371ULL, 0x3333713333713333ULL, },
+ { 0x1c71381c71381c71ULL, 0x381c71381c71381cULL, },
+ { 0x1c71c71c71c71c71ULL, 0xc71c71c71c71c71cULL, },
+ { 0x886ae6cc28625540ULL, 0x4b670b5efe7bb00cULL, }, /* 64 */
+ { 0xfb6a00634d625540ULL, 0x4b670b5e157b520cULL, },
+ { 0xac6ae6cc28625540ULL, 0x4b670b5efe7b2514ULL, },
+ { 0x706a164d5e62554eULL, 0x4b670b5efe7be20cULL, },
+ { 0xfb6a00634d625540ULL, 0x4b670b5e157b520cULL, },
+ { 0xfbbe00634d93c708ULL, 0x12f7bb1a153f52fcULL, },
+ { 0xfb5a00634dcfc708ULL, 0x27f7c61a153f5214ULL, },
+ { 0x704f16635e31e24eULL, 0x12f7bb1a154252fcULL, },
+ { 0xac6ae6cc28625540ULL, 0x4b670b5efe7b2514ULL, }, /* 72 */
+ { 0xfb5a00634dcfc708ULL, 0x27f7c61a153f5214ULL, },
+ { 0xac5aaeaab9cf8b80ULL, 0x27d8c6ffab2b2514ULL, },
+ { 0x705a164d5e31e24eULL, 0x27f1c6ffab422514ULL, },
+ { 0x706a164d5e62554eULL, 0x4b670b5efe7be20cULL, },
+ { 0x704f16635e31e24eULL, 0x12f7bb1a154252fcULL, },
+ { 0x705a164d5e31e24eULL, 0x27f1c6ffab422514ULL, },
+ { 0x704f164d5e31e24eULL, 0x8df188d8a942e2a0ULL, },
+ };
+
+ gettimeofday(&start, NULL);
+
+ for (i = 0; i < PATTERN_INPUTS_SHORT_COUNT; i++) {
+ for (j = 0; j < PATTERN_INPUTS_SHORT_COUNT; j++) {
+ do_msa_MAX_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_MAX_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-max-min/test_msa_max_s_d.c b/tests/tcg/mips/user/ase/msa/int-max-min/test_msa_max_s_d.c
new file mode 100644
index 0000000..2957db4
--- /dev/null
+++ b/tests/tcg/mips/user/ase/msa/int-max-min/test_msa_max_s_d.c
@@ -0,0 +1,153 @@
+/*
+ * Test program for MSA instruction MAX_S.D
+ *
+ * Copyright (C) 2018 Wave Computing, Inc.
+ * Copyright (C) 2018 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.h"
+#include "../../../../include/test_utils.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 = "MAX_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] = {
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 0 */
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0x5555555555555555ULL, 0x5555555555555555ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0x3333333333333333ULL, 0x3333333333333333ULL, },
+ { 0xffffffffffffffffULL, 0x38e38e38e38e38e3ULL, },
+ { 0x1c71c71c71c71c71ULL, 0xffffffffffffffffULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, }, /* 8 */
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x5555555555555555ULL, 0x5555555555555555ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x3333333333333333ULL, 0x3333333333333333ULL, },
+ { 0x0000000000000000ULL, 0x38e38e38e38e38e3ULL, },
+ { 0x1c71c71c71c71c71ULL, 0x0000000000000000ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 16 */
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, },
+ { 0x5555555555555555ULL, 0x5555555555555555ULL, },
+ { 0xccccccccccccccccULL, 0xccccccccccccccccULL, },
+ { 0x3333333333333333ULL, 0x3333333333333333ULL, },
+ { 0xe38e38e38e38e38eULL, 0x38e38e38e38e38e3ULL, },
+ { 0x1c71c71c71c71c71ULL, 0xc71c71c71c71c71cULL, },
+ { 0x5555555555555555ULL, 0x5555555555555555ULL, }, /* 24 */
+ { 0x5555555555555555ULL, 0x5555555555555555ULL, },
+ { 0x5555555555555555ULL, 0x5555555555555555ULL, },
+ { 0x5555555555555555ULL, 0x5555555555555555ULL, },
+ { 0x5555555555555555ULL, 0x5555555555555555ULL, },
+ { 0x5555555555555555ULL, 0x5555555555555555ULL, },
+ { 0x5555555555555555ULL, 0x5555555555555555ULL, },
+ { 0x5555555555555555ULL, 0x5555555555555555ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 32 */
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xccccccccccccccccULL, 0xccccccccccccccccULL, },
+ { 0x5555555555555555ULL, 0x5555555555555555ULL, },
+ { 0xccccccccccccccccULL, 0xccccccccccccccccULL, },
+ { 0x3333333333333333ULL, 0x3333333333333333ULL, },
+ { 0xe38e38e38e38e38eULL, 0x38e38e38e38e38e3ULL, },
+ { 0x1c71c71c71c71c71ULL, 0xccccccccccccccccULL, },
+ { 0x3333333333333333ULL, 0x3333333333333333ULL, }, /* 40 */
+ { 0x3333333333333333ULL, 0x3333333333333333ULL, },
+ { 0x3333333333333333ULL, 0x3333333333333333ULL, },
+ { 0x5555555555555555ULL, 0x5555555555555555ULL, },
+ { 0x3333333333333333ULL, 0x3333333333333333ULL, },
+ { 0x3333333333333333ULL, 0x3333333333333333ULL, },
+ { 0x3333333333333333ULL, 0x38e38e38e38e38e3ULL, },
+ { 0x3333333333333333ULL, 0x3333333333333333ULL, },
+ { 0xffffffffffffffffULL, 0x38e38e38e38e38e3ULL, }, /* 48 */
+ { 0x0000000000000000ULL, 0x38e38e38e38e38e3ULL, },
+ { 0xe38e38e38e38e38eULL, 0x38e38e38e38e38e3ULL, },
+ { 0x5555555555555555ULL, 0x5555555555555555ULL, },
+ { 0xe38e38e38e38e38eULL, 0x38e38e38e38e38e3ULL, },
+ { 0x3333333333333333ULL, 0x38e38e38e38e38e3ULL, },
+ { 0xe38e38e38e38e38eULL, 0x38e38e38e38e38e3ULL, },
+ { 0x1c71c71c71c71c71ULL, 0x38e38e38e38e38e3ULL, },
+ { 0x1c71c71c71c71c71ULL, 0xffffffffffffffffULL, }, /* 56 */
+ { 0x1c71c71c71c71c71ULL, 0x0000000000000000ULL, },
+ { 0x1c71c71c71c71c71ULL, 0xc71c71c71c71c71cULL, },
+ { 0x5555555555555555ULL, 0x5555555555555555ULL, },
+ { 0x1c71c71c71c71c71ULL, 0xccccccccccccccccULL, },
+ { 0x3333333333333333ULL, 0x3333333333333333ULL, },
+ { 0x1c71c71c71c71c71ULL, 0x38e38e38e38e38e3ULL, },
+ { 0x1c71c71c71c71c71ULL, 0xc71c71c71c71c71cULL, },
+ { 0x886ae6cc28625540ULL, 0x4b670b5efe7bb00cULL, }, /* 64 */
+ { 0xfbbe00634d93c708ULL, 0x4b670b5efe7bb00cULL, },
+ { 0xac5aaeaab9cf8b80ULL, 0x4b670b5efe7bb00cULL, },
+ { 0x704f164d5e31e24eULL, 0x4b670b5efe7bb00cULL, },
+ { 0xfbbe00634d93c708ULL, 0x4b670b5efe7bb00cULL, },
+ { 0xfbbe00634d93c708ULL, 0x12f7bb1a153f52fcULL, },
+ { 0xfbbe00634d93c708ULL, 0x27d8c6ffab2b2514ULL, },
+ { 0x704f164d5e31e24eULL, 0x12f7bb1a153f52fcULL, },
+ { 0xac5aaeaab9cf8b80ULL, 0x4b670b5efe7bb00cULL, }, /* 72 */
+ { 0xfbbe00634d93c708ULL, 0x27d8c6ffab2b2514ULL, },
+ { 0xac5aaeaab9cf8b80ULL, 0x27d8c6ffab2b2514ULL, },
+ { 0x704f164d5e31e24eULL, 0x27d8c6ffab2b2514ULL, },
+ { 0x704f164d5e31e24eULL, 0x4b670b5efe7bb00cULL, },
+ { 0x704f164d5e31e24eULL, 0x12f7bb1a153f52fcULL, },
+ { 0x704f164d5e31e24eULL, 0x27d8c6ffab2b2514ULL, },
+ { 0x704f164d5e31e24eULL, 0x8df188d8a942e2a0ULL, },
+ };
+
+ gettimeofday(&start, NULL);
+
+ for (i = 0; i < PATTERN_INPUTS_SHORT_COUNT; i++) {
+ for (j = 0; j < PATTERN_INPUTS_SHORT_COUNT; j++) {
+ do_msa_MAX_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_MAX_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-max-min/test_msa_max_s_h.c b/tests/tcg/mips/user/ase/msa/int-max-min/test_msa_max_s_h.c
new file mode 100644
index 0000000..e101764
--- /dev/null
+++ b/tests/tcg/mips/user/ase/msa/int-max-min/test_msa_max_s_h.c
@@ -0,0 +1,153 @@
+/*
+ * Test program for MSA instruction MAX_S.H
+ *
+ * Copyright (C) 2018 Wave Computing, Inc.
+ * Copyright (C) 2018 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.h"
+#include "../../../../include/test_utils.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 = "MAX_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] = {
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 0 */
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0x5555555555555555ULL, 0x5555555555555555ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0x3333333333333333ULL, 0x3333333333333333ULL, },
+ { 0xffff38e3ffffffffULL, 0x38e3ffffffff38e3ULL, },
+ { 0x1c71ffff71c71c71ULL, 0xffff71c71c71ffffULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, }, /* 8 */
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x5555555555555555ULL, 0x5555555555555555ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x3333333333333333ULL, 0x3333333333333333ULL, },
+ { 0x000038e300000000ULL, 0x38e30000000038e3ULL, },
+ { 0x1c71000071c71c71ULL, 0x000071c71c710000ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 16 */
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, },
+ { 0x5555555555555555ULL, 0x5555555555555555ULL, },
+ { 0xccccccccccccccccULL, 0xccccccccccccccccULL, },
+ { 0x3333333333333333ULL, 0x3333333333333333ULL, },
+ { 0xe38e38e3aaaae38eULL, 0x38e3aaaae38e38e3ULL, },
+ { 0x1c71c71c71c71c71ULL, 0xc71c71c71c71c71cULL, },
+ { 0x5555555555555555ULL, 0x5555555555555555ULL, }, /* 24 */
+ { 0x5555555555555555ULL, 0x5555555555555555ULL, },
+ { 0x5555555555555555ULL, 0x5555555555555555ULL, },
+ { 0x5555555555555555ULL, 0x5555555555555555ULL, },
+ { 0x5555555555555555ULL, 0x5555555555555555ULL, },
+ { 0x5555555555555555ULL, 0x5555555555555555ULL, },
+ { 0x5555555555555555ULL, 0x5555555555555555ULL, },
+ { 0x5555555571c75555ULL, 0x555571c755555555ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 32 */
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xccccccccccccccccULL, 0xccccccccccccccccULL, },
+ { 0x5555555555555555ULL, 0x5555555555555555ULL, },
+ { 0xccccccccccccccccULL, 0xccccccccccccccccULL, },
+ { 0x3333333333333333ULL, 0x3333333333333333ULL, },
+ { 0xe38e38e3cccce38eULL, 0x38e3cccce38e38e3ULL, },
+ { 0x1c71cccc71c71c71ULL, 0xcccc71c71c71ccccULL, },
+ { 0x3333333333333333ULL, 0x3333333333333333ULL, }, /* 40 */
+ { 0x3333333333333333ULL, 0x3333333333333333ULL, },
+ { 0x3333333333333333ULL, 0x3333333333333333ULL, },
+ { 0x5555555555555555ULL, 0x5555555555555555ULL, },
+ { 0x3333333333333333ULL, 0x3333333333333333ULL, },
+ { 0x3333333333333333ULL, 0x3333333333333333ULL, },
+ { 0x333338e333333333ULL, 0x38e33333333338e3ULL, },
+ { 0x3333333371c73333ULL, 0x333371c733333333ULL, },
+ { 0xffff38e3ffffffffULL, 0x38e3ffffffff38e3ULL, }, /* 48 */
+ { 0x000038e300000000ULL, 0x38e30000000038e3ULL, },
+ { 0xe38e38e3aaaae38eULL, 0x38e3aaaae38e38e3ULL, },
+ { 0x5555555555555555ULL, 0x5555555555555555ULL, },
+ { 0xe38e38e3cccce38eULL, 0x38e3cccce38e38e3ULL, },
+ { 0x333338e333333333ULL, 0x38e33333333338e3ULL, },
+ { 0xe38e38e38e38e38eULL, 0x38e38e38e38e38e3ULL, },
+ { 0x1c7138e371c71c71ULL, 0x38e371c71c7138e3ULL, },
+ { 0x1c71ffff71c71c71ULL, 0xffff71c71c71ffffULL, }, /* 56 */
+ { 0x1c71000071c71c71ULL, 0x000071c71c710000ULL, },
+ { 0x1c71c71c71c71c71ULL, 0xc71c71c71c71c71cULL, },
+ { 0x5555555571c75555ULL, 0x555571c755555555ULL, },
+ { 0x1c71cccc71c71c71ULL, 0xcccc71c71c71ccccULL, },
+ { 0x3333333371c73333ULL, 0x333371c733333333ULL, },
+ { 0x1c7138e371c71c71ULL, 0x38e371c71c7138e3ULL, },
+ { 0x1c71c71c71c71c71ULL, 0xc71c71c71c71c71cULL, },
+ { 0x886ae6cc28625540ULL, 0x4b670b5efe7bb00cULL, }, /* 64 */
+ { 0xfbbe00634d935540ULL, 0x4b670b5e153f52fcULL, },
+ { 0xac5ae6cc28625540ULL, 0x4b670b5efe7b2514ULL, },
+ { 0x704f164d5e315540ULL, 0x4b670b5efe7be2a0ULL, },
+ { 0xfbbe00634d935540ULL, 0x4b670b5e153f52fcULL, },
+ { 0xfbbe00634d93c708ULL, 0x12f7bb1a153f52fcULL, },
+ { 0xfbbe00634d93c708ULL, 0x27d8c6ff153f52fcULL, },
+ { 0x704f164d5e31e24eULL, 0x12f7bb1a153f52fcULL, },
+ { 0xac5ae6cc28625540ULL, 0x4b670b5efe7b2514ULL, }, /* 72 */
+ { 0xfbbe00634d93c708ULL, 0x27d8c6ff153f52fcULL, },
+ { 0xac5aaeaab9cf8b80ULL, 0x27d8c6ffab2b2514ULL, },
+ { 0x704f164d5e31e24eULL, 0x27d8c6ffab2b2514ULL, },
+ { 0x704f164d5e315540ULL, 0x4b670b5efe7be2a0ULL, },
+ { 0x704f164d5e31e24eULL, 0x12f7bb1a153f52fcULL, },
+ { 0x704f164d5e31e24eULL, 0x27d8c6ffab2b2514ULL, },
+ { 0x704f164d5e31e24eULL, 0x8df188d8a942e2a0ULL, },
+ };
+
+ gettimeofday(&start, NULL);
+
+ for (i = 0; i < PATTERN_INPUTS_SHORT_COUNT; i++) {
+ for (j = 0; j < PATTERN_INPUTS_SHORT_COUNT; j++) {
+ do_msa_MAX_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_MAX_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-max-min/test_msa_max_s_w.c b/tests/tcg/mips/user/ase/msa/int-max-min/test_msa_max_s_w.c
new file mode 100644
index 0000000..119f03f
--- /dev/null
+++ b/tests/tcg/mips/user/ase/msa/int-max-min/test_msa_max_s_w.c
@@ -0,0 +1,153 @@
+/*
+ * Test program for MSA instruction MAX_S.W
+ *
+ * Copyright (C) 2018 Wave Computing, Inc.
+ * Copyright (C) 2018 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.h"
+#include "../../../../include/test_utils.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 = "MAX_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] = {
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 0 */
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0x5555555555555555ULL, 0x5555555555555555ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0x3333333333333333ULL, 0x3333333333333333ULL, },
+ { 0xffffffffffffffffULL, 0x38e38e38ffffffffULL, },
+ { 0x1c71c71c71c71c71ULL, 0xffffffff1c71c71cULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, }, /* 8 */
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x5555555555555555ULL, 0x5555555555555555ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x3333333333333333ULL, 0x3333333333333333ULL, },
+ { 0x0000000000000000ULL, 0x38e38e3800000000ULL, },
+ { 0x1c71c71c71c71c71ULL, 0x000000001c71c71cULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 16 */
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, },
+ { 0x5555555555555555ULL, 0x5555555555555555ULL, },
+ { 0xccccccccccccccccULL, 0xccccccccccccccccULL, },
+ { 0x3333333333333333ULL, 0x3333333333333333ULL, },
+ { 0xe38e38e3aaaaaaaaULL, 0x38e38e38e38e38e3ULL, },
+ { 0x1c71c71c71c71c71ULL, 0xc71c71c71c71c71cULL, },
+ { 0x5555555555555555ULL, 0x5555555555555555ULL, }, /* 24 */
+ { 0x5555555555555555ULL, 0x5555555555555555ULL, },
+ { 0x5555555555555555ULL, 0x5555555555555555ULL, },
+ { 0x5555555555555555ULL, 0x5555555555555555ULL, },
+ { 0x5555555555555555ULL, 0x5555555555555555ULL, },
+ { 0x5555555555555555ULL, 0x5555555555555555ULL, },
+ { 0x5555555555555555ULL, 0x5555555555555555ULL, },
+ { 0x5555555571c71c71ULL, 0x5555555555555555ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 32 */
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xccccccccccccccccULL, 0xccccccccccccccccULL, },
+ { 0x5555555555555555ULL, 0x5555555555555555ULL, },
+ { 0xccccccccccccccccULL, 0xccccccccccccccccULL, },
+ { 0x3333333333333333ULL, 0x3333333333333333ULL, },
+ { 0xe38e38e3ccccccccULL, 0x38e38e38e38e38e3ULL, },
+ { 0x1c71c71c71c71c71ULL, 0xcccccccc1c71c71cULL, },
+ { 0x3333333333333333ULL, 0x3333333333333333ULL, }, /* 40 */
+ { 0x3333333333333333ULL, 0x3333333333333333ULL, },
+ { 0x3333333333333333ULL, 0x3333333333333333ULL, },
+ { 0x5555555555555555ULL, 0x5555555555555555ULL, },
+ { 0x3333333333333333ULL, 0x3333333333333333ULL, },
+ { 0x3333333333333333ULL, 0x3333333333333333ULL, },
+ { 0x3333333333333333ULL, 0x38e38e3833333333ULL, },
+ { 0x3333333371c71c71ULL, 0x3333333333333333ULL, },
+ { 0xffffffffffffffffULL, 0x38e38e38ffffffffULL, }, /* 48 */
+ { 0x0000000000000000ULL, 0x38e38e3800000000ULL, },
+ { 0xe38e38e3aaaaaaaaULL, 0x38e38e38e38e38e3ULL, },
+ { 0x5555555555555555ULL, 0x5555555555555555ULL, },
+ { 0xe38e38e3ccccccccULL, 0x38e38e38e38e38e3ULL, },
+ { 0x3333333333333333ULL, 0x38e38e3833333333ULL, },
+ { 0xe38e38e38e38e38eULL, 0x38e38e38e38e38e3ULL, },
+ { 0x1c71c71c71c71c71ULL, 0x38e38e381c71c71cULL, },
+ { 0x1c71c71c71c71c71ULL, 0xffffffff1c71c71cULL, }, /* 56 */
+ { 0x1c71c71c71c71c71ULL, 0x000000001c71c71cULL, },
+ { 0x1c71c71c71c71c71ULL, 0xc71c71c71c71c71cULL, },
+ { 0x5555555571c71c71ULL, 0x5555555555555555ULL, },
+ { 0x1c71c71c71c71c71ULL, 0xcccccccc1c71c71cULL, },
+ { 0x3333333371c71c71ULL, 0x3333333333333333ULL, },
+ { 0x1c71c71c71c71c71ULL, 0x38e38e381c71c71cULL, },
+ { 0x1c71c71c71c71c71ULL, 0xc71c71c71c71c71cULL, },
+ { 0x886ae6cc28625540ULL, 0x4b670b5efe7bb00cULL, }, /* 64 */
+ { 0xfbbe00634d93c708ULL, 0x4b670b5e153f52fcULL, },
+ { 0xac5aaeaa28625540ULL, 0x4b670b5efe7bb00cULL, },
+ { 0x704f164d5e31e24eULL, 0x4b670b5efe7bb00cULL, },
+ { 0xfbbe00634d93c708ULL, 0x4b670b5e153f52fcULL, },
+ { 0xfbbe00634d93c708ULL, 0x12f7bb1a153f52fcULL, },
+ { 0xfbbe00634d93c708ULL, 0x27d8c6ff153f52fcULL, },
+ { 0x704f164d5e31e24eULL, 0x12f7bb1a153f52fcULL, },
+ { 0xac5aaeaa28625540ULL, 0x4b670b5efe7bb00cULL, }, /* 72 */
+ { 0xfbbe00634d93c708ULL, 0x27d8c6ff153f52fcULL, },
+ { 0xac5aaeaab9cf8b80ULL, 0x27d8c6ffab2b2514ULL, },
+ { 0x704f164d5e31e24eULL, 0x27d8c6ffab2b2514ULL, },
+ { 0x704f164d5e31e24eULL, 0x4b670b5efe7bb00cULL, },
+ { 0x704f164d5e31e24eULL, 0x12f7bb1a153f52fcULL, },
+ { 0x704f164d5e31e24eULL, 0x27d8c6ffab2b2514ULL, },
+ { 0x704f164d5e31e24eULL, 0x8df188d8a942e2a0ULL, },
+ };
+
+ gettimeofday(&start, NULL);
+
+ for (i = 0; i < PATTERN_INPUTS_SHORT_COUNT; i++) {
+ for (j = 0; j < PATTERN_INPUTS_SHORT_COUNT; j++) {
+ do_msa_MAX_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_MAX_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-max-min/test_msa_max_u_b.c b/tests/tcg/mips/user/ase/msa/int-max-min/test_msa_max_u_b.c
new file mode 100644
index 0000000..d18b6bf
--- /dev/null
+++ b/tests/tcg/mips/user/ase/msa/int-max-min/test_msa_max_u_b.c
@@ -0,0 +1,153 @@
+/*
+ * Test program for MSA instruction MAX_U.B
+ *
+ * Copyright (C) 2018 Wave Computing, Inc.
+ * Copyright (C) 2018 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.h"
+#include "../../../../include/test_utils.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 = "MAX_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] = {
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 0 */
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 8 */
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, },
+ { 0x5555555555555555ULL, 0x5555555555555555ULL, },
+ { 0xccccccccccccccccULL, 0xccccccccccccccccULL, },
+ { 0x3333333333333333ULL, 0x3333333333333333ULL, },
+ { 0xe38e38e38e38e38eULL, 0x38e38e38e38e38e3ULL, },
+ { 0x1c71c71c71c71c71ULL, 0xc71c71c71c71c71cULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 16 */
+ { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, },
+ { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, },
+ { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, },
+ { 0xccccccccccccccccULL, 0xccccccccccccccccULL, },
+ { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, },
+ { 0xe3aaaae3aaaae3aaULL, 0xaae3aaaae3aaaae3ULL, },
+ { 0xaaaac7aaaac7aaaaULL, 0xc7aaaac7aaaac7aaULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 24 */
+ { 0x5555555555555555ULL, 0x5555555555555555ULL, },
+ { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, },
+ { 0x5555555555555555ULL, 0x5555555555555555ULL, },
+ { 0xccccccccccccccccULL, 0xccccccccccccccccULL, },
+ { 0x5555555555555555ULL, 0x5555555555555555ULL, },
+ { 0xe38e55e38e55e38eULL, 0x55e38e55e38e55e3ULL, },
+ { 0x5571c75571c75571ULL, 0xc75571c75571c755ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 32 */
+ { 0xccccccccccccccccULL, 0xccccccccccccccccULL, },
+ { 0xccccccccccccccccULL, 0xccccccccccccccccULL, },
+ { 0xccccccccccccccccULL, 0xccccccccccccccccULL, },
+ { 0xccccccccccccccccULL, 0xccccccccccccccccULL, },
+ { 0xccccccccccccccccULL, 0xccccccccccccccccULL, },
+ { 0xe3cccce3cccce3ccULL, 0xcce3cccce3cccce3ULL, },
+ { 0xccccccccccccccccULL, 0xccccccccccccccccULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 40 */
+ { 0x3333333333333333ULL, 0x3333333333333333ULL, },
+ { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, },
+ { 0x5555555555555555ULL, 0x5555555555555555ULL, },
+ { 0xccccccccccccccccULL, 0xccccccccccccccccULL, },
+ { 0x3333333333333333ULL, 0x3333333333333333ULL, },
+ { 0xe38e38e38e38e38eULL, 0x38e38e38e38e38e3ULL, },
+ { 0x3371c73371c73371ULL, 0xc73371c73371c733ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 48 */
+ { 0xe38e38e38e38e38eULL, 0x38e38e38e38e38e3ULL, },
+ { 0xe3aaaae3aaaae3aaULL, 0xaae3aaaae3aaaae3ULL, },
+ { 0xe38e55e38e55e38eULL, 0x55e38e55e38e55e3ULL, },
+ { 0xe3cccce3cccce3ccULL, 0xcce3cccce3cccce3ULL, },
+ { 0xe38e38e38e38e38eULL, 0x38e38e38e38e38e3ULL, },
+ { 0xe38e38e38e38e38eULL, 0x38e38e38e38e38e3ULL, },
+ { 0xe38ec7e38ec7e38eULL, 0xc7e38ec7e38ec7e3ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 56 */
+ { 0x1c71c71c71c71c71ULL, 0xc71c71c71c71c71cULL, },
+ { 0xaaaac7aaaac7aaaaULL, 0xc7aaaac7aaaac7aaULL, },
+ { 0x5571c75571c75571ULL, 0xc75571c75571c755ULL, },
+ { 0xccccccccccccccccULL, 0xccccccccccccccccULL, },
+ { 0x3371c73371c73371ULL, 0xc73371c73371c733ULL, },
+ { 0xe38ec7e38ec7e38eULL, 0xc7e38ec7e38ec7e3ULL, },
+ { 0x1c71c71c71c71c71ULL, 0xc71c71c71c71c71cULL, },
+ { 0x886ae6cc28625540ULL, 0x4b670b5efe7bb00cULL, }, /* 64 */
+ { 0xfbbee6cc4d93c740ULL, 0x4bf7bb5efe7bb0fcULL, },
+ { 0xac6ae6ccb9cf8b80ULL, 0x4bd8c6fffe7bb014ULL, },
+ { 0x886ae6cc5e62e24eULL, 0x8df188d8fe7be2a0ULL, },
+ { 0xfbbee6cc4d93c740ULL, 0x4bf7bb5efe7bb0fcULL, },
+ { 0xfbbe00634d93c708ULL, 0x12f7bb1a153f52fcULL, },
+ { 0xfbbeaeaab9cfc780ULL, 0x27f7c6ffab3f52fcULL, },
+ { 0xfbbe16635e93e24eULL, 0x8df7bbd8a942e2fcULL, },
+ { 0xac6ae6ccb9cf8b80ULL, 0x4bd8c6fffe7bb014ULL, }, /* 72 */
+ { 0xfbbeaeaab9cfc780ULL, 0x27f7c6ffab3f52fcULL, },
+ { 0xac5aaeaab9cf8b80ULL, 0x27d8c6ffab2b2514ULL, },
+ { 0xac5aaeaab9cfe280ULL, 0x8df1c6ffab42e2a0ULL, },
+ { 0x886ae6cc5e62e24eULL, 0x8df188d8fe7be2a0ULL, },
+ { 0xfbbe16635e93e24eULL, 0x8df7bbd8a942e2fcULL, },
+ { 0xac5aaeaab9cfe280ULL, 0x8df1c6ffab42e2a0ULL, },
+ { 0x704f164d5e31e24eULL, 0x8df188d8a942e2a0ULL, },
+ };
+
+ gettimeofday(&start, NULL);
+
+ for (i = 0; i < PATTERN_INPUTS_SHORT_COUNT; i++) {
+ for (j = 0; j < PATTERN_INPUTS_SHORT_COUNT; j++) {
+ do_msa_MAX_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_MAX_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-max-min/test_msa_max_u_d.c b/tests/tcg/mips/user/ase/msa/int-max-min/test_msa_max_u_d.c
new file mode 100644
index 0000000..1396e74
--- /dev/null
+++ b/tests/tcg/mips/user/ase/msa/int-max-min/test_msa_max_u_d.c
@@ -0,0 +1,153 @@
+/*
+ * Test program for MSA instruction MAX_U.D
+ *
+ * Copyright (C) 2018 Wave Computing, Inc.
+ * Copyright (C) 2018 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.h"
+#include "../../../../include/test_utils.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 = "MAX_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] = {
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 0 */
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 8 */
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, },
+ { 0x5555555555555555ULL, 0x5555555555555555ULL, },
+ { 0xccccccccccccccccULL, 0xccccccccccccccccULL, },
+ { 0x3333333333333333ULL, 0x3333333333333333ULL, },
+ { 0xe38e38e38e38e38eULL, 0x38e38e38e38e38e3ULL, },
+ { 0x1c71c71c71c71c71ULL, 0xc71c71c71c71c71cULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 16 */
+ { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, },
+ { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, },
+ { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, },
+ { 0xccccccccccccccccULL, 0xccccccccccccccccULL, },
+ { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, },
+ { 0xe38e38e38e38e38eULL, 0xaaaaaaaaaaaaaaaaULL, },
+ { 0xaaaaaaaaaaaaaaaaULL, 0xc71c71c71c71c71cULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 24 */
+ { 0x5555555555555555ULL, 0x5555555555555555ULL, },
+ { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, },
+ { 0x5555555555555555ULL, 0x5555555555555555ULL, },
+ { 0xccccccccccccccccULL, 0xccccccccccccccccULL, },
+ { 0x5555555555555555ULL, 0x5555555555555555ULL, },
+ { 0xe38e38e38e38e38eULL, 0x5555555555555555ULL, },
+ { 0x5555555555555555ULL, 0xc71c71c71c71c71cULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 32 */
+ { 0xccccccccccccccccULL, 0xccccccccccccccccULL, },
+ { 0xccccccccccccccccULL, 0xccccccccccccccccULL, },
+ { 0xccccccccccccccccULL, 0xccccccccccccccccULL, },
+ { 0xccccccccccccccccULL, 0xccccccccccccccccULL, },
+ { 0xccccccccccccccccULL, 0xccccccccccccccccULL, },
+ { 0xe38e38e38e38e38eULL, 0xccccccccccccccccULL, },
+ { 0xccccccccccccccccULL, 0xccccccccccccccccULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 40 */
+ { 0x3333333333333333ULL, 0x3333333333333333ULL, },
+ { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, },
+ { 0x5555555555555555ULL, 0x5555555555555555ULL, },
+ { 0xccccccccccccccccULL, 0xccccccccccccccccULL, },
+ { 0x3333333333333333ULL, 0x3333333333333333ULL, },
+ { 0xe38e38e38e38e38eULL, 0x38e38e38e38e38e3ULL, },
+ { 0x3333333333333333ULL, 0xc71c71c71c71c71cULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 48 */
+ { 0xe38e38e38e38e38eULL, 0x38e38e38e38e38e3ULL, },
+ { 0xe38e38e38e38e38eULL, 0xaaaaaaaaaaaaaaaaULL, },
+ { 0xe38e38e38e38e38eULL, 0x5555555555555555ULL, },
+ { 0xe38e38e38e38e38eULL, 0xccccccccccccccccULL, },
+ { 0xe38e38e38e38e38eULL, 0x38e38e38e38e38e3ULL, },
+ { 0xe38e38e38e38e38eULL, 0x38e38e38e38e38e3ULL, },
+ { 0xe38e38e38e38e38eULL, 0xc71c71c71c71c71cULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 56 */
+ { 0x1c71c71c71c71c71ULL, 0xc71c71c71c71c71cULL, },
+ { 0xaaaaaaaaaaaaaaaaULL, 0xc71c71c71c71c71cULL, },
+ { 0x5555555555555555ULL, 0xc71c71c71c71c71cULL, },
+ { 0xccccccccccccccccULL, 0xccccccccccccccccULL, },
+ { 0x3333333333333333ULL, 0xc71c71c71c71c71cULL, },
+ { 0xe38e38e38e38e38eULL, 0xc71c71c71c71c71cULL, },
+ { 0x1c71c71c71c71c71ULL, 0xc71c71c71c71c71cULL, },
+ { 0x886ae6cc28625540ULL, 0x4b670b5efe7bb00cULL, }, /* 64 */
+ { 0xfbbe00634d93c708ULL, 0x4b670b5efe7bb00cULL, },
+ { 0xac5aaeaab9cf8b80ULL, 0x4b670b5efe7bb00cULL, },
+ { 0x886ae6cc28625540ULL, 0x8df188d8a942e2a0ULL, },
+ { 0xfbbe00634d93c708ULL, 0x4b670b5efe7bb00cULL, },
+ { 0xfbbe00634d93c708ULL, 0x12f7bb1a153f52fcULL, },
+ { 0xfbbe00634d93c708ULL, 0x27d8c6ffab2b2514ULL, },
+ { 0xfbbe00634d93c708ULL, 0x8df188d8a942e2a0ULL, },
+ { 0xac5aaeaab9cf8b80ULL, 0x4b670b5efe7bb00cULL, }, /* 72 */
+ { 0xfbbe00634d93c708ULL, 0x27d8c6ffab2b2514ULL, },
+ { 0xac5aaeaab9cf8b80ULL, 0x27d8c6ffab2b2514ULL, },
+ { 0xac5aaeaab9cf8b80ULL, 0x8df188d8a942e2a0ULL, },
+ { 0x886ae6cc28625540ULL, 0x8df188d8a942e2a0ULL, },
+ { 0xfbbe00634d93c708ULL, 0x8df188d8a942e2a0ULL, },
+ { 0xac5aaeaab9cf8b80ULL, 0x8df188d8a942e2a0ULL, },
+ { 0x704f164d5e31e24eULL, 0x8df188d8a942e2a0ULL, },
+ };
+
+ gettimeofday(&start, NULL);
+
+ for (i = 0; i < PATTERN_INPUTS_SHORT_COUNT; i++) {
+ for (j = 0; j < PATTERN_INPUTS_SHORT_COUNT; j++) {
+ do_msa_MAX_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_MAX_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-max-min/test_msa_max_u_h.c b/tests/tcg/mips/user/ase/msa/int-max-min/test_msa_max_u_h.c
new file mode 100644
index 0000000..c7dff10
--- /dev/null
+++ b/tests/tcg/mips/user/ase/msa/int-max-min/test_msa_max_u_h.c
@@ -0,0 +1,153 @@
+/*
+ * Test program for MSA instruction MAX_U.H
+ *
+ * Copyright (C) 2018 Wave Computing, Inc.
+ * Copyright (C) 2018 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.h"
+#include "../../../../include/test_utils.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 = "MAX_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] = {
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 0 */
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 8 */
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, },
+ { 0x5555555555555555ULL, 0x5555555555555555ULL, },
+ { 0xccccccccccccccccULL, 0xccccccccccccccccULL, },
+ { 0x3333333333333333ULL, 0x3333333333333333ULL, },
+ { 0xe38e38e38e38e38eULL, 0x38e38e38e38e38e3ULL, },
+ { 0x1c71c71c71c71c71ULL, 0xc71c71c71c71c71cULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 16 */
+ { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, },
+ { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, },
+ { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, },
+ { 0xccccccccccccccccULL, 0xccccccccccccccccULL, },
+ { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, },
+ { 0xe38eaaaaaaaae38eULL, 0xaaaaaaaae38eaaaaULL, },
+ { 0xaaaac71caaaaaaaaULL, 0xc71caaaaaaaac71cULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 24 */
+ { 0x5555555555555555ULL, 0x5555555555555555ULL, },
+ { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, },
+ { 0x5555555555555555ULL, 0x5555555555555555ULL, },
+ { 0xccccccccccccccccULL, 0xccccccccccccccccULL, },
+ { 0x5555555555555555ULL, 0x5555555555555555ULL, },
+ { 0xe38e55558e38e38eULL, 0x55558e38e38e5555ULL, },
+ { 0x5555c71c71c75555ULL, 0xc71c71c75555c71cULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 32 */
+ { 0xccccccccccccccccULL, 0xccccccccccccccccULL, },
+ { 0xccccccccccccccccULL, 0xccccccccccccccccULL, },
+ { 0xccccccccccccccccULL, 0xccccccccccccccccULL, },
+ { 0xccccccccccccccccULL, 0xccccccccccccccccULL, },
+ { 0xccccccccccccccccULL, 0xccccccccccccccccULL, },
+ { 0xe38ecccccccce38eULL, 0xcccccccce38eccccULL, },
+ { 0xccccccccccccccccULL, 0xccccccccccccccccULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 40 */
+ { 0x3333333333333333ULL, 0x3333333333333333ULL, },
+ { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, },
+ { 0x5555555555555555ULL, 0x5555555555555555ULL, },
+ { 0xccccccccccccccccULL, 0xccccccccccccccccULL, },
+ { 0x3333333333333333ULL, 0x3333333333333333ULL, },
+ { 0xe38e38e38e38e38eULL, 0x38e38e38e38e38e3ULL, },
+ { 0x3333c71c71c73333ULL, 0xc71c71c73333c71cULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 48 */
+ { 0xe38e38e38e38e38eULL, 0x38e38e38e38e38e3ULL, },
+ { 0xe38eaaaaaaaae38eULL, 0xaaaaaaaae38eaaaaULL, },
+ { 0xe38e55558e38e38eULL, 0x55558e38e38e5555ULL, },
+ { 0xe38ecccccccce38eULL, 0xcccccccce38eccccULL, },
+ { 0xe38e38e38e38e38eULL, 0x38e38e38e38e38e3ULL, },
+ { 0xe38e38e38e38e38eULL, 0x38e38e38e38e38e3ULL, },
+ { 0xe38ec71c8e38e38eULL, 0xc71c8e38e38ec71cULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 56 */
+ { 0x1c71c71c71c71c71ULL, 0xc71c71c71c71c71cULL, },
+ { 0xaaaac71caaaaaaaaULL, 0xc71caaaaaaaac71cULL, },
+ { 0x5555c71c71c75555ULL, 0xc71c71c75555c71cULL, },
+ { 0xccccccccccccccccULL, 0xccccccccccccccccULL, },
+ { 0x3333c71c71c73333ULL, 0xc71c71c73333c71cULL, },
+ { 0xe38ec71c8e38e38eULL, 0xc71c8e38e38ec71cULL, },
+ { 0x1c71c71c71c71c71ULL, 0xc71c71c71c71c71cULL, },
+ { 0x886ae6cc28625540ULL, 0x4b670b5efe7bb00cULL, }, /* 64 */
+ { 0xfbbee6cc4d93c708ULL, 0x4b67bb1afe7bb00cULL, },
+ { 0xac5ae6ccb9cf8b80ULL, 0x4b67c6fffe7bb00cULL, },
+ { 0x886ae6cc5e31e24eULL, 0x8df188d8fe7be2a0ULL, },
+ { 0xfbbee6cc4d93c708ULL, 0x4b67bb1afe7bb00cULL, },
+ { 0xfbbe00634d93c708ULL, 0x12f7bb1a153f52fcULL, },
+ { 0xfbbeaeaab9cfc708ULL, 0x27d8c6ffab2b52fcULL, },
+ { 0xfbbe164d5e31e24eULL, 0x8df1bb1aa942e2a0ULL, },
+ { 0xac5ae6ccb9cf8b80ULL, 0x4b67c6fffe7bb00cULL, }, /* 72 */
+ { 0xfbbeaeaab9cfc708ULL, 0x27d8c6ffab2b52fcULL, },
+ { 0xac5aaeaab9cf8b80ULL, 0x27d8c6ffab2b2514ULL, },
+ { 0xac5aaeaab9cfe24eULL, 0x8df1c6ffab2be2a0ULL, },
+ { 0x886ae6cc5e31e24eULL, 0x8df188d8fe7be2a0ULL, },
+ { 0xfbbe164d5e31e24eULL, 0x8df1bb1aa942e2a0ULL, },
+ { 0xac5aaeaab9cfe24eULL, 0x8df1c6ffab2be2a0ULL, },
+ { 0x704f164d5e31e24eULL, 0x8df188d8a942e2a0ULL, },
+ };
+
+ gettimeofday(&start, NULL);
+
+ for (i = 0; i < PATTERN_INPUTS_SHORT_COUNT; i++) {
+ for (j = 0; j < PATTERN_INPUTS_SHORT_COUNT; j++) {
+ do_msa_MAX_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_MAX_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-max-min/test_msa_max_u_w.c b/tests/tcg/mips/user/ase/msa/int-max-min/test_msa_max_u_w.c
new file mode 100644
index 0000000..910dbfc
--- /dev/null
+++ b/tests/tcg/mips/user/ase/msa/int-max-min/test_msa_max_u_w.c
@@ -0,0 +1,153 @@
+/*
+ * Test program for MSA instruction MAX_U.W
+ *
+ * Copyright (C) 2018 Wave Computing, Inc.
+ * Copyright (C) 2018 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.h"
+#include "../../../../include/test_utils.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 = "MAX_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] = {
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 0 */
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 8 */
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, },
+ { 0x5555555555555555ULL, 0x5555555555555555ULL, },
+ { 0xccccccccccccccccULL, 0xccccccccccccccccULL, },
+ { 0x3333333333333333ULL, 0x3333333333333333ULL, },
+ { 0xe38e38e38e38e38eULL, 0x38e38e38e38e38e3ULL, },
+ { 0x1c71c71c71c71c71ULL, 0xc71c71c71c71c71cULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 16 */
+ { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, },
+ { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, },
+ { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, },
+ { 0xccccccccccccccccULL, 0xccccccccccccccccULL, },
+ { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, },
+ { 0xe38e38e3aaaaaaaaULL, 0xaaaaaaaae38e38e3ULL, },
+ { 0xaaaaaaaaaaaaaaaaULL, 0xc71c71c7aaaaaaaaULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 24 */
+ { 0x5555555555555555ULL, 0x5555555555555555ULL, },
+ { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, },
+ { 0x5555555555555555ULL, 0x5555555555555555ULL, },
+ { 0xccccccccccccccccULL, 0xccccccccccccccccULL, },
+ { 0x5555555555555555ULL, 0x5555555555555555ULL, },
+ { 0xe38e38e38e38e38eULL, 0x55555555e38e38e3ULL, },
+ { 0x5555555571c71c71ULL, 0xc71c71c755555555ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 32 */
+ { 0xccccccccccccccccULL, 0xccccccccccccccccULL, },
+ { 0xccccccccccccccccULL, 0xccccccccccccccccULL, },
+ { 0xccccccccccccccccULL, 0xccccccccccccccccULL, },
+ { 0xccccccccccccccccULL, 0xccccccccccccccccULL, },
+ { 0xccccccccccccccccULL, 0xccccccccccccccccULL, },
+ { 0xe38e38e3ccccccccULL, 0xcccccccce38e38e3ULL, },
+ { 0xccccccccccccccccULL, 0xccccccccccccccccULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 40 */
+ { 0x3333333333333333ULL, 0x3333333333333333ULL, },
+ { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, },
+ { 0x5555555555555555ULL, 0x5555555555555555ULL, },
+ { 0xccccccccccccccccULL, 0xccccccccccccccccULL, },
+ { 0x3333333333333333ULL, 0x3333333333333333ULL, },
+ { 0xe38e38e38e38e38eULL, 0x38e38e38e38e38e3ULL, },
+ { 0x3333333371c71c71ULL, 0xc71c71c733333333ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 48 */
+ { 0xe38e38e38e38e38eULL, 0x38e38e38e38e38e3ULL, },
+ { 0xe38e38e3aaaaaaaaULL, 0xaaaaaaaae38e38e3ULL, },
+ { 0xe38e38e38e38e38eULL, 0x55555555e38e38e3ULL, },
+ { 0xe38e38e3ccccccccULL, 0xcccccccce38e38e3ULL, },
+ { 0xe38e38e38e38e38eULL, 0x38e38e38e38e38e3ULL, },
+ { 0xe38e38e38e38e38eULL, 0x38e38e38e38e38e3ULL, },
+ { 0xe38e38e38e38e38eULL, 0xc71c71c7e38e38e3ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 56 */
+ { 0x1c71c71c71c71c71ULL, 0xc71c71c71c71c71cULL, },
+ { 0xaaaaaaaaaaaaaaaaULL, 0xc71c71c7aaaaaaaaULL, },
+ { 0x5555555571c71c71ULL, 0xc71c71c755555555ULL, },
+ { 0xccccccccccccccccULL, 0xccccccccccccccccULL, },
+ { 0x3333333371c71c71ULL, 0xc71c71c733333333ULL, },
+ { 0xe38e38e38e38e38eULL, 0xc71c71c7e38e38e3ULL, },
+ { 0x1c71c71c71c71c71ULL, 0xc71c71c71c71c71cULL, },
+ { 0x886ae6cc28625540ULL, 0x4b670b5efe7bb00cULL, }, /* 64 */
+ { 0xfbbe00634d93c708ULL, 0x4b670b5efe7bb00cULL, },
+ { 0xac5aaeaab9cf8b80ULL, 0x4b670b5efe7bb00cULL, },
+ { 0x886ae6cc5e31e24eULL, 0x8df188d8fe7bb00cULL, },
+ { 0xfbbe00634d93c708ULL, 0x4b670b5efe7bb00cULL, },
+ { 0xfbbe00634d93c708ULL, 0x12f7bb1a153f52fcULL, },
+ { 0xfbbe0063b9cf8b80ULL, 0x27d8c6ffab2b2514ULL, },
+ { 0xfbbe00635e31e24eULL, 0x8df188d8a942e2a0ULL, },
+ { 0xac5aaeaab9cf8b80ULL, 0x4b670b5efe7bb00cULL, }, /* 72 */
+ { 0xfbbe0063b9cf8b80ULL, 0x27d8c6ffab2b2514ULL, },
+ { 0xac5aaeaab9cf8b80ULL, 0x27d8c6ffab2b2514ULL, },
+ { 0xac5aaeaab9cf8b80ULL, 0x8df188d8ab2b2514ULL, },
+ { 0x886ae6cc5e31e24eULL, 0x8df188d8fe7bb00cULL, },
+ { 0xfbbe00635e31e24eULL, 0x8df188d8a942e2a0ULL, },
+ { 0xac5aaeaab9cf8b80ULL, 0x8df188d8ab2b2514ULL, },
+ { 0x704f164d5e31e24eULL, 0x8df188d8a942e2a0ULL, },
+ };
+
+ gettimeofday(&start, NULL);
+
+ for (i = 0; i < PATTERN_INPUTS_SHORT_COUNT; i++) {
+ for (j = 0; j < PATTERN_INPUTS_SHORT_COUNT; j++) {
+ do_msa_MAX_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_MAX_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-max-min/test_msa_min_a_b.c b/tests/tcg/mips/user/ase/msa/int-max-min/test_msa_min_a_b.c
new file mode 100644
index 0000000..c632fe9
--- /dev/null
+++ b/tests/tcg/mips/user/ase/msa/int-max-min/test_msa_min_a_b.c
@@ -0,0 +1,153 @@
+/*
+ * Test program for MSA instruction MIN_A.B
+ *
+ * Copyright (C) 2018 Wave Computing, Inc.
+ * Copyright (C) 2018 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.h"
+#include "../../../../include/test_utils.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 = "MIN_A.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 */
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 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 */
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, },
+ { 0x5555555555555555ULL, 0x5555555555555555ULL, },
+ { 0xccccccccccccccccULL, 0xccccccccccccccccULL, },
+ { 0x3333333333333333ULL, 0x3333333333333333ULL, },
+ { 0xe3aa38e3aa38e3aaULL, 0x38e3aa38e3aa38e3ULL, },
+ { 0x1caac71caac71caaULL, 0xc71caac71caac71cULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 24 */
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x5555555555555555ULL, 0x5555555555555555ULL, },
+ { 0x5555555555555555ULL, 0x5555555555555555ULL, },
+ { 0xccccccccccccccccULL, 0xccccccccccccccccULL, },
+ { 0x3333333333333333ULL, 0x3333333333333333ULL, },
+ { 0xe35538e35538e355ULL, 0x38e35538e35538e3ULL, },
+ { 0x1c55c71c55c71c55ULL, 0xc71c55c71c55c71cULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 32 */
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xccccccccccccccccULL, 0xccccccccccccccccULL, },
+ { 0xccccccccccccccccULL, 0xccccccccccccccccULL, },
+ { 0xccccccccccccccccULL, 0xccccccccccccccccULL, },
+ { 0x3333333333333333ULL, 0x3333333333333333ULL, },
+ { 0xe3cccce3cccce3ccULL, 0xcce3cccce3cccce3ULL, },
+ { 0x1ccccc1ccccc1cccULL, 0xcc1ccccc1ccccc1cULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 40 */
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x3333333333333333ULL, 0x3333333333333333ULL, },
+ { 0x3333333333333333ULL, 0x3333333333333333ULL, },
+ { 0x3333333333333333ULL, 0x3333333333333333ULL, },
+ { 0x3333333333333333ULL, 0x3333333333333333ULL, },
+ { 0xe33333e33333e333ULL, 0x33e33333e33333e3ULL, },
+ { 0x1c33331c33331c33ULL, 0x331c33331c33331cULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 48 */
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xe3aa38e3aa38e3aaULL, 0x38e3aa38e3aa38e3ULL, },
+ { 0xe35538e35538e355ULL, 0x38e35538e35538e3ULL, },
+ { 0xe3cccce3cccce3ccULL, 0xcce3cccce3cccce3ULL, },
+ { 0xe33333e33333e333ULL, 0x33e33333e33333e3ULL, },
+ { 0xe38e38e38e38e38eULL, 0x38e38e38e38e38e3ULL, },
+ { 0x1c71381c71381c71ULL, 0x381c71381c71381cULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 56 */
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x1caac71caac71caaULL, 0xc71caac71caac71cULL, },
+ { 0x1c55c71c55c71c55ULL, 0xc71c55c71c55c71cULL, },
+ { 0x1ccccc1ccccc1cccULL, 0xcc1ccccc1ccccc1cULL, },
+ { 0x1c33331c33331c33ULL, 0x331c33331c33331cULL, },
+ { 0x1c71381c71381c71ULL, 0x381c71381c71381cULL, },
+ { 0x1c71c71c71c71c71ULL, 0xc71c71c71c71c71cULL, },
+ { 0x886ae6cc28625540ULL, 0x4b670b5efe7bb00cULL, }, /* 64 */
+ { 0xfbbe00cc2862c708ULL, 0x12f70b1afe3fb0fcULL, },
+ { 0xac5ae6cc28cf5540ULL, 0x27d80bfffe2b250cULL, },
+ { 0x704f16cc2831e240ULL, 0x4bf10bd8fe42e20cULL, },
+ { 0xfbbe00cc2862c708ULL, 0x12f70b1afe3fb0fcULL, },
+ { 0xfbbe00634d93c708ULL, 0x12f7bb1a153f52fcULL, },
+ { 0xfbbe00aab9cfc708ULL, 0x12f7c6ff152b25fcULL, },
+ { 0xfbbe004d4d31e208ULL, 0x12f7bb1a153fe2fcULL, },
+ { 0xac5ae6cc28cf5540ULL, 0x27d80bfffe2b250cULL, }, /* 72 */
+ { 0xfbbe00aab9cfc708ULL, 0x12f7c6ff152b25fcULL, },
+ { 0xac5aaeaab9cf8b80ULL, 0x27d8c6ffab2b2514ULL, },
+ { 0xac4f164db931e24eULL, 0x27f1c6ffab2be214ULL, },
+ { 0x704f16cc2831e240ULL, 0x4bf10bd8fe42e20cULL, },
+ { 0xfbbe004d4d31e208ULL, 0x12f7bb1a153fe2fcULL, },
+ { 0xac4f164db9cfe24eULL, 0x27f1c6ffab2be214ULL, },
+ { 0x704f164d5e31e24eULL, 0x8df188d8a942e2a0ULL, },
+ };
+
+ gettimeofday(&start, NULL);
+
+ for (i = 0; i < PATTERN_INPUTS_SHORT_COUNT; i++) {
+ for (j = 0; j < PATTERN_INPUTS_SHORT_COUNT; j++) {
+ do_msa_MIN_A_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_MIN_A_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-max-min/test_msa_min_a_d.c b/tests/tcg/mips/user/ase/msa/int-max-min/test_msa_min_a_d.c
new file mode 100644
index 0000000..5f9a9d4
--- /dev/null
+++ b/tests/tcg/mips/user/ase/msa/int-max-min/test_msa_min_a_d.c
@@ -0,0 +1,153 @@
+/*
+ * Test program for MSA instruction MIN_A.D
+ *
+ * Copyright (C) 2018 Wave Computing, Inc.
+ * Copyright (C) 2018 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.h"
+#include "../../../../include/test_utils.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 = "MIN_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, },
+ { 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 */
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, },
+ { 0x5555555555555555ULL, 0x5555555555555555ULL, },
+ { 0xccccccccccccccccULL, 0xccccccccccccccccULL, },
+ { 0x3333333333333333ULL, 0x3333333333333333ULL, },
+ { 0xe38e38e38e38e38eULL, 0x38e38e38e38e38e3ULL, },
+ { 0x1c71c71c71c71c71ULL, 0xc71c71c71c71c71cULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 24 */
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x5555555555555555ULL, 0x5555555555555555ULL, },
+ { 0x5555555555555555ULL, 0x5555555555555555ULL, },
+ { 0xccccccccccccccccULL, 0xccccccccccccccccULL, },
+ { 0x3333333333333333ULL, 0x3333333333333333ULL, },
+ { 0xe38e38e38e38e38eULL, 0x38e38e38e38e38e3ULL, },
+ { 0x1c71c71c71c71c71ULL, 0xc71c71c71c71c71cULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 32 */
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xccccccccccccccccULL, 0xccccccccccccccccULL, },
+ { 0xccccccccccccccccULL, 0xccccccccccccccccULL, },
+ { 0xccccccccccccccccULL, 0xccccccccccccccccULL, },
+ { 0x3333333333333333ULL, 0x3333333333333333ULL, },
+ { 0xe38e38e38e38e38eULL, 0xccccccccccccccccULL, },
+ { 0x1c71c71c71c71c71ULL, 0xccccccccccccccccULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 40 */
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x3333333333333333ULL, 0x3333333333333333ULL, },
+ { 0x3333333333333333ULL, 0x3333333333333333ULL, },
+ { 0x3333333333333333ULL, 0x3333333333333333ULL, },
+ { 0x3333333333333333ULL, 0x3333333333333333ULL, },
+ { 0xe38e38e38e38e38eULL, 0x3333333333333333ULL, },
+ { 0x1c71c71c71c71c71ULL, 0x3333333333333333ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 48 */
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xe38e38e38e38e38eULL, 0x38e38e38e38e38e3ULL, },
+ { 0xe38e38e38e38e38eULL, 0x38e38e38e38e38e3ULL, },
+ { 0xe38e38e38e38e38eULL, 0xccccccccccccccccULL, },
+ { 0xe38e38e38e38e38eULL, 0x3333333333333333ULL, },
+ { 0xe38e38e38e38e38eULL, 0x38e38e38e38e38e3ULL, },
+ { 0x1c71c71c71c71c71ULL, 0x38e38e38e38e38e3ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 56 */
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x1c71c71c71c71c71ULL, 0xc71c71c71c71c71cULL, },
+ { 0x1c71c71c71c71c71ULL, 0xc71c71c71c71c71cULL, },
+ { 0x1c71c71c71c71c71ULL, 0xccccccccccccccccULL, },
+ { 0x1c71c71c71c71c71ULL, 0x3333333333333333ULL, },
+ { 0x1c71c71c71c71c71ULL, 0x38e38e38e38e38e3ULL, },
+ { 0x1c71c71c71c71c71ULL, 0xc71c71c71c71c71cULL, },
+ { 0x886ae6cc28625540ULL, 0x4b670b5efe7bb00cULL, }, /* 64 */
+ { 0xfbbe00634d93c708ULL, 0x12f7bb1a153f52fcULL, },
+ { 0xac5aaeaab9cf8b80ULL, 0x27d8c6ffab2b2514ULL, },
+ { 0x704f164d5e31e24eULL, 0x4b670b5efe7bb00cULL, },
+ { 0xfbbe00634d93c708ULL, 0x12f7bb1a153f52fcULL, },
+ { 0xfbbe00634d93c708ULL, 0x12f7bb1a153f52fcULL, },
+ { 0xfbbe00634d93c708ULL, 0x12f7bb1a153f52fcULL, },
+ { 0xfbbe00634d93c708ULL, 0x12f7bb1a153f52fcULL, },
+ { 0xac5aaeaab9cf8b80ULL, 0x27d8c6ffab2b2514ULL, }, /* 72 */
+ { 0xfbbe00634d93c708ULL, 0x12f7bb1a153f52fcULL, },
+ { 0xac5aaeaab9cf8b80ULL, 0x27d8c6ffab2b2514ULL, },
+ { 0xac5aaeaab9cf8b80ULL, 0x27d8c6ffab2b2514ULL, },
+ { 0x704f164d5e31e24eULL, 0x4b670b5efe7bb00cULL, },
+ { 0xfbbe00634d93c708ULL, 0x12f7bb1a153f52fcULL, },
+ { 0xac5aaeaab9cf8b80ULL, 0x27d8c6ffab2b2514ULL, },
+ { 0x704f164d5e31e24eULL, 0x8df188d8a942e2a0ULL, },
+ };
+
+ gettimeofday(&start, NULL);
+
+ for (i = 0; i < PATTERN_INPUTS_SHORT_COUNT; i++) {
+ for (j = 0; j < PATTERN_INPUTS_SHORT_COUNT; j++) {
+ do_msa_MIN_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_MIN_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/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
new file mode 100644
index 0000000..dc73927
--- /dev/null
+++ b/tests/tcg/mips/user/ase/msa/int-max-min/test_msa_min_a_h.c
@@ -0,0 +1,153 @@
+/*
+ * Test program for MSA instruction MIN_A.H
+ *
+ * Copyright (C) 2018 Wave Computing, Inc.
+ * Copyright (C) 2018 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.h"
+#include "../../../../include/test_utils.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 = "MIN_A.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 */
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 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 */
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, },
+ { 0x5555555555555555ULL, 0x5555555555555555ULL, },
+ { 0xccccccccccccccccULL, 0xccccccccccccccccULL, },
+ { 0x3333333333333333ULL, 0x3333333333333333ULL, },
+ { 0xe38e38e3aaaae38eULL, 0x38e3aaaae38e38e3ULL, },
+ { 0x1c71c71caaaa1c71ULL, 0xc71caaaa1c71c71cULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 24 */
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x5555555555555555ULL, 0x5555555555555555ULL, },
+ { 0x5555555555555555ULL, 0x5555555555555555ULL, },
+ { 0xccccccccccccccccULL, 0xccccccccccccccccULL, },
+ { 0x3333333333333333ULL, 0x3333333333333333ULL, },
+ { 0xe38e38e35555e38eULL, 0x38e35555e38e38e3ULL, },
+ { 0x1c71c71c55551c71ULL, 0xc71c55551c71c71cULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 32 */
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xccccccccccccccccULL, 0xccccccccccccccccULL, },
+ { 0xccccccccccccccccULL, 0xccccccccccccccccULL, },
+ { 0xccccccccccccccccULL, 0xccccccccccccccccULL, },
+ { 0x3333333333333333ULL, 0x3333333333333333ULL, },
+ { 0xe38ecccccccce38eULL, 0xcccccccce38eccccULL, },
+ { 0x1c71cccccccc1c71ULL, 0xcccccccc1c71ccccULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 40 */
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x3333333333333333ULL, 0x3333333333333333ULL, },
+ { 0x3333333333333333ULL, 0x3333333333333333ULL, },
+ { 0x3333333333333333ULL, 0x3333333333333333ULL, },
+ { 0x3333333333333333ULL, 0x3333333333333333ULL, },
+ { 0xe38e33333333e38eULL, 0x33333333e38e3333ULL, },
+ { 0x1c71333333331c71ULL, 0x333333331c713333ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 48 */
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xe38e38e3aaaae38eULL, 0x38e3aaaae38e38e3ULL, },
+ { 0xe38e38e35555e38eULL, 0x38e35555e38e38e3ULL, },
+ { 0xe38ecccccccce38eULL, 0xcccccccce38eccccULL, },
+ { 0xe38e33333333e38eULL, 0x33333333e38e3333ULL, },
+ { 0xe38e38e38e38e38eULL, 0x38e38e38e38e38e3ULL, },
+ { 0x1c7138e371c71c71ULL, 0x38e371c71c7138e3ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 56 */
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x1c71c71caaaa1c71ULL, 0xc71caaaa1c71c71cULL, },
+ { 0x1c71c71c55551c71ULL, 0xc71c55551c71c71cULL, },
+ { 0x1c71cccccccc1c71ULL, 0xcccccccc1c71ccccULL, },
+ { 0x1c71333333331c71ULL, 0x333333331c713333ULL, },
+ { 0x1c7138e371c71c71ULL, 0x38e371c71c7138e3ULL, },
+ { 0x1c71c71c71c71c71ULL, 0xc71c71c71c71c71cULL, },
+ { 0x886ae6cc28625540ULL, 0x4b670b5efe7bb00cULL, }, /* 64 */
+ { 0xfbbe00632862c708ULL, 0x12f70b5efe7bb00cULL, },
+ { 0xac5ae6cc28625540ULL, 0x27d80b5efe7b2514ULL, },
+ { 0x704f164d2862e24eULL, 0x4b670b5efe7be2a0ULL, },
+ { 0xfbbe00632862c708ULL, 0x12f70b5efe7bb00cULL, },
+ { 0xfbbe00634d93c708ULL, 0x12f7bb1a153f52fcULL, },
+ { 0xfbbe0063b9cfc708ULL, 0x12f7c6ff153f2514ULL, },
+ { 0xfbbe00634d93e24eULL, 0x12f7bb1a153fe2a0ULL, },
+ { 0xac5ae6cc28625540ULL, 0x27d80b5efe7b2514ULL, }, /* 72 */
+ { 0xfbbe0063b9cfc708ULL, 0x12f7c6ff153f2514ULL, },
+ { 0xac5aaeaab9cf8b80ULL, 0x27d8c6ffab2b2514ULL, },
+ { 0xac5a164db9cfe24eULL, 0x27d8c6ffab2be2a0ULL, },
+ { 0x704f164d2862e24eULL, 0x4b670b5efe7be2a0ULL, },
+ { 0xfbbe00634d93e24eULL, 0x12f7bb1a153fe2a0ULL, },
+ { 0xac5a164db9cfe24eULL, 0x27d8c6ffab2be2a0ULL, },
+ { 0x704f164d5e31e24eULL, 0x8df188d8a942e2a0ULL, },
+ };
+
+ gettimeofday(&start, NULL);
+
+ for (i = 0; i < PATTERN_INPUTS_SHORT_COUNT; i++) {
+ for (j = 0; j < PATTERN_INPUTS_SHORT_COUNT; j++) {
+ do_msa_MIN_A_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_MIN_A_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-max-min/test_msa_min_a_w.c b/tests/tcg/mips/user/ase/msa/int-max-min/test_msa_min_a_w.c
new file mode 100644
index 0000000..67b33f3
--- /dev/null
+++ b/tests/tcg/mips/user/ase/msa/int-max-min/test_msa_min_a_w.c
@@ -0,0 +1,153 @@
+/*
+ * Test program for MSA instruction MIN_A.W
+ *
+ * Copyright (C) 2018 Wave Computing, Inc.
+ * Copyright (C) 2018 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.h"
+#include "../../../../include/test_utils.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 = "MIN_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, },
+ { 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 */
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, },
+ { 0x5555555555555555ULL, 0x5555555555555555ULL, },
+ { 0xccccccccccccccccULL, 0xccccccccccccccccULL, },
+ { 0x3333333333333333ULL, 0x3333333333333333ULL, },
+ { 0xe38e38e3aaaaaaaaULL, 0x38e38e38e38e38e3ULL, },
+ { 0x1c71c71caaaaaaaaULL, 0xc71c71c71c71c71cULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 24 */
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x5555555555555555ULL, 0x5555555555555555ULL, },
+ { 0x5555555555555555ULL, 0x5555555555555555ULL, },
+ { 0xccccccccccccccccULL, 0xccccccccccccccccULL, },
+ { 0x3333333333333333ULL, 0x3333333333333333ULL, },
+ { 0xe38e38e355555555ULL, 0x38e38e38e38e38e3ULL, },
+ { 0x1c71c71c55555555ULL, 0xc71c71c71c71c71cULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 32 */
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xccccccccccccccccULL, 0xccccccccccccccccULL, },
+ { 0xccccccccccccccccULL, 0xccccccccccccccccULL, },
+ { 0xccccccccccccccccULL, 0xccccccccccccccccULL, },
+ { 0x3333333333333333ULL, 0x3333333333333333ULL, },
+ { 0xe38e38e3ccccccccULL, 0xcccccccce38e38e3ULL, },
+ { 0x1c71c71cccccccccULL, 0xcccccccc1c71c71cULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 40 */
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x3333333333333333ULL, 0x3333333333333333ULL, },
+ { 0x3333333333333333ULL, 0x3333333333333333ULL, },
+ { 0x3333333333333333ULL, 0x3333333333333333ULL, },
+ { 0x3333333333333333ULL, 0x3333333333333333ULL, },
+ { 0xe38e38e333333333ULL, 0x33333333e38e38e3ULL, },
+ { 0x1c71c71c33333333ULL, 0x333333331c71c71cULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 48 */
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xe38e38e3aaaaaaaaULL, 0x38e38e38e38e38e3ULL, },
+ { 0xe38e38e355555555ULL, 0x38e38e38e38e38e3ULL, },
+ { 0xe38e38e3ccccccccULL, 0xcccccccce38e38e3ULL, },
+ { 0xe38e38e333333333ULL, 0x33333333e38e38e3ULL, },
+ { 0xe38e38e38e38e38eULL, 0x38e38e38e38e38e3ULL, },
+ { 0x1c71c71c71c71c71ULL, 0x38e38e381c71c71cULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 56 */
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x1c71c71caaaaaaaaULL, 0xc71c71c71c71c71cULL, },
+ { 0x1c71c71c55555555ULL, 0xc71c71c71c71c71cULL, },
+ { 0x1c71c71cccccccccULL, 0xcccccccc1c71c71cULL, },
+ { 0x1c71c71c33333333ULL, 0x333333331c71c71cULL, },
+ { 0x1c71c71c71c71c71ULL, 0x38e38e381c71c71cULL, },
+ { 0x1c71c71c71c71c71ULL, 0xc71c71c71c71c71cULL, },
+ { 0x886ae6cc28625540ULL, 0x4b670b5efe7bb00cULL, }, /* 64 */
+ { 0xfbbe006328625540ULL, 0x12f7bb1afe7bb00cULL, },
+ { 0xac5aaeaa28625540ULL, 0x27d8c6fffe7bb00cULL, },
+ { 0x704f164d28625540ULL, 0x4b670b5efe7bb00cULL, },
+ { 0xfbbe006328625540ULL, 0x12f7bb1afe7bb00cULL, },
+ { 0xfbbe00634d93c708ULL, 0x12f7bb1a153f52fcULL, },
+ { 0xfbbe0063b9cf8b80ULL, 0x12f7bb1a153f52fcULL, },
+ { 0xfbbe00634d93c708ULL, 0x12f7bb1a153f52fcULL, },
+ { 0xac5aaeaa28625540ULL, 0x27d8c6fffe7bb00cULL, }, /* 72 */
+ { 0xfbbe0063b9cf8b80ULL, 0x12f7bb1a153f52fcULL, },
+ { 0xac5aaeaab9cf8b80ULL, 0x27d8c6ffab2b2514ULL, },
+ { 0xac5aaeaab9cf8b80ULL, 0x27d8c6ffab2b2514ULL, },
+ { 0x704f164d28625540ULL, 0x4b670b5efe7bb00cULL, },
+ { 0xfbbe00634d93c708ULL, 0x12f7bb1a153f52fcULL, },
+ { 0xac5aaeaab9cf8b80ULL, 0x27d8c6ffab2b2514ULL, },
+ { 0x704f164d5e31e24eULL, 0x8df188d8a942e2a0ULL, },
+ };
+
+ gettimeofday(&start, NULL);
+
+ for (i = 0; i < PATTERN_INPUTS_SHORT_COUNT; i++) {
+ for (j = 0; j < PATTERN_INPUTS_SHORT_COUNT; j++) {
+ do_msa_MIN_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_MIN_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/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
new file mode 100644
index 0000000..76bb133
--- /dev/null
+++ b/tests/tcg/mips/user/ase/msa/int-max-min/test_msa_min_s_b.c
@@ -0,0 +1,153 @@
+/*
+ * Test program for MSA instruction MIN_S.B
+ *
+ * Copyright (C) 2018 Wave Computing, Inc.
+ * Copyright (C) 2018 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.h"
+#include "../../../../include/test_utils.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 = "MIN_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] = {
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 0 */
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0xccccccccccccccccULL, 0xccccccccccccccccULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0xe38effe38effe38eULL, 0xffe38effe38effe3ULL, },
+ { 0xffffc7ffffc7ffffULL, 0xc7ffffc7ffffc7ffULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 8 */
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xccccccccccccccccULL, 0xccccccccccccccccULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xe38e00e38e00e38eULL, 0x00e38e00e38e00e3ULL, },
+ { 0x0000c70000c70000ULL, 0xc70000c70000c700ULL, },
+ { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, }, /* 16 */
+ { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, },
+ { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, },
+ { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, },
+ { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, },
+ { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, },
+ { 0xaa8eaaaa8eaaaa8eULL, 0xaaaa8eaaaa8eaaaaULL, },
+ { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 24 */
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, },
+ { 0x5555555555555555ULL, 0x5555555555555555ULL, },
+ { 0xccccccccccccccccULL, 0xccccccccccccccccULL, },
+ { 0x3333333333333333ULL, 0x3333333333333333ULL, },
+ { 0xe38e38e38e38e38eULL, 0x38e38e38e38e38e3ULL, },
+ { 0x1c55c71c55c71c55ULL, 0xc71c55c71c55c71cULL, },
+ { 0xccccccccccccccccULL, 0xccccccccccccccccULL, }, /* 32 */
+ { 0xccccccccccccccccULL, 0xccccccccccccccccULL, },
+ { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, },
+ { 0xccccccccccccccccULL, 0xccccccccccccccccULL, },
+ { 0xccccccccccccccccULL, 0xccccccccccccccccULL, },
+ { 0xccccccccccccccccULL, 0xccccccccccccccccULL, },
+ { 0xcc8ecccc8ecccc8eULL, 0xcccc8ecccc8eccccULL, },
+ { 0xccccc7ccccc7ccccULL, 0xc7ccccc7ccccc7ccULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 40 */
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, },
+ { 0x3333333333333333ULL, 0x3333333333333333ULL, },
+ { 0xccccccccccccccccULL, 0xccccccccccccccccULL, },
+ { 0x3333333333333333ULL, 0x3333333333333333ULL, },
+ { 0xe38e33e38e33e38eULL, 0x33e38e33e38e33e3ULL, },
+ { 0x1c33c71c33c71c33ULL, 0xc71c33c71c33c71cULL, },
+ { 0xe38effe38effe38eULL, 0xffe38effe38effe3ULL, }, /* 48 */
+ { 0xe38e00e38e00e38eULL, 0x00e38e00e38e00e3ULL, },
+ { 0xaa8eaaaa8eaaaa8eULL, 0xaaaa8eaaaa8eaaaaULL, },
+ { 0xe38e38e38e38e38eULL, 0x38e38e38e38e38e3ULL, },
+ { 0xcc8ecccc8ecccc8eULL, 0xcccc8ecccc8eccccULL, },
+ { 0xe38e33e38e33e38eULL, 0x33e38e33e38e33e3ULL, },
+ { 0xe38e38e38e38e38eULL, 0x38e38e38e38e38e3ULL, },
+ { 0xe38ec7e38ec7e38eULL, 0xc7e38ec7e38ec7e3ULL, },
+ { 0xffffc7ffffc7ffffULL, 0xc7ffffc7ffffc7ffULL, }, /* 56 */
+ { 0x0000c70000c70000ULL, 0xc70000c70000c700ULL, },
+ { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, },
+ { 0x1c55c71c55c71c55ULL, 0xc71c55c71c55c71cULL, },
+ { 0xccccc7ccccc7ccccULL, 0xc7ccccc7ccccc7ccULL, },
+ { 0x1c33c71c33c71c33ULL, 0xc71c33c71c33c71cULL, },
+ { 0xe38ec7e38ec7e38eULL, 0xc7e38ec7e38ec7e3ULL, },
+ { 0x1c71c71c71c71c71ULL, 0xc71c71c71c71c71cULL, },
+ { 0x886ae6cc28625540ULL, 0x4b670b5efe7bb00cULL, }, /* 64 */
+ { 0x88bee6cc2893c708ULL, 0x12f7bb1afe3fb0fcULL, },
+ { 0x885aaeaab9cf8b80ULL, 0x27d8c6ffab2bb00cULL, },
+ { 0x884fe6cc2831e240ULL, 0x8df188d8a942b0a0ULL, },
+ { 0x88bee6cc2893c708ULL, 0x12f7bb1afe3fb0fcULL, },
+ { 0xfbbe00634d93c708ULL, 0x12f7bb1a153f52fcULL, },
+ { 0xacbeaeaab9938b80ULL, 0x12d8bbffab2b25fcULL, },
+ { 0xfbbe004d4d93c708ULL, 0x8df188d8a93fe2a0ULL, },
+ { 0x885aaeaab9cf8b80ULL, 0x27d8c6ffab2bb00cULL, }, /* 72 */
+ { 0xacbeaeaab9938b80ULL, 0x12d8bbffab2b25fcULL, },
+ { 0xac5aaeaab9cf8b80ULL, 0x27d8c6ffab2b2514ULL, },
+ { 0xac4faeaab9cf8b80ULL, 0x8dd888d8a92be2a0ULL, },
+ { 0x884fe6cc2831e240ULL, 0x8df188d8a942b0a0ULL, },
+ { 0xfbbe004d4d93c708ULL, 0x8df188d8a93fe2a0ULL, },
+ { 0xac4faeaab9cf8b80ULL, 0x8dd888d8a92be2a0ULL, },
+ { 0x704f164d5e31e24eULL, 0x8df188d8a942e2a0ULL, },
+ };
+
+ gettimeofday(&start, NULL);
+
+ for (i = 0; i < PATTERN_INPUTS_SHORT_COUNT; i++) {
+ for (j = 0; j < PATTERN_INPUTS_SHORT_COUNT; j++) {
+ do_msa_MIN_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_MIN_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-max-min/test_msa_min_s_d.c b/tests/tcg/mips/user/ase/msa/int-max-min/test_msa_min_s_d.c
new file mode 100644
index 0000000..8ef57a9
--- /dev/null
+++ b/tests/tcg/mips/user/ase/msa/int-max-min/test_msa_min_s_d.c
@@ -0,0 +1,153 @@
+/*
+ * Test program for MSA instruction MIN_S.D
+ *
+ * Copyright (C) 2018 Wave Computing, Inc.
+ * Copyright (C) 2018 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.h"
+#include "../../../../include/test_utils.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 = "MIN_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] = {
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 0 */
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0xccccccccccccccccULL, 0xccccccccccccccccULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0xe38e38e38e38e38eULL, 0xffffffffffffffffULL, },
+ { 0xffffffffffffffffULL, 0xc71c71c71c71c71cULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 8 */
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xccccccccccccccccULL, 0xccccccccccccccccULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xe38e38e38e38e38eULL, 0x0000000000000000ULL, },
+ { 0x0000000000000000ULL, 0xc71c71c71c71c71cULL, },
+ { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, }, /* 16 */
+ { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, },
+ { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, },
+ { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, },
+ { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, },
+ { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, },
+ { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, },
+ { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 24 */
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, },
+ { 0x5555555555555555ULL, 0x5555555555555555ULL, },
+ { 0xccccccccccccccccULL, 0xccccccccccccccccULL, },
+ { 0x3333333333333333ULL, 0x3333333333333333ULL, },
+ { 0xe38e38e38e38e38eULL, 0x38e38e38e38e38e3ULL, },
+ { 0x1c71c71c71c71c71ULL, 0xc71c71c71c71c71cULL, },
+ { 0xccccccccccccccccULL, 0xccccccccccccccccULL, }, /* 32 */
+ { 0xccccccccccccccccULL, 0xccccccccccccccccULL, },
+ { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, },
+ { 0xccccccccccccccccULL, 0xccccccccccccccccULL, },
+ { 0xccccccccccccccccULL, 0xccccccccccccccccULL, },
+ { 0xccccccccccccccccULL, 0xccccccccccccccccULL, },
+ { 0xccccccccccccccccULL, 0xccccccccccccccccULL, },
+ { 0xccccccccccccccccULL, 0xc71c71c71c71c71cULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 40 */
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, },
+ { 0x3333333333333333ULL, 0x3333333333333333ULL, },
+ { 0xccccccccccccccccULL, 0xccccccccccccccccULL, },
+ { 0x3333333333333333ULL, 0x3333333333333333ULL, },
+ { 0xe38e38e38e38e38eULL, 0x3333333333333333ULL, },
+ { 0x1c71c71c71c71c71ULL, 0xc71c71c71c71c71cULL, },
+ { 0xe38e38e38e38e38eULL, 0xffffffffffffffffULL, }, /* 48 */
+ { 0xe38e38e38e38e38eULL, 0x0000000000000000ULL, },
+ { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, },
+ { 0xe38e38e38e38e38eULL, 0x38e38e38e38e38e3ULL, },
+ { 0xccccccccccccccccULL, 0xccccccccccccccccULL, },
+ { 0xe38e38e38e38e38eULL, 0x3333333333333333ULL, },
+ { 0xe38e38e38e38e38eULL, 0x38e38e38e38e38e3ULL, },
+ { 0xe38e38e38e38e38eULL, 0xc71c71c71c71c71cULL, },
+ { 0xffffffffffffffffULL, 0xc71c71c71c71c71cULL, }, /* 56 */
+ { 0x0000000000000000ULL, 0xc71c71c71c71c71cULL, },
+ { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, },
+ { 0x1c71c71c71c71c71ULL, 0xc71c71c71c71c71cULL, },
+ { 0xccccccccccccccccULL, 0xc71c71c71c71c71cULL, },
+ { 0x1c71c71c71c71c71ULL, 0xc71c71c71c71c71cULL, },
+ { 0xe38e38e38e38e38eULL, 0xc71c71c71c71c71cULL, },
+ { 0x1c71c71c71c71c71ULL, 0xc71c71c71c71c71cULL, },
+ { 0x886ae6cc28625540ULL, 0x4b670b5efe7bb00cULL, }, /* 64 */
+ { 0x886ae6cc28625540ULL, 0x12f7bb1a153f52fcULL, },
+ { 0x886ae6cc28625540ULL, 0x27d8c6ffab2b2514ULL, },
+ { 0x886ae6cc28625540ULL, 0x8df188d8a942e2a0ULL, },
+ { 0x886ae6cc28625540ULL, 0x12f7bb1a153f52fcULL, },
+ { 0xfbbe00634d93c708ULL, 0x12f7bb1a153f52fcULL, },
+ { 0xac5aaeaab9cf8b80ULL, 0x12f7bb1a153f52fcULL, },
+ { 0xfbbe00634d93c708ULL, 0x8df188d8a942e2a0ULL, },
+ { 0x886ae6cc28625540ULL, 0x27d8c6ffab2b2514ULL, }, /* 72 */
+ { 0xac5aaeaab9cf8b80ULL, 0x12f7bb1a153f52fcULL, },
+ { 0xac5aaeaab9cf8b80ULL, 0x27d8c6ffab2b2514ULL, },
+ { 0xac5aaeaab9cf8b80ULL, 0x8df188d8a942e2a0ULL, },
+ { 0x886ae6cc28625540ULL, 0x8df188d8a942e2a0ULL, },
+ { 0xfbbe00634d93c708ULL, 0x8df188d8a942e2a0ULL, },
+ { 0xac5aaeaab9cf8b80ULL, 0x8df188d8a942e2a0ULL, },
+ { 0x704f164d5e31e24eULL, 0x8df188d8a942e2a0ULL, },
+ };
+
+ gettimeofday(&start, NULL);
+
+ for (i = 0; i < PATTERN_INPUTS_SHORT_COUNT; i++) {
+ for (j = 0; j < PATTERN_INPUTS_SHORT_COUNT; j++) {
+ do_msa_MIN_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_MIN_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-max-min/test_msa_min_s_h.c b/tests/tcg/mips/user/ase/msa/int-max-min/test_msa_min_s_h.c
new file mode 100644
index 0000000..e206040
--- /dev/null
+++ b/tests/tcg/mips/user/ase/msa/int-max-min/test_msa_min_s_h.c
@@ -0,0 +1,153 @@
+/*
+ * Test program for MSA instruction MIN_S.H
+ *
+ * Copyright (C) 2018 Wave Computing, Inc.
+ * Copyright (C) 2018 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.h"
+#include "../../../../include/test_utils.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 = "MIN_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] = {
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 0 */
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0xccccccccccccccccULL, 0xccccccccccccccccULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0xe38effff8e38e38eULL, 0xffff8e38e38effffULL, },
+ { 0xffffc71cffffffffULL, 0xc71cffffffffc71cULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 8 */
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xccccccccccccccccULL, 0xccccccccccccccccULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xe38e00008e38e38eULL, 0x00008e38e38e0000ULL, },
+ { 0x0000c71c00000000ULL, 0xc71c00000000c71cULL, },
+ { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, }, /* 16 */
+ { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, },
+ { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, },
+ { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, },
+ { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, },
+ { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, },
+ { 0xaaaaaaaa8e38aaaaULL, 0xaaaa8e38aaaaaaaaULL, },
+ { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 24 */
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, },
+ { 0x5555555555555555ULL, 0x5555555555555555ULL, },
+ { 0xccccccccccccccccULL, 0xccccccccccccccccULL, },
+ { 0x3333333333333333ULL, 0x3333333333333333ULL, },
+ { 0xe38e38e38e38e38eULL, 0x38e38e38e38e38e3ULL, },
+ { 0x1c71c71c55551c71ULL, 0xc71c55551c71c71cULL, },
+ { 0xccccccccccccccccULL, 0xccccccccccccccccULL, }, /* 32 */
+ { 0xccccccccccccccccULL, 0xccccccccccccccccULL, },
+ { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, },
+ { 0xccccccccccccccccULL, 0xccccccccccccccccULL, },
+ { 0xccccccccccccccccULL, 0xccccccccccccccccULL, },
+ { 0xccccccccccccccccULL, 0xccccccccccccccccULL, },
+ { 0xcccccccc8e38ccccULL, 0xcccc8e38ccccccccULL, },
+ { 0xccccc71cccccccccULL, 0xc71cccccccccc71cULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 40 */
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, },
+ { 0x3333333333333333ULL, 0x3333333333333333ULL, },
+ { 0xccccccccccccccccULL, 0xccccccccccccccccULL, },
+ { 0x3333333333333333ULL, 0x3333333333333333ULL, },
+ { 0xe38e33338e38e38eULL, 0x33338e38e38e3333ULL, },
+ { 0x1c71c71c33331c71ULL, 0xc71c33331c71c71cULL, },
+ { 0xe38effff8e38e38eULL, 0xffff8e38e38effffULL, }, /* 48 */
+ { 0xe38e00008e38e38eULL, 0x00008e38e38e0000ULL, },
+ { 0xaaaaaaaa8e38aaaaULL, 0xaaaa8e38aaaaaaaaULL, },
+ { 0xe38e38e38e38e38eULL, 0x38e38e38e38e38e3ULL, },
+ { 0xcccccccc8e38ccccULL, 0xcccc8e38ccccccccULL, },
+ { 0xe38e33338e38e38eULL, 0x33338e38e38e3333ULL, },
+ { 0xe38e38e38e38e38eULL, 0x38e38e38e38e38e3ULL, },
+ { 0xe38ec71c8e38e38eULL, 0xc71c8e38e38ec71cULL, },
+ { 0xffffc71cffffffffULL, 0xc71cffffffffc71cULL, }, /* 56 */
+ { 0x0000c71c00000000ULL, 0xc71c00000000c71cULL, },
+ { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, },
+ { 0x1c71c71c55551c71ULL, 0xc71c55551c71c71cULL, },
+ { 0xccccc71cccccccccULL, 0xc71cccccccccc71cULL, },
+ { 0x1c71c71c33331c71ULL, 0xc71c33331c71c71cULL, },
+ { 0xe38ec71c8e38e38eULL, 0xc71c8e38e38ec71cULL, },
+ { 0x1c71c71c71c71c71ULL, 0xc71c71c71c71c71cULL, },
+ { 0x886ae6cc28625540ULL, 0x4b670b5efe7bb00cULL, }, /* 64 */
+ { 0x886ae6cc2862c708ULL, 0x12f7bb1afe7bb00cULL, },
+ { 0x886aaeaab9cf8b80ULL, 0x27d8c6ffab2bb00cULL, },
+ { 0x886ae6cc2862e24eULL, 0x8df188d8a942b00cULL, },
+ { 0x886ae6cc2862c708ULL, 0x12f7bb1afe7bb00cULL, },
+ { 0xfbbe00634d93c708ULL, 0x12f7bb1a153f52fcULL, },
+ { 0xac5aaeaab9cf8b80ULL, 0x12f7bb1aab2b2514ULL, },
+ { 0xfbbe00634d93c708ULL, 0x8df188d8a942e2a0ULL, },
+ { 0x886aaeaab9cf8b80ULL, 0x27d8c6ffab2bb00cULL, }, /* 72 */
+ { 0xac5aaeaab9cf8b80ULL, 0x12f7bb1aab2b2514ULL, },
+ { 0xac5aaeaab9cf8b80ULL, 0x27d8c6ffab2b2514ULL, },
+ { 0xac5aaeaab9cf8b80ULL, 0x8df188d8a942e2a0ULL, },
+ { 0x886ae6cc2862e24eULL, 0x8df188d8a942b00cULL, },
+ { 0xfbbe00634d93c708ULL, 0x8df188d8a942e2a0ULL, },
+ { 0xac5aaeaab9cf8b80ULL, 0x8df188d8a942e2a0ULL, },
+ { 0x704f164d5e31e24eULL, 0x8df188d8a942e2a0ULL, },
+ };
+
+ gettimeofday(&start, NULL);
+
+ for (i = 0; i < PATTERN_INPUTS_SHORT_COUNT; i++) {
+ for (j = 0; j < PATTERN_INPUTS_SHORT_COUNT; j++) {
+ do_msa_MIN_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_MIN_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-max-min/test_msa_min_s_w.c b/tests/tcg/mips/user/ase/msa/int-max-min/test_msa_min_s_w.c
new file mode 100644
index 0000000..7532bce
--- /dev/null
+++ b/tests/tcg/mips/user/ase/msa/int-max-min/test_msa_min_s_w.c
@@ -0,0 +1,153 @@
+/*
+ * Test program for MSA instruction MIN_S.W
+ *
+ * Copyright (C) 2018 Wave Computing, Inc.
+ * Copyright (C) 2018 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.h"
+#include "../../../../include/test_utils.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 = "MIN_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] = {
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 0 */
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0xccccccccccccccccULL, 0xccccccccccccccccULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+ { 0xe38e38e38e38e38eULL, 0xffffffffe38e38e3ULL, },
+ { 0xffffffffffffffffULL, 0xc71c71c7ffffffffULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 8 */
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xccccccccccccccccULL, 0xccccccccccccccccULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xe38e38e38e38e38eULL, 0x00000000e38e38e3ULL, },
+ { 0x0000000000000000ULL, 0xc71c71c700000000ULL, },
+ { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, }, /* 16 */
+ { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, },
+ { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, },
+ { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, },
+ { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, },
+ { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, },
+ { 0xaaaaaaaa8e38e38eULL, 0xaaaaaaaaaaaaaaaaULL, },
+ { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 24 */
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, },
+ { 0x5555555555555555ULL, 0x5555555555555555ULL, },
+ { 0xccccccccccccccccULL, 0xccccccccccccccccULL, },
+ { 0x3333333333333333ULL, 0x3333333333333333ULL, },
+ { 0xe38e38e38e38e38eULL, 0x38e38e38e38e38e3ULL, },
+ { 0x1c71c71c55555555ULL, 0xc71c71c71c71c71cULL, },
+ { 0xccccccccccccccccULL, 0xccccccccccccccccULL, }, /* 32 */
+ { 0xccccccccccccccccULL, 0xccccccccccccccccULL, },
+ { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, },
+ { 0xccccccccccccccccULL, 0xccccccccccccccccULL, },
+ { 0xccccccccccccccccULL, 0xccccccccccccccccULL, },
+ { 0xccccccccccccccccULL, 0xccccccccccccccccULL, },
+ { 0xcccccccc8e38e38eULL, 0xccccccccccccccccULL, },
+ { 0xccccccccccccccccULL, 0xc71c71c7ccccccccULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 40 */
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, },
+ { 0x3333333333333333ULL, 0x3333333333333333ULL, },
+ { 0xccccccccccccccccULL, 0xccccccccccccccccULL, },
+ { 0x3333333333333333ULL, 0x3333333333333333ULL, },
+ { 0xe38e38e38e38e38eULL, 0x33333333e38e38e3ULL, },
+ { 0x1c71c71c33333333ULL, 0xc71c71c71c71c71cULL, },
+ { 0xe38e38e38e38e38eULL, 0xffffffffe38e38e3ULL, }, /* 48 */
+ { 0xe38e38e38e38e38eULL, 0x00000000e38e38e3ULL, },
+ { 0xaaaaaaaa8e38e38eULL, 0xaaaaaaaaaaaaaaaaULL, },
+ { 0xe38e38e38e38e38eULL, 0x38e38e38e38e38e3ULL, },
+ { 0xcccccccc8e38e38eULL, 0xccccccccccccccccULL, },
+ { 0xe38e38e38e38e38eULL, 0x33333333e38e38e3ULL, },
+ { 0xe38e38e38e38e38eULL, 0x38e38e38e38e38e3ULL, },
+ { 0xe38e38e38e38e38eULL, 0xc71c71c7e38e38e3ULL, },
+ { 0xffffffffffffffffULL, 0xc71c71c7ffffffffULL, }, /* 56 */
+ { 0x0000000000000000ULL, 0xc71c71c700000000ULL, },
+ { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, },
+ { 0x1c71c71c55555555ULL, 0xc71c71c71c71c71cULL, },
+ { 0xccccccccccccccccULL, 0xc71c71c7ccccccccULL, },
+ { 0x1c71c71c33333333ULL, 0xc71c71c71c71c71cULL, },
+ { 0xe38e38e38e38e38eULL, 0xc71c71c7e38e38e3ULL, },
+ { 0x1c71c71c71c71c71ULL, 0xc71c71c71c71c71cULL, },
+ { 0x886ae6cc28625540ULL, 0x4b670b5efe7bb00cULL, }, /* 64 */
+ { 0x886ae6cc28625540ULL, 0x12f7bb1afe7bb00cULL, },
+ { 0x886ae6ccb9cf8b80ULL, 0x27d8c6ffab2b2514ULL, },
+ { 0x886ae6cc28625540ULL, 0x8df188d8a942e2a0ULL, },
+ { 0x886ae6cc28625540ULL, 0x12f7bb1afe7bb00cULL, },
+ { 0xfbbe00634d93c708ULL, 0x12f7bb1a153f52fcULL, },
+ { 0xac5aaeaab9cf8b80ULL, 0x12f7bb1aab2b2514ULL, },
+ { 0xfbbe00634d93c708ULL, 0x8df188d8a942e2a0ULL, },
+ { 0x886ae6ccb9cf8b80ULL, 0x27d8c6ffab2b2514ULL, }, /* 72 */
+ { 0xac5aaeaab9cf8b80ULL, 0x12f7bb1aab2b2514ULL, },
+ { 0xac5aaeaab9cf8b80ULL, 0x27d8c6ffab2b2514ULL, },
+ { 0xac5aaeaab9cf8b80ULL, 0x8df188d8a942e2a0ULL, },
+ { 0x886ae6cc28625540ULL, 0x8df188d8a942e2a0ULL, },
+ { 0xfbbe00634d93c708ULL, 0x8df188d8a942e2a0ULL, },
+ { 0xac5aaeaab9cf8b80ULL, 0x8df188d8a942e2a0ULL, },
+ { 0x704f164d5e31e24eULL, 0x8df188d8a942e2a0ULL, },
+ };
+
+ gettimeofday(&start, NULL);
+
+ for (i = 0; i < PATTERN_INPUTS_SHORT_COUNT; i++) {
+ for (j = 0; j < PATTERN_INPUTS_SHORT_COUNT; j++) {
+ do_msa_MIN_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_MIN_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-max-min/test_msa_min_u_b.c b/tests/tcg/mips/user/ase/msa/int-max-min/test_msa_min_u_b.c
new file mode 100644
index 0000000..1f61145
--- /dev/null
+++ b/tests/tcg/mips/user/ase/msa/int-max-min/test_msa_min_u_b.c
@@ -0,0 +1,153 @@
+/*
+ * Test program for MSA instruction MIN_U.B
+ *
+ * Copyright (C) 2018 Wave Computing, Inc.
+ * Copyright (C) 2018 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.h"
+#include "../../../../include/test_utils.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 = "MIN_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] = {
+ { 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, },
+ { 0x5555555555555555ULL, 0x5555555555555555ULL, },
+ { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, },
+ { 0x3333333333333333ULL, 0x3333333333333333ULL, },
+ { 0xaa8e38aa8e38aa8eULL, 0x38aa8e38aa8e38aaULL, },
+ { 0x1c71aa1c71aa1c71ULL, 0xaa1c71aa1c71aa1cULL, },
+ { 0x5555555555555555ULL, 0x5555555555555555ULL, }, /* 24 */
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x5555555555555555ULL, 0x5555555555555555ULL, },
+ { 0x5555555555555555ULL, 0x5555555555555555ULL, },
+ { 0x5555555555555555ULL, 0x5555555555555555ULL, },
+ { 0x3333333333333333ULL, 0x3333333333333333ULL, },
+ { 0x5555385555385555ULL, 0x3855553855553855ULL, },
+ { 0x1c55551c55551c55ULL, 0x551c55551c55551cULL, },
+ { 0xccccccccccccccccULL, 0xccccccccccccccccULL, }, /* 32 */
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, },
+ { 0x5555555555555555ULL, 0x5555555555555555ULL, },
+ { 0xccccccccccccccccULL, 0xccccccccccccccccULL, },
+ { 0x3333333333333333ULL, 0x3333333333333333ULL, },
+ { 0xcc8e38cc8e38cc8eULL, 0x38cc8e38cc8e38ccULL, },
+ { 0x1c71c71c71c71c71ULL, 0xc71c71c71c71c71cULL, },
+ { 0x3333333333333333ULL, 0x3333333333333333ULL, }, /* 40 */
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x3333333333333333ULL, 0x3333333333333333ULL, },
+ { 0x3333333333333333ULL, 0x3333333333333333ULL, },
+ { 0x3333333333333333ULL, 0x3333333333333333ULL, },
+ { 0x3333333333333333ULL, 0x3333333333333333ULL, },
+ { 0x3333333333333333ULL, 0x3333333333333333ULL, },
+ { 0x1c33331c33331c33ULL, 0x331c33331c33331cULL, },
+ { 0xe38e38e38e38e38eULL, 0x38e38e38e38e38e3ULL, }, /* 48 */
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xaa8e38aa8e38aa8eULL, 0x38aa8e38aa8e38aaULL, },
+ { 0x5555385555385555ULL, 0x3855553855553855ULL, },
+ { 0xcc8e38cc8e38cc8eULL, 0x38cc8e38cc8e38ccULL, },
+ { 0x3333333333333333ULL, 0x3333333333333333ULL, },
+ { 0xe38e38e38e38e38eULL, 0x38e38e38e38e38e3ULL, },
+ { 0x1c71381c71381c71ULL, 0x381c71381c71381cULL, },
+ { 0x1c71c71c71c71c71ULL, 0xc71c71c71c71c71cULL, }, /* 56 */
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x1c71aa1c71aa1c71ULL, 0xaa1c71aa1c71aa1cULL, },
+ { 0x1c55551c55551c55ULL, 0x551c55551c55551cULL, },
+ { 0x1c71c71c71c71c71ULL, 0xc71c71c71c71c71cULL, },
+ { 0x1c33331c33331c33ULL, 0x331c33331c33331cULL, },
+ { 0x1c71381c71381c71ULL, 0x381c71381c71381cULL, },
+ { 0x1c71c71c71c71c71ULL, 0xc71c71c71c71c71cULL, },
+ { 0x886ae6cc28625540ULL, 0x4b670b5efe7bb00cULL, }, /* 64 */
+ { 0x886a006328625508ULL, 0x12670b1a153f520cULL, },
+ { 0x885aaeaa28625540ULL, 0x27670b5eab2b250cULL, },
+ { 0x704f164d28315540ULL, 0x4b670b5ea942b00cULL, },
+ { 0x886a006328625508ULL, 0x12670b1a153f520cULL, },
+ { 0xfbbe00634d93c708ULL, 0x12f7bb1a153f52fcULL, },
+ { 0xac5a00634d938b08ULL, 0x12d8bb1a152b2514ULL, },
+ { 0x704f004d4d31c708ULL, 0x12f1881a153f52a0ULL, },
+ { 0x885aaeaa28625540ULL, 0x27670b5eab2b250cULL, }, /* 72 */
+ { 0xac5a00634d938b08ULL, 0x12d8bb1a152b2514ULL, },
+ { 0xac5aaeaab9cf8b80ULL, 0x27d8c6ffab2b2514ULL, },
+ { 0x704f164d5e318b4eULL, 0x27d888d8a92b2514ULL, },
+ { 0x704f164d28315540ULL, 0x4b670b5ea942b00cULL, },
+ { 0x704f004d4d31c708ULL, 0x12f1881a153f52a0ULL, },
+ { 0x704f164d5e318b4eULL, 0x27d888d8a92b2514ULL, },
+ { 0x704f164d5e31e24eULL, 0x8df188d8a942e2a0ULL, },
+ };
+
+ gettimeofday(&start, NULL);
+
+ for (i = 0; i < PATTERN_INPUTS_SHORT_COUNT; i++) {
+ for (j = 0; j < PATTERN_INPUTS_SHORT_COUNT; j++) {
+ do_msa_MIN_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_MIN_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-max-min/test_msa_min_u_d.c b/tests/tcg/mips/user/ase/msa/int-max-min/test_msa_min_u_d.c
new file mode 100644
index 0000000..4626c62
--- /dev/null
+++ b/tests/tcg/mips/user/ase/msa/int-max-min/test_msa_min_u_d.c
@@ -0,0 +1,153 @@
+/*
+ * Test program for MSA instruction MIN_U.D
+ *
+ * Copyright (C) 2018 Wave Computing, Inc.
+ * Copyright (C) 2018 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.h"
+#include "../../../../include/test_utils.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 = "MIN_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] = {
+ { 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, },
+ { 0x5555555555555555ULL, 0x5555555555555555ULL, },
+ { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, },
+ { 0x3333333333333333ULL, 0x3333333333333333ULL, },
+ { 0xaaaaaaaaaaaaaaaaULL, 0x38e38e38e38e38e3ULL, },
+ { 0x1c71c71c71c71c71ULL, 0xaaaaaaaaaaaaaaaaULL, },
+ { 0x5555555555555555ULL, 0x5555555555555555ULL, }, /* 24 */
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x5555555555555555ULL, 0x5555555555555555ULL, },
+ { 0x5555555555555555ULL, 0x5555555555555555ULL, },
+ { 0x5555555555555555ULL, 0x5555555555555555ULL, },
+ { 0x3333333333333333ULL, 0x3333333333333333ULL, },
+ { 0x5555555555555555ULL, 0x38e38e38e38e38e3ULL, },
+ { 0x1c71c71c71c71c71ULL, 0x5555555555555555ULL, },
+ { 0xccccccccccccccccULL, 0xccccccccccccccccULL, }, /* 32 */
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, },
+ { 0x5555555555555555ULL, 0x5555555555555555ULL, },
+ { 0xccccccccccccccccULL, 0xccccccccccccccccULL, },
+ { 0x3333333333333333ULL, 0x3333333333333333ULL, },
+ { 0xccccccccccccccccULL, 0x38e38e38e38e38e3ULL, },
+ { 0x1c71c71c71c71c71ULL, 0xc71c71c71c71c71cULL, },
+ { 0x3333333333333333ULL, 0x3333333333333333ULL, }, /* 40 */
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x3333333333333333ULL, 0x3333333333333333ULL, },
+ { 0x3333333333333333ULL, 0x3333333333333333ULL, },
+ { 0x3333333333333333ULL, 0x3333333333333333ULL, },
+ { 0x3333333333333333ULL, 0x3333333333333333ULL, },
+ { 0x3333333333333333ULL, 0x3333333333333333ULL, },
+ { 0x1c71c71c71c71c71ULL, 0x3333333333333333ULL, },
+ { 0xe38e38e38e38e38eULL, 0x38e38e38e38e38e3ULL, }, /* 48 */
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xaaaaaaaaaaaaaaaaULL, 0x38e38e38e38e38e3ULL, },
+ { 0x5555555555555555ULL, 0x38e38e38e38e38e3ULL, },
+ { 0xccccccccccccccccULL, 0x38e38e38e38e38e3ULL, },
+ { 0x3333333333333333ULL, 0x3333333333333333ULL, },
+ { 0xe38e38e38e38e38eULL, 0x38e38e38e38e38e3ULL, },
+ { 0x1c71c71c71c71c71ULL, 0x38e38e38e38e38e3ULL, },
+ { 0x1c71c71c71c71c71ULL, 0xc71c71c71c71c71cULL, }, /* 56 */
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x1c71c71c71c71c71ULL, 0xaaaaaaaaaaaaaaaaULL, },
+ { 0x1c71c71c71c71c71ULL, 0x5555555555555555ULL, },
+ { 0x1c71c71c71c71c71ULL, 0xc71c71c71c71c71cULL, },
+ { 0x1c71c71c71c71c71ULL, 0x3333333333333333ULL, },
+ { 0x1c71c71c71c71c71ULL, 0x38e38e38e38e38e3ULL, },
+ { 0x1c71c71c71c71c71ULL, 0xc71c71c71c71c71cULL, },
+ { 0x886ae6cc28625540ULL, 0x4b670b5efe7bb00cULL, }, /* 64 */
+ { 0x886ae6cc28625540ULL, 0x12f7bb1a153f52fcULL, },
+ { 0x886ae6cc28625540ULL, 0x27d8c6ffab2b2514ULL, },
+ { 0x704f164d5e31e24eULL, 0x4b670b5efe7bb00cULL, },
+ { 0x886ae6cc28625540ULL, 0x12f7bb1a153f52fcULL, },
+ { 0xfbbe00634d93c708ULL, 0x12f7bb1a153f52fcULL, },
+ { 0xac5aaeaab9cf8b80ULL, 0x12f7bb1a153f52fcULL, },
+ { 0x704f164d5e31e24eULL, 0x12f7bb1a153f52fcULL, },
+ { 0x886ae6cc28625540ULL, 0x27d8c6ffab2b2514ULL, }, /* 72 */
+ { 0xac5aaeaab9cf8b80ULL, 0x12f7bb1a153f52fcULL, },
+ { 0xac5aaeaab9cf8b80ULL, 0x27d8c6ffab2b2514ULL, },
+ { 0x704f164d5e31e24eULL, 0x27d8c6ffab2b2514ULL, },
+ { 0x704f164d5e31e24eULL, 0x4b670b5efe7bb00cULL, },
+ { 0x704f164d5e31e24eULL, 0x12f7bb1a153f52fcULL, },
+ { 0x704f164d5e31e24eULL, 0x27d8c6ffab2b2514ULL, },
+ { 0x704f164d5e31e24eULL, 0x8df188d8a942e2a0ULL, },
+ };
+
+ gettimeofday(&start, NULL);
+
+ for (i = 0; i < PATTERN_INPUTS_SHORT_COUNT; i++) {
+ for (j = 0; j < PATTERN_INPUTS_SHORT_COUNT; j++) {
+ do_msa_MIN_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_MIN_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-max-min/test_msa_min_u_h.c b/tests/tcg/mips/user/ase/msa/int-max-min/test_msa_min_u_h.c
new file mode 100644
index 0000000..5eeb8d0
--- /dev/null
+++ b/tests/tcg/mips/user/ase/msa/int-max-min/test_msa_min_u_h.c
@@ -0,0 +1,153 @@
+/*
+ * Test program for MSA instruction MIN_U.H
+ *
+ * Copyright (C) 2018 Wave Computing, Inc.
+ * Copyright (C) 2018 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.h"
+#include "../../../../include/test_utils.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 = "MIN_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] = {
+ { 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, },
+ { 0x5555555555555555ULL, 0x5555555555555555ULL, },
+ { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, },
+ { 0x3333333333333333ULL, 0x3333333333333333ULL, },
+ { 0xaaaa38e38e38aaaaULL, 0x38e38e38aaaa38e3ULL, },
+ { 0x1c71aaaa71c71c71ULL, 0xaaaa71c71c71aaaaULL, },
+ { 0x5555555555555555ULL, 0x5555555555555555ULL, }, /* 24 */
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x5555555555555555ULL, 0x5555555555555555ULL, },
+ { 0x5555555555555555ULL, 0x5555555555555555ULL, },
+ { 0x5555555555555555ULL, 0x5555555555555555ULL, },
+ { 0x3333333333333333ULL, 0x3333333333333333ULL, },
+ { 0x555538e355555555ULL, 0x38e35555555538e3ULL, },
+ { 0x1c71555555551c71ULL, 0x555555551c715555ULL, },
+ { 0xccccccccccccccccULL, 0xccccccccccccccccULL, }, /* 32 */
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, },
+ { 0x5555555555555555ULL, 0x5555555555555555ULL, },
+ { 0xccccccccccccccccULL, 0xccccccccccccccccULL, },
+ { 0x3333333333333333ULL, 0x3333333333333333ULL, },
+ { 0xcccc38e38e38ccccULL, 0x38e38e38cccc38e3ULL, },
+ { 0x1c71c71c71c71c71ULL, 0xc71c71c71c71c71cULL, },
+ { 0x3333333333333333ULL, 0x3333333333333333ULL, }, /* 40 */
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x3333333333333333ULL, 0x3333333333333333ULL, },
+ { 0x3333333333333333ULL, 0x3333333333333333ULL, },
+ { 0x3333333333333333ULL, 0x3333333333333333ULL, },
+ { 0x3333333333333333ULL, 0x3333333333333333ULL, },
+ { 0x3333333333333333ULL, 0x3333333333333333ULL, },
+ { 0x1c71333333331c71ULL, 0x333333331c713333ULL, },
+ { 0xe38e38e38e38e38eULL, 0x38e38e38e38e38e3ULL, }, /* 48 */
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xaaaa38e38e38aaaaULL, 0x38e38e38aaaa38e3ULL, },
+ { 0x555538e355555555ULL, 0x38e35555555538e3ULL, },
+ { 0xcccc38e38e38ccccULL, 0x38e38e38cccc38e3ULL, },
+ { 0x3333333333333333ULL, 0x3333333333333333ULL, },
+ { 0xe38e38e38e38e38eULL, 0x38e38e38e38e38e3ULL, },
+ { 0x1c7138e371c71c71ULL, 0x38e371c71c7138e3ULL, },
+ { 0x1c71c71c71c71c71ULL, 0xc71c71c71c71c71cULL, }, /* 56 */
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x1c71aaaa71c71c71ULL, 0xaaaa71c71c71aaaaULL, },
+ { 0x1c71555555551c71ULL, 0x555555551c715555ULL, },
+ { 0x1c71c71c71c71c71ULL, 0xc71c71c71c71c71cULL, },
+ { 0x1c71333333331c71ULL, 0x333333331c713333ULL, },
+ { 0x1c7138e371c71c71ULL, 0x38e371c71c7138e3ULL, },
+ { 0x1c71c71c71c71c71ULL, 0xc71c71c71c71c71cULL, },
+ { 0x886ae6cc28625540ULL, 0x4b670b5efe7bb00cULL, }, /* 64 */
+ { 0x886a006328625540ULL, 0x12f70b5e153f52fcULL, },
+ { 0x886aaeaa28625540ULL, 0x27d80b5eab2b2514ULL, },
+ { 0x704f164d28625540ULL, 0x4b670b5ea942b00cULL, },
+ { 0x886a006328625540ULL, 0x12f70b5e153f52fcULL, },
+ { 0xfbbe00634d93c708ULL, 0x12f7bb1a153f52fcULL, },
+ { 0xac5a00634d938b80ULL, 0x12f7bb1a153f2514ULL, },
+ { 0x704f00634d93c708ULL, 0x12f788d8153f52fcULL, },
+ { 0x886aaeaa28625540ULL, 0x27d80b5eab2b2514ULL, }, /* 72 */
+ { 0xac5a00634d938b80ULL, 0x12f7bb1a153f2514ULL, },
+ { 0xac5aaeaab9cf8b80ULL, 0x27d8c6ffab2b2514ULL, },
+ { 0x704f164d5e318b80ULL, 0x27d888d8a9422514ULL, },
+ { 0x704f164d28625540ULL, 0x4b670b5ea942b00cULL, },
+ { 0x704f00634d93c708ULL, 0x12f788d8153f52fcULL, },
+ { 0x704f164d5e318b80ULL, 0x27d888d8a9422514ULL, },
+ { 0x704f164d5e31e24eULL, 0x8df188d8a942e2a0ULL, },
+ };
+
+ gettimeofday(&start, NULL);
+
+ for (i = 0; i < PATTERN_INPUTS_SHORT_COUNT; i++) {
+ for (j = 0; j < PATTERN_INPUTS_SHORT_COUNT; j++) {
+ do_msa_MIN_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_MIN_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-max-min/test_msa_min_u_w.c b/tests/tcg/mips/user/ase/msa/int-max-min/test_msa_min_u_w.c
new file mode 100644
index 0000000..e70964a
--- /dev/null
+++ b/tests/tcg/mips/user/ase/msa/int-max-min/test_msa_min_u_w.c
@@ -0,0 +1,153 @@
+/*
+ * Test program for MSA instruction MIN_U.W
+ *
+ * Copyright (C) 2018 Wave Computing, Inc.
+ * Copyright (C) 2018 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.h"
+#include "../../../../include/test_utils.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 = "MIN_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] = {
+ { 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, },
+ { 0x5555555555555555ULL, 0x5555555555555555ULL, },
+ { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, },
+ { 0x3333333333333333ULL, 0x3333333333333333ULL, },
+ { 0xaaaaaaaa8e38e38eULL, 0x38e38e38aaaaaaaaULL, },
+ { 0x1c71c71c71c71c71ULL, 0xaaaaaaaa1c71c71cULL, },
+ { 0x5555555555555555ULL, 0x5555555555555555ULL, }, /* 24 */
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x5555555555555555ULL, 0x5555555555555555ULL, },
+ { 0x5555555555555555ULL, 0x5555555555555555ULL, },
+ { 0x5555555555555555ULL, 0x5555555555555555ULL, },
+ { 0x3333333333333333ULL, 0x3333333333333333ULL, },
+ { 0x5555555555555555ULL, 0x38e38e3855555555ULL, },
+ { 0x1c71c71c55555555ULL, 0x555555551c71c71cULL, },
+ { 0xccccccccccccccccULL, 0xccccccccccccccccULL, }, /* 32 */
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, },
+ { 0x5555555555555555ULL, 0x5555555555555555ULL, },
+ { 0xccccccccccccccccULL, 0xccccccccccccccccULL, },
+ { 0x3333333333333333ULL, 0x3333333333333333ULL, },
+ { 0xcccccccc8e38e38eULL, 0x38e38e38ccccccccULL, },
+ { 0x1c71c71c71c71c71ULL, 0xc71c71c71c71c71cULL, },
+ { 0x3333333333333333ULL, 0x3333333333333333ULL, }, /* 40 */
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x3333333333333333ULL, 0x3333333333333333ULL, },
+ { 0x3333333333333333ULL, 0x3333333333333333ULL, },
+ { 0x3333333333333333ULL, 0x3333333333333333ULL, },
+ { 0x3333333333333333ULL, 0x3333333333333333ULL, },
+ { 0x3333333333333333ULL, 0x3333333333333333ULL, },
+ { 0x1c71c71c33333333ULL, 0x333333331c71c71cULL, },
+ { 0xe38e38e38e38e38eULL, 0x38e38e38e38e38e3ULL, }, /* 48 */
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xaaaaaaaa8e38e38eULL, 0x38e38e38aaaaaaaaULL, },
+ { 0x5555555555555555ULL, 0x38e38e3855555555ULL, },
+ { 0xcccccccc8e38e38eULL, 0x38e38e38ccccccccULL, },
+ { 0x3333333333333333ULL, 0x3333333333333333ULL, },
+ { 0xe38e38e38e38e38eULL, 0x38e38e38e38e38e3ULL, },
+ { 0x1c71c71c71c71c71ULL, 0x38e38e381c71c71cULL, },
+ { 0x1c71c71c71c71c71ULL, 0xc71c71c71c71c71cULL, }, /* 56 */
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x1c71c71c71c71c71ULL, 0xaaaaaaaa1c71c71cULL, },
+ { 0x1c71c71c55555555ULL, 0x555555551c71c71cULL, },
+ { 0x1c71c71c71c71c71ULL, 0xc71c71c71c71c71cULL, },
+ { 0x1c71c71c33333333ULL, 0x333333331c71c71cULL, },
+ { 0x1c71c71c71c71c71ULL, 0x38e38e381c71c71cULL, },
+ { 0x1c71c71c71c71c71ULL, 0xc71c71c71c71c71cULL, },
+ { 0x886ae6cc28625540ULL, 0x4b670b5efe7bb00cULL, }, /* 64 */
+ { 0x886ae6cc28625540ULL, 0x12f7bb1a153f52fcULL, },
+ { 0x886ae6cc28625540ULL, 0x27d8c6ffab2b2514ULL, },
+ { 0x704f164d28625540ULL, 0x4b670b5ea942e2a0ULL, },
+ { 0x886ae6cc28625540ULL, 0x12f7bb1a153f52fcULL, },
+ { 0xfbbe00634d93c708ULL, 0x12f7bb1a153f52fcULL, },
+ { 0xac5aaeaa4d93c708ULL, 0x12f7bb1a153f52fcULL, },
+ { 0x704f164d4d93c708ULL, 0x12f7bb1a153f52fcULL, },
+ { 0x886ae6cc28625540ULL, 0x27d8c6ffab2b2514ULL, }, /* 72 */
+ { 0xac5aaeaa4d93c708ULL, 0x12f7bb1a153f52fcULL, },
+ { 0xac5aaeaab9cf8b80ULL, 0x27d8c6ffab2b2514ULL, },
+ { 0x704f164d5e31e24eULL, 0x27d8c6ffa942e2a0ULL, },
+ { 0x704f164d28625540ULL, 0x4b670b5ea942e2a0ULL, },
+ { 0x704f164d4d93c708ULL, 0x12f7bb1a153f52fcULL, },
+ { 0x704f164d5e31e24eULL, 0x27d8c6ffa942e2a0ULL, },
+ { 0x704f164d5e31e24eULL, 0x8df188d8a942e2a0ULL, },
+ };
+
+ gettimeofday(&start, NULL);
+
+ for (i = 0; i < PATTERN_INPUTS_SHORT_COUNT; i++) {
+ for (j = 0; j < PATTERN_INPUTS_SHORT_COUNT; j++) {
+ do_msa_MIN_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_MIN_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/pack/test_msa_pckev_b.c b/tests/tcg/mips/user/ase/msa/pack/test_msa_pckev_b.c
new file mode 100644
index 0000000..d98dd22
--- /dev/null
+++ b/tests/tcg/mips/user/ase/msa/pack/test_msa_pckev_b.c
@@ -0,0 +1,153 @@
+/*
+ * Test program for MSA instruction PCKEV.B
+ *
+ * Copyright (C) 2018 Wave Computing, Inc.
+ * Copyright (C) 2018 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.h"
+#include "../../../../include/test_utils.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 = "PCKEV.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 */
+ { 0x0000000000000000ULL, 0xffffffffffffffffULL, },
+ { 0xaaaaaaaaaaaaaaaaULL, 0xffffffffffffffffULL, },
+ { 0x5555555555555555ULL, 0xffffffffffffffffULL, },
+ { 0xccccccccccccccccULL, 0xffffffffffffffffULL, },
+ { 0x3333333333333333ULL, 0xffffffffffffffffULL, },
+ { 0xe3388ee38ee3388eULL, 0xffffffffffffffffULL, },
+ { 0x1cc7711c711cc771ULL, 0xffffffffffffffffULL, },
+ { 0xffffffffffffffffULL, 0x0000000000000000ULL, }, /* 8 */
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xaaaaaaaaaaaaaaaaULL, 0x0000000000000000ULL, },
+ { 0x5555555555555555ULL, 0x0000000000000000ULL, },
+ { 0xccccccccccccccccULL, 0x0000000000000000ULL, },
+ { 0x3333333333333333ULL, 0x0000000000000000ULL, },
+ { 0xe3388ee38ee3388eULL, 0x0000000000000000ULL, },
+ { 0x1cc7711c711cc771ULL, 0x0000000000000000ULL, },
+ { 0xffffffffffffffffULL, 0xaaaaaaaaaaaaaaaaULL, }, /* 16 */
+ { 0x0000000000000000ULL, 0xaaaaaaaaaaaaaaaaULL, },
+ { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, },
+ { 0x5555555555555555ULL, 0xaaaaaaaaaaaaaaaaULL, },
+ { 0xccccccccccccccccULL, 0xaaaaaaaaaaaaaaaaULL, },
+ { 0x3333333333333333ULL, 0xaaaaaaaaaaaaaaaaULL, },
+ { 0xe3388ee38ee3388eULL, 0xaaaaaaaaaaaaaaaaULL, },
+ { 0x1cc7711c711cc771ULL, 0xaaaaaaaaaaaaaaaaULL, },
+ { 0xffffffffffffffffULL, 0x5555555555555555ULL, }, /* 24 */
+ { 0x0000000000000000ULL, 0x5555555555555555ULL, },
+ { 0xaaaaaaaaaaaaaaaaULL, 0x5555555555555555ULL, },
+ { 0x5555555555555555ULL, 0x5555555555555555ULL, },
+ { 0xccccccccccccccccULL, 0x5555555555555555ULL, },
+ { 0x3333333333333333ULL, 0x5555555555555555ULL, },
+ { 0xe3388ee38ee3388eULL, 0x5555555555555555ULL, },
+ { 0x1cc7711c711cc771ULL, 0x5555555555555555ULL, },
+ { 0xffffffffffffffffULL, 0xccccccccccccccccULL, }, /* 32 */
+ { 0x0000000000000000ULL, 0xccccccccccccccccULL, },
+ { 0xaaaaaaaaaaaaaaaaULL, 0xccccccccccccccccULL, },
+ { 0x5555555555555555ULL, 0xccccccccccccccccULL, },
+ { 0xccccccccccccccccULL, 0xccccccccccccccccULL, },
+ { 0x3333333333333333ULL, 0xccccccccccccccccULL, },
+ { 0xe3388ee38ee3388eULL, 0xccccccccccccccccULL, },
+ { 0x1cc7711c711cc771ULL, 0xccccccccccccccccULL, },
+ { 0xffffffffffffffffULL, 0x3333333333333333ULL, }, /* 40 */
+ { 0x0000000000000000ULL, 0x3333333333333333ULL, },
+ { 0xaaaaaaaaaaaaaaaaULL, 0x3333333333333333ULL, },
+ { 0x5555555555555555ULL, 0x3333333333333333ULL, },
+ { 0xccccccccccccccccULL, 0x3333333333333333ULL, },
+ { 0x3333333333333333ULL, 0x3333333333333333ULL, },
+ { 0xe3388ee38ee3388eULL, 0x3333333333333333ULL, },
+ { 0x1cc7711c711cc771ULL, 0x3333333333333333ULL, },
+ { 0xffffffffffffffffULL, 0xe3388ee38ee3388eULL, }, /* 48 */
+ { 0x0000000000000000ULL, 0xe3388ee38ee3388eULL, },
+ { 0xaaaaaaaaaaaaaaaaULL, 0xe3388ee38ee3388eULL, },
+ { 0x5555555555555555ULL, 0xe3388ee38ee3388eULL, },
+ { 0xccccccccccccccccULL, 0xe3388ee38ee3388eULL, },
+ { 0x3333333333333333ULL, 0xe3388ee38ee3388eULL, },
+ { 0xe3388ee38ee3388eULL, 0xe3388ee38ee3388eULL, },
+ { 0x1cc7711c711cc771ULL, 0xe3388ee38ee3388eULL, },
+ { 0xffffffffffffffffULL, 0x1cc7711c711cc771ULL, }, /* 56 */
+ { 0x0000000000000000ULL, 0x1cc7711c711cc771ULL, },
+ { 0xaaaaaaaaaaaaaaaaULL, 0x1cc7711c711cc771ULL, },
+ { 0x5555555555555555ULL, 0x1cc7711c711cc771ULL, },
+ { 0xccccccccccccccccULL, 0x1cc7711c711cc771ULL, },
+ { 0x3333333333333333ULL, 0x1cc7711c711cc771ULL, },
+ { 0xe3388ee38ee3388eULL, 0x1cc7711c711cc771ULL, },
+ { 0x1cc7711c711cc771ULL, 0x1cc7711c711cc771ULL, },
+ { 0x675e7b0c6acc6240ULL, 0x675e7b0c6acc6240ULL, }, /* 64 */
+ { 0xf71a3ffcbe639308ULL, 0x675e7b0c6acc6240ULL, },
+ { 0xd8ff2b145aaacf80ULL, 0x675e7b0c6acc6240ULL, },
+ { 0xf1d842a04f4d314eULL, 0x675e7b0c6acc6240ULL, },
+ { 0x675e7b0c6acc6240ULL, 0xf71a3ffcbe639308ULL, },
+ { 0xf71a3ffcbe639308ULL, 0xf71a3ffcbe639308ULL, },
+ { 0xd8ff2b145aaacf80ULL, 0xf71a3ffcbe639308ULL, },
+ { 0xf1d842a04f4d314eULL, 0xf71a3ffcbe639308ULL, },
+ { 0x675e7b0c6acc6240ULL, 0xd8ff2b145aaacf80ULL, }, /* 72 */
+ { 0xf71a3ffcbe639308ULL, 0xd8ff2b145aaacf80ULL, },
+ { 0xd8ff2b145aaacf80ULL, 0xd8ff2b145aaacf80ULL, },
+ { 0xf1d842a04f4d314eULL, 0xd8ff2b145aaacf80ULL, },
+ { 0x675e7b0c6acc6240ULL, 0xf1d842a04f4d314eULL, },
+ { 0xf71a3ffcbe639308ULL, 0xf1d842a04f4d314eULL, },
+ { 0xd8ff2b145aaacf80ULL, 0xf1d842a04f4d314eULL, },
+ { 0xf1d842a04f4d314eULL, 0xf1d842a04f4d314eULL, },
+ };
+
+ gettimeofday(&start, NULL);
+
+ for (i = 0; i < PATTERN_INPUTS_SHORT_COUNT; i++) {
+ for (j = 0; j < PATTERN_INPUTS_SHORT_COUNT; j++) {
+ do_msa_PCKEV_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_PCKEV_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/pack/test_msa_pckev_d.c b/tests/tcg/mips/user/ase/msa/pack/test_msa_pckev_d.c
new file mode 100644
index 0000000..543fb6a
--- /dev/null
+++ b/tests/tcg/mips/user/ase/msa/pack/test_msa_pckev_d.c
@@ -0,0 +1,153 @@
+/*
+ * Test program for MSA instruction PCKEV.D
+ *
+ * Copyright (C) 2018 Wave Computing, Inc.
+ * Copyright (C) 2018 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.h"
+#include "../../../../include/test_utils.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 = "PCKEV.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, 0xffffffffffffffffULL, },
+ { 0xaaaaaaaaaaaaaaaaULL, 0xffffffffffffffffULL, },
+ { 0x5555555555555555ULL, 0xffffffffffffffffULL, },
+ { 0xccccccccccccccccULL, 0xffffffffffffffffULL, },
+ { 0x3333333333333333ULL, 0xffffffffffffffffULL, },
+ { 0xe38e38e38e38e38eULL, 0xffffffffffffffffULL, },
+ { 0x1c71c71c71c71c71ULL, 0xffffffffffffffffULL, },
+ { 0xffffffffffffffffULL, 0x0000000000000000ULL, }, /* 8 */
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xaaaaaaaaaaaaaaaaULL, 0x0000000000000000ULL, },
+ { 0x5555555555555555ULL, 0x0000000000000000ULL, },
+ { 0xccccccccccccccccULL, 0x0000000000000000ULL, },
+ { 0x3333333333333333ULL, 0x0000000000000000ULL, },
+ { 0xe38e38e38e38e38eULL, 0x0000000000000000ULL, },
+ { 0x1c71c71c71c71c71ULL, 0x0000000000000000ULL, },
+ { 0xffffffffffffffffULL, 0xaaaaaaaaaaaaaaaaULL, }, /* 16 */
+ { 0x0000000000000000ULL, 0xaaaaaaaaaaaaaaaaULL, },
+ { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, },
+ { 0x5555555555555555ULL, 0xaaaaaaaaaaaaaaaaULL, },
+ { 0xccccccccccccccccULL, 0xaaaaaaaaaaaaaaaaULL, },
+ { 0x3333333333333333ULL, 0xaaaaaaaaaaaaaaaaULL, },
+ { 0xe38e38e38e38e38eULL, 0xaaaaaaaaaaaaaaaaULL, },
+ { 0x1c71c71c71c71c71ULL, 0xaaaaaaaaaaaaaaaaULL, },
+ { 0xffffffffffffffffULL, 0x5555555555555555ULL, }, /* 24 */
+ { 0x0000000000000000ULL, 0x5555555555555555ULL, },
+ { 0xaaaaaaaaaaaaaaaaULL, 0x5555555555555555ULL, },
+ { 0x5555555555555555ULL, 0x5555555555555555ULL, },
+ { 0xccccccccccccccccULL, 0x5555555555555555ULL, },
+ { 0x3333333333333333ULL, 0x5555555555555555ULL, },
+ { 0xe38e38e38e38e38eULL, 0x5555555555555555ULL, },
+ { 0x1c71c71c71c71c71ULL, 0x5555555555555555ULL, },
+ { 0xffffffffffffffffULL, 0xccccccccccccccccULL, }, /* 32 */
+ { 0x0000000000000000ULL, 0xccccccccccccccccULL, },
+ { 0xaaaaaaaaaaaaaaaaULL, 0xccccccccccccccccULL, },
+ { 0x5555555555555555ULL, 0xccccccccccccccccULL, },
+ { 0xccccccccccccccccULL, 0xccccccccccccccccULL, },
+ { 0x3333333333333333ULL, 0xccccccccccccccccULL, },
+ { 0xe38e38e38e38e38eULL, 0xccccccccccccccccULL, },
+ { 0x1c71c71c71c71c71ULL, 0xccccccccccccccccULL, },
+ { 0xffffffffffffffffULL, 0x3333333333333333ULL, }, /* 40 */
+ { 0x0000000000000000ULL, 0x3333333333333333ULL, },
+ { 0xaaaaaaaaaaaaaaaaULL, 0x3333333333333333ULL, },
+ { 0x5555555555555555ULL, 0x3333333333333333ULL, },
+ { 0xccccccccccccccccULL, 0x3333333333333333ULL, },
+ { 0x3333333333333333ULL, 0x3333333333333333ULL, },
+ { 0xe38e38e38e38e38eULL, 0x3333333333333333ULL, },
+ { 0x1c71c71c71c71c71ULL, 0x3333333333333333ULL, },
+ { 0xffffffffffffffffULL, 0xe38e38e38e38e38eULL, }, /* 48 */
+ { 0x0000000000000000ULL, 0xe38e38e38e38e38eULL, },
+ { 0xaaaaaaaaaaaaaaaaULL, 0xe38e38e38e38e38eULL, },
+ { 0x5555555555555555ULL, 0xe38e38e38e38e38eULL, },
+ { 0xccccccccccccccccULL, 0xe38e38e38e38e38eULL, },
+ { 0x3333333333333333ULL, 0xe38e38e38e38e38eULL, },
+ { 0xe38e38e38e38e38eULL, 0xe38e38e38e38e38eULL, },
+ { 0x1c71c71c71c71c71ULL, 0xe38e38e38e38e38eULL, },
+ { 0xffffffffffffffffULL, 0x1c71c71c71c71c71ULL, }, /* 56 */
+ { 0x0000000000000000ULL, 0x1c71c71c71c71c71ULL, },
+ { 0xaaaaaaaaaaaaaaaaULL, 0x1c71c71c71c71c71ULL, },
+ { 0x5555555555555555ULL, 0x1c71c71c71c71c71ULL, },
+ { 0xccccccccccccccccULL, 0x1c71c71c71c71c71ULL, },
+ { 0x3333333333333333ULL, 0x1c71c71c71c71c71ULL, },
+ { 0xe38e38e38e38e38eULL, 0x1c71c71c71c71c71ULL, },
+ { 0x1c71c71c71c71c71ULL, 0x1c71c71c71c71c71ULL, },
+ { 0x886ae6cc28625540ULL, 0x886ae6cc28625540ULL, }, /* 64 */
+ { 0xfbbe00634d93c708ULL, 0x886ae6cc28625540ULL, },
+ { 0xac5aaeaab9cf8b80ULL, 0x886ae6cc28625540ULL, },
+ { 0x704f164d5e31e24eULL, 0x886ae6cc28625540ULL, },
+ { 0x886ae6cc28625540ULL, 0xfbbe00634d93c708ULL, },
+ { 0xfbbe00634d93c708ULL, 0xfbbe00634d93c708ULL, },
+ { 0xac5aaeaab9cf8b80ULL, 0xfbbe00634d93c708ULL, },
+ { 0x704f164d5e31e24eULL, 0xfbbe00634d93c708ULL, },
+ { 0x886ae6cc28625540ULL, 0xac5aaeaab9cf8b80ULL, }, /* 72 */
+ { 0xfbbe00634d93c708ULL, 0xac5aaeaab9cf8b80ULL, },
+ { 0xac5aaeaab9cf8b80ULL, 0xac5aaeaab9cf8b80ULL, },
+ { 0x704f164d5e31e24eULL, 0xac5aaeaab9cf8b80ULL, },
+ { 0x886ae6cc28625540ULL, 0x704f164d5e31e24eULL, },
+ { 0xfbbe00634d93c708ULL, 0x704f164d5e31e24eULL, },
+ { 0xac5aaeaab9cf8b80ULL, 0x704f164d5e31e24eULL, },
+ { 0x704f164d5e31e24eULL, 0x704f164d5e31e24eULL, },
+ };
+
+ gettimeofday(&start, NULL);
+
+ for (i = 0; i < PATTERN_INPUTS_SHORT_COUNT; i++) {
+ for (j = 0; j < PATTERN_INPUTS_SHORT_COUNT; j++) {
+ do_msa_PCKEV_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_PCKEV_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/pack/test_msa_pckev_h.c b/tests/tcg/mips/user/ase/msa/pack/test_msa_pckev_h.c
new file mode 100644
index 0000000..64a18c0
--- /dev/null
+++ b/tests/tcg/mips/user/ase/msa/pack/test_msa_pckev_h.c
@@ -0,0 +1,153 @@
+/*
+ * Test program for MSA instruction PCKEV.H
+ *
+ * Copyright (C) 2018 Wave Computing, Inc.
+ * Copyright (C) 2018 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.h"
+#include "../../../../include/test_utils.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 = "PCKEV.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 */
+ { 0x0000000000000000ULL, 0xffffffffffffffffULL, },
+ { 0xaaaaaaaaaaaaaaaaULL, 0xffffffffffffffffULL, },
+ { 0x5555555555555555ULL, 0xffffffffffffffffULL, },
+ { 0xccccccccccccccccULL, 0xffffffffffffffffULL, },
+ { 0x3333333333333333ULL, 0xffffffffffffffffULL, },
+ { 0x8e3838e338e3e38eULL, 0xffffffffffffffffULL, },
+ { 0x71c7c71cc71c1c71ULL, 0xffffffffffffffffULL, },
+ { 0xffffffffffffffffULL, 0x0000000000000000ULL, }, /* 8 */
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xaaaaaaaaaaaaaaaaULL, 0x0000000000000000ULL, },
+ { 0x5555555555555555ULL, 0x0000000000000000ULL, },
+ { 0xccccccccccccccccULL, 0x0000000000000000ULL, },
+ { 0x3333333333333333ULL, 0x0000000000000000ULL, },
+ { 0x8e3838e338e3e38eULL, 0x0000000000000000ULL, },
+ { 0x71c7c71cc71c1c71ULL, 0x0000000000000000ULL, },
+ { 0xffffffffffffffffULL, 0xaaaaaaaaaaaaaaaaULL, }, /* 16 */
+ { 0x0000000000000000ULL, 0xaaaaaaaaaaaaaaaaULL, },
+ { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, },
+ { 0x5555555555555555ULL, 0xaaaaaaaaaaaaaaaaULL, },
+ { 0xccccccccccccccccULL, 0xaaaaaaaaaaaaaaaaULL, },
+ { 0x3333333333333333ULL, 0xaaaaaaaaaaaaaaaaULL, },
+ { 0x8e3838e338e3e38eULL, 0xaaaaaaaaaaaaaaaaULL, },
+ { 0x71c7c71cc71c1c71ULL, 0xaaaaaaaaaaaaaaaaULL, },
+ { 0xffffffffffffffffULL, 0x5555555555555555ULL, }, /* 24 */
+ { 0x0000000000000000ULL, 0x5555555555555555ULL, },
+ { 0xaaaaaaaaaaaaaaaaULL, 0x5555555555555555ULL, },
+ { 0x5555555555555555ULL, 0x5555555555555555ULL, },
+ { 0xccccccccccccccccULL, 0x5555555555555555ULL, },
+ { 0x3333333333333333ULL, 0x5555555555555555ULL, },
+ { 0x8e3838e338e3e38eULL, 0x5555555555555555ULL, },
+ { 0x71c7c71cc71c1c71ULL, 0x5555555555555555ULL, },
+ { 0xffffffffffffffffULL, 0xccccccccccccccccULL, }, /* 32 */
+ { 0x0000000000000000ULL, 0xccccccccccccccccULL, },
+ { 0xaaaaaaaaaaaaaaaaULL, 0xccccccccccccccccULL, },
+ { 0x5555555555555555ULL, 0xccccccccccccccccULL, },
+ { 0xccccccccccccccccULL, 0xccccccccccccccccULL, },
+ { 0x3333333333333333ULL, 0xccccccccccccccccULL, },
+ { 0x8e3838e338e3e38eULL, 0xccccccccccccccccULL, },
+ { 0x71c7c71cc71c1c71ULL, 0xccccccccccccccccULL, },
+ { 0xffffffffffffffffULL, 0x3333333333333333ULL, }, /* 40 */
+ { 0x0000000000000000ULL, 0x3333333333333333ULL, },
+ { 0xaaaaaaaaaaaaaaaaULL, 0x3333333333333333ULL, },
+ { 0x5555555555555555ULL, 0x3333333333333333ULL, },
+ { 0xccccccccccccccccULL, 0x3333333333333333ULL, },
+ { 0x3333333333333333ULL, 0x3333333333333333ULL, },
+ { 0x8e3838e338e3e38eULL, 0x3333333333333333ULL, },
+ { 0x71c7c71cc71c1c71ULL, 0x3333333333333333ULL, },
+ { 0xffffffffffffffffULL, 0x8e3838e338e3e38eULL, }, /* 48 */
+ { 0x0000000000000000ULL, 0x8e3838e338e3e38eULL, },
+ { 0xaaaaaaaaaaaaaaaaULL, 0x8e3838e338e3e38eULL, },
+ { 0x5555555555555555ULL, 0x8e3838e338e3e38eULL, },
+ { 0xccccccccccccccccULL, 0x8e3838e338e3e38eULL, },
+ { 0x3333333333333333ULL, 0x8e3838e338e3e38eULL, },
+ { 0x8e3838e338e3e38eULL, 0x8e3838e338e3e38eULL, },
+ { 0x71c7c71cc71c1c71ULL, 0x8e3838e338e3e38eULL, },
+ { 0xffffffffffffffffULL, 0x71c7c71cc71c1c71ULL, }, /* 56 */
+ { 0x0000000000000000ULL, 0x71c7c71cc71c1c71ULL, },
+ { 0xaaaaaaaaaaaaaaaaULL, 0x71c7c71cc71c1c71ULL, },
+ { 0x5555555555555555ULL, 0x71c7c71cc71c1c71ULL, },
+ { 0xccccccccccccccccULL, 0x71c7c71cc71c1c71ULL, },
+ { 0x3333333333333333ULL, 0x71c7c71cc71c1c71ULL, },
+ { 0x8e3838e338e3e38eULL, 0x71c7c71cc71c1c71ULL, },
+ { 0x71c7c71cc71c1c71ULL, 0x71c7c71cc71c1c71ULL, },
+ { 0x0b5eb00ce6cc5540ULL, 0x0b5eb00ce6cc5540ULL, }, /* 64 */
+ { 0xbb1a52fc0063c708ULL, 0x0b5eb00ce6cc5540ULL, },
+ { 0xc6ff2514aeaa8b80ULL, 0x0b5eb00ce6cc5540ULL, },
+ { 0x88d8e2a0164de24eULL, 0x0b5eb00ce6cc5540ULL, },
+ { 0x0b5eb00ce6cc5540ULL, 0xbb1a52fc0063c708ULL, },
+ { 0xbb1a52fc0063c708ULL, 0xbb1a52fc0063c708ULL, },
+ { 0xc6ff2514aeaa8b80ULL, 0xbb1a52fc0063c708ULL, },
+ { 0x88d8e2a0164de24eULL, 0xbb1a52fc0063c708ULL, },
+ { 0x0b5eb00ce6cc5540ULL, 0xc6ff2514aeaa8b80ULL, }, /* 72 */
+ { 0xbb1a52fc0063c708ULL, 0xc6ff2514aeaa8b80ULL, },
+ { 0xc6ff2514aeaa8b80ULL, 0xc6ff2514aeaa8b80ULL, },
+ { 0x88d8e2a0164de24eULL, 0xc6ff2514aeaa8b80ULL, },
+ { 0x0b5eb00ce6cc5540ULL, 0x88d8e2a0164de24eULL, },
+ { 0xbb1a52fc0063c708ULL, 0x88d8e2a0164de24eULL, },
+ { 0xc6ff2514aeaa8b80ULL, 0x88d8e2a0164de24eULL, },
+ { 0x88d8e2a0164de24eULL, 0x88d8e2a0164de24eULL, },
+ };
+
+ gettimeofday(&start, NULL);
+
+ for (i = 0; i < PATTERN_INPUTS_SHORT_COUNT; i++) {
+ for (j = 0; j < PATTERN_INPUTS_SHORT_COUNT; j++) {
+ do_msa_PCKEV_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_PCKEV_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/pack/test_msa_pckev_w.c b/tests/tcg/mips/user/ase/msa/pack/test_msa_pckev_w.c
new file mode 100644
index 0000000..a0acacd
--- /dev/null
+++ b/tests/tcg/mips/user/ase/msa/pack/test_msa_pckev_w.c
@@ -0,0 +1,153 @@
+/*
+ * Test program for MSA instruction PCKEV.W
+ *
+ * Copyright (C) 2018 Wave Computing, Inc.
+ * Copyright (C) 2018 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.h"
+#include "../../../../include/test_utils.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 = "PCKEV.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, 0xffffffffffffffffULL, },
+ { 0xaaaaaaaaaaaaaaaaULL, 0xffffffffffffffffULL, },
+ { 0x5555555555555555ULL, 0xffffffffffffffffULL, },
+ { 0xccccccccccccccccULL, 0xffffffffffffffffULL, },
+ { 0x3333333333333333ULL, 0xffffffffffffffffULL, },
+ { 0xe38e38e38e38e38eULL, 0xffffffffffffffffULL, },
+ { 0x1c71c71c71c71c71ULL, 0xffffffffffffffffULL, },
+ { 0xffffffffffffffffULL, 0x0000000000000000ULL, }, /* 8 */
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xaaaaaaaaaaaaaaaaULL, 0x0000000000000000ULL, },
+ { 0x5555555555555555ULL, 0x0000000000000000ULL, },
+ { 0xccccccccccccccccULL, 0x0000000000000000ULL, },
+ { 0x3333333333333333ULL, 0x0000000000000000ULL, },
+ { 0xe38e38e38e38e38eULL, 0x0000000000000000ULL, },
+ { 0x1c71c71c71c71c71ULL, 0x0000000000000000ULL, },
+ { 0xffffffffffffffffULL, 0xaaaaaaaaaaaaaaaaULL, }, /* 16 */
+ { 0x0000000000000000ULL, 0xaaaaaaaaaaaaaaaaULL, },
+ { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, },
+ { 0x5555555555555555ULL, 0xaaaaaaaaaaaaaaaaULL, },
+ { 0xccccccccccccccccULL, 0xaaaaaaaaaaaaaaaaULL, },
+ { 0x3333333333333333ULL, 0xaaaaaaaaaaaaaaaaULL, },
+ { 0xe38e38e38e38e38eULL, 0xaaaaaaaaaaaaaaaaULL, },
+ { 0x1c71c71c71c71c71ULL, 0xaaaaaaaaaaaaaaaaULL, },
+ { 0xffffffffffffffffULL, 0x5555555555555555ULL, }, /* 24 */
+ { 0x0000000000000000ULL, 0x5555555555555555ULL, },
+ { 0xaaaaaaaaaaaaaaaaULL, 0x5555555555555555ULL, },
+ { 0x5555555555555555ULL, 0x5555555555555555ULL, },
+ { 0xccccccccccccccccULL, 0x5555555555555555ULL, },
+ { 0x3333333333333333ULL, 0x5555555555555555ULL, },
+ { 0xe38e38e38e38e38eULL, 0x5555555555555555ULL, },
+ { 0x1c71c71c71c71c71ULL, 0x5555555555555555ULL, },
+ { 0xffffffffffffffffULL, 0xccccccccccccccccULL, }, /* 32 */
+ { 0x0000000000000000ULL, 0xccccccccccccccccULL, },
+ { 0xaaaaaaaaaaaaaaaaULL, 0xccccccccccccccccULL, },
+ { 0x5555555555555555ULL, 0xccccccccccccccccULL, },
+ { 0xccccccccccccccccULL, 0xccccccccccccccccULL, },
+ { 0x3333333333333333ULL, 0xccccccccccccccccULL, },
+ { 0xe38e38e38e38e38eULL, 0xccccccccccccccccULL, },
+ { 0x1c71c71c71c71c71ULL, 0xccccccccccccccccULL, },
+ { 0xffffffffffffffffULL, 0x3333333333333333ULL, }, /* 40 */
+ { 0x0000000000000000ULL, 0x3333333333333333ULL, },
+ { 0xaaaaaaaaaaaaaaaaULL, 0x3333333333333333ULL, },
+ { 0x5555555555555555ULL, 0x3333333333333333ULL, },
+ { 0xccccccccccccccccULL, 0x3333333333333333ULL, },
+ { 0x3333333333333333ULL, 0x3333333333333333ULL, },
+ { 0xe38e38e38e38e38eULL, 0x3333333333333333ULL, },
+ { 0x1c71c71c71c71c71ULL, 0x3333333333333333ULL, },
+ { 0xffffffffffffffffULL, 0xe38e38e38e38e38eULL, }, /* 48 */
+ { 0x0000000000000000ULL, 0xe38e38e38e38e38eULL, },
+ { 0xaaaaaaaaaaaaaaaaULL, 0xe38e38e38e38e38eULL, },
+ { 0x5555555555555555ULL, 0xe38e38e38e38e38eULL, },
+ { 0xccccccccccccccccULL, 0xe38e38e38e38e38eULL, },
+ { 0x3333333333333333ULL, 0xe38e38e38e38e38eULL, },
+ { 0xe38e38e38e38e38eULL, 0xe38e38e38e38e38eULL, },
+ { 0x1c71c71c71c71c71ULL, 0xe38e38e38e38e38eULL, },
+ { 0xffffffffffffffffULL, 0x1c71c71c71c71c71ULL, }, /* 56 */
+ { 0x0000000000000000ULL, 0x1c71c71c71c71c71ULL, },
+ { 0xaaaaaaaaaaaaaaaaULL, 0x1c71c71c71c71c71ULL, },
+ { 0x5555555555555555ULL, 0x1c71c71c71c71c71ULL, },
+ { 0xccccccccccccccccULL, 0x1c71c71c71c71c71ULL, },
+ { 0x3333333333333333ULL, 0x1c71c71c71c71c71ULL, },
+ { 0xe38e38e38e38e38eULL, 0x1c71c71c71c71c71ULL, },
+ { 0x1c71c71c71c71c71ULL, 0x1c71c71c71c71c71ULL, },
+ { 0xfe7bb00c28625540ULL, 0xfe7bb00c28625540ULL, }, /* 64 */
+ { 0x153f52fc4d93c708ULL, 0xfe7bb00c28625540ULL, },
+ { 0xab2b2514b9cf8b80ULL, 0xfe7bb00c28625540ULL, },
+ { 0xa942e2a05e31e24eULL, 0xfe7bb00c28625540ULL, },
+ { 0xfe7bb00c28625540ULL, 0x153f52fc4d93c708ULL, },
+ { 0x153f52fc4d93c708ULL, 0x153f52fc4d93c708ULL, },
+ { 0xab2b2514b9cf8b80ULL, 0x153f52fc4d93c708ULL, },
+ { 0xa942e2a05e31e24eULL, 0x153f52fc4d93c708ULL, },
+ { 0xfe7bb00c28625540ULL, 0xab2b2514b9cf8b80ULL, }, /* 72 */
+ { 0x153f52fc4d93c708ULL, 0xab2b2514b9cf8b80ULL, },
+ { 0xab2b2514b9cf8b80ULL, 0xab2b2514b9cf8b80ULL, },
+ { 0xa942e2a05e31e24eULL, 0xab2b2514b9cf8b80ULL, },
+ { 0xfe7bb00c28625540ULL, 0xa942e2a05e31e24eULL, },
+ { 0x153f52fc4d93c708ULL, 0xa942e2a05e31e24eULL, },
+ { 0xab2b2514b9cf8b80ULL, 0xa942e2a05e31e24eULL, },
+ { 0xa942e2a05e31e24eULL, 0xa942e2a05e31e24eULL, },
+ };
+
+ gettimeofday(&start, NULL);
+
+ for (i = 0; i < PATTERN_INPUTS_SHORT_COUNT; i++) {
+ for (j = 0; j < PATTERN_INPUTS_SHORT_COUNT; j++) {
+ do_msa_PCKEV_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_PCKEV_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/pack/test_msa_pckod_b.c b/tests/tcg/mips/user/ase/msa/pack/test_msa_pckod_b.c
new file mode 100644
index 0000000..7bf86fc
--- /dev/null
+++ b/tests/tcg/mips/user/ase/msa/pack/test_msa_pckod_b.c
@@ -0,0 +1,153 @@
+/*
+ * Test program for MSA instruction PCKOD.B
+ *
+ * Copyright (C) 2018 Wave Computing, Inc.
+ * Copyright (C) 2018 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.h"
+#include "../../../../include/test_utils.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 = "PCKOD.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 */
+ { 0x0000000000000000ULL, 0xffffffffffffffffULL, },
+ { 0xaaaaaaaaaaaaaaaaULL, 0xffffffffffffffffULL, },
+ { 0x5555555555555555ULL, 0xffffffffffffffffULL, },
+ { 0xccccccccccccccccULL, 0xffffffffffffffffULL, },
+ { 0x3333333333333333ULL, 0xffffffffffffffffULL, },
+ { 0x388ee338e3388ee3ULL, 0xffffffffffffffffULL, },
+ { 0xc7711cc71cc7711cULL, 0xffffffffffffffffULL, },
+ { 0xffffffffffffffffULL, 0x0000000000000000ULL, }, /* 8 */
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xaaaaaaaaaaaaaaaaULL, 0x0000000000000000ULL, },
+ { 0x5555555555555555ULL, 0x0000000000000000ULL, },
+ { 0xccccccccccccccccULL, 0x0000000000000000ULL, },
+ { 0x3333333333333333ULL, 0x0000000000000000ULL, },
+ { 0x388ee338e3388ee3ULL, 0x0000000000000000ULL, },
+ { 0xc7711cc71cc7711cULL, 0x0000000000000000ULL, },
+ { 0xffffffffffffffffULL, 0xaaaaaaaaaaaaaaaaULL, }, /* 16 */
+ { 0x0000000000000000ULL, 0xaaaaaaaaaaaaaaaaULL, },
+ { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, },
+ { 0x5555555555555555ULL, 0xaaaaaaaaaaaaaaaaULL, },
+ { 0xccccccccccccccccULL, 0xaaaaaaaaaaaaaaaaULL, },
+ { 0x3333333333333333ULL, 0xaaaaaaaaaaaaaaaaULL, },
+ { 0x388ee338e3388ee3ULL, 0xaaaaaaaaaaaaaaaaULL, },
+ { 0xc7711cc71cc7711cULL, 0xaaaaaaaaaaaaaaaaULL, },
+ { 0xffffffffffffffffULL, 0x5555555555555555ULL, }, /* 24 */
+ { 0x0000000000000000ULL, 0x5555555555555555ULL, },
+ { 0xaaaaaaaaaaaaaaaaULL, 0x5555555555555555ULL, },
+ { 0x5555555555555555ULL, 0x5555555555555555ULL, },
+ { 0xccccccccccccccccULL, 0x5555555555555555ULL, },
+ { 0x3333333333333333ULL, 0x5555555555555555ULL, },
+ { 0x388ee338e3388ee3ULL, 0x5555555555555555ULL, },
+ { 0xc7711cc71cc7711cULL, 0x5555555555555555ULL, },
+ { 0xffffffffffffffffULL, 0xccccccccccccccccULL, }, /* 32 */
+ { 0x0000000000000000ULL, 0xccccccccccccccccULL, },
+ { 0xaaaaaaaaaaaaaaaaULL, 0xccccccccccccccccULL, },
+ { 0x5555555555555555ULL, 0xccccccccccccccccULL, },
+ { 0xccccccccccccccccULL, 0xccccccccccccccccULL, },
+ { 0x3333333333333333ULL, 0xccccccccccccccccULL, },
+ { 0x388ee338e3388ee3ULL, 0xccccccccccccccccULL, },
+ { 0xc7711cc71cc7711cULL, 0xccccccccccccccccULL, },
+ { 0xffffffffffffffffULL, 0x3333333333333333ULL, }, /* 40 */
+ { 0x0000000000000000ULL, 0x3333333333333333ULL, },
+ { 0xaaaaaaaaaaaaaaaaULL, 0x3333333333333333ULL, },
+ { 0x5555555555555555ULL, 0x3333333333333333ULL, },
+ { 0xccccccccccccccccULL, 0x3333333333333333ULL, },
+ { 0x3333333333333333ULL, 0x3333333333333333ULL, },
+ { 0x388ee338e3388ee3ULL, 0x3333333333333333ULL, },
+ { 0xc7711cc71cc7711cULL, 0x3333333333333333ULL, },
+ { 0xffffffffffffffffULL, 0x388ee338e3388ee3ULL, }, /* 48 */
+ { 0x0000000000000000ULL, 0x388ee338e3388ee3ULL, },
+ { 0xaaaaaaaaaaaaaaaaULL, 0x388ee338e3388ee3ULL, },
+ { 0x5555555555555555ULL, 0x388ee338e3388ee3ULL, },
+ { 0xccccccccccccccccULL, 0x388ee338e3388ee3ULL, },
+ { 0x3333333333333333ULL, 0x388ee338e3388ee3ULL, },
+ { 0x388ee338e3388ee3ULL, 0x388ee338e3388ee3ULL, },
+ { 0xc7711cc71cc7711cULL, 0x388ee338e3388ee3ULL, },
+ { 0xffffffffffffffffULL, 0xc7711cc71cc7711cULL, }, /* 56 */
+ { 0x0000000000000000ULL, 0xc7711cc71cc7711cULL, },
+ { 0xaaaaaaaaaaaaaaaaULL, 0xc7711cc71cc7711cULL, },
+ { 0x5555555555555555ULL, 0xc7711cc71cc7711cULL, },
+ { 0xccccccccccccccccULL, 0xc7711cc71cc7711cULL, },
+ { 0x3333333333333333ULL, 0xc7711cc71cc7711cULL, },
+ { 0x388ee338e3388ee3ULL, 0xc7711cc71cc7711cULL, },
+ { 0xc7711cc71cc7711cULL, 0xc7711cc71cc7711cULL, },
+ { 0x4b0bfeb088e62855ULL, 0x4b0bfeb088e62855ULL, }, /* 64 */
+ { 0x12bb1552fb004dc7ULL, 0x4b0bfeb088e62855ULL, },
+ { 0x27c6ab25acaeb98bULL, 0x4b0bfeb088e62855ULL, },
+ { 0x8d88a9e270165ee2ULL, 0x4b0bfeb088e62855ULL, },
+ { 0x4b0bfeb088e62855ULL, 0x12bb1552fb004dc7ULL, },
+ { 0x12bb1552fb004dc7ULL, 0x12bb1552fb004dc7ULL, },
+ { 0x27c6ab25acaeb98bULL, 0x12bb1552fb004dc7ULL, },
+ { 0x8d88a9e270165ee2ULL, 0x12bb1552fb004dc7ULL, },
+ { 0x4b0bfeb088e62855ULL, 0x27c6ab25acaeb98bULL, }, /* 72 */
+ { 0x12bb1552fb004dc7ULL, 0x27c6ab25acaeb98bULL, },
+ { 0x27c6ab25acaeb98bULL, 0x27c6ab25acaeb98bULL, },
+ { 0x8d88a9e270165ee2ULL, 0x27c6ab25acaeb98bULL, },
+ { 0x4b0bfeb088e62855ULL, 0x8d88a9e270165ee2ULL, },
+ { 0x12bb1552fb004dc7ULL, 0x8d88a9e270165ee2ULL, },
+ { 0x27c6ab25acaeb98bULL, 0x8d88a9e270165ee2ULL, },
+ { 0x8d88a9e270165ee2ULL, 0x8d88a9e270165ee2ULL, },
+ };
+
+ gettimeofday(&start, NULL);
+
+ for (i = 0; i < PATTERN_INPUTS_SHORT_COUNT; i++) {
+ for (j = 0; j < PATTERN_INPUTS_SHORT_COUNT; j++) {
+ do_msa_PCKOD_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_PCKOD_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/pack/test_msa_pckod_d.c b/tests/tcg/mips/user/ase/msa/pack/test_msa_pckod_d.c
new file mode 100644
index 0000000..3c4d55b
--- /dev/null
+++ b/tests/tcg/mips/user/ase/msa/pack/test_msa_pckod_d.c
@@ -0,0 +1,153 @@
+/*
+ * Test program for MSA instruction PCKOD.D
+ *
+ * Copyright (C) 2018 Wave Computing, Inc.
+ * Copyright (C) 2018 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.h"
+#include "../../../../include/test_utils.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 = "PCKOD.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, 0xffffffffffffffffULL, },
+ { 0xaaaaaaaaaaaaaaaaULL, 0xffffffffffffffffULL, },
+ { 0x5555555555555555ULL, 0xffffffffffffffffULL, },
+ { 0xccccccccccccccccULL, 0xffffffffffffffffULL, },
+ { 0x3333333333333333ULL, 0xffffffffffffffffULL, },
+ { 0x38e38e38e38e38e3ULL, 0xffffffffffffffffULL, },
+ { 0xc71c71c71c71c71cULL, 0xffffffffffffffffULL, },
+ { 0xffffffffffffffffULL, 0x0000000000000000ULL, }, /* 8 */
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xaaaaaaaaaaaaaaaaULL, 0x0000000000000000ULL, },
+ { 0x5555555555555555ULL, 0x0000000000000000ULL, },
+ { 0xccccccccccccccccULL, 0x0000000000000000ULL, },
+ { 0x3333333333333333ULL, 0x0000000000000000ULL, },
+ { 0x38e38e38e38e38e3ULL, 0x0000000000000000ULL, },
+ { 0xc71c71c71c71c71cULL, 0x0000000000000000ULL, },
+ { 0xffffffffffffffffULL, 0xaaaaaaaaaaaaaaaaULL, }, /* 16 */
+ { 0x0000000000000000ULL, 0xaaaaaaaaaaaaaaaaULL, },
+ { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, },
+ { 0x5555555555555555ULL, 0xaaaaaaaaaaaaaaaaULL, },
+ { 0xccccccccccccccccULL, 0xaaaaaaaaaaaaaaaaULL, },
+ { 0x3333333333333333ULL, 0xaaaaaaaaaaaaaaaaULL, },
+ { 0x38e38e38e38e38e3ULL, 0xaaaaaaaaaaaaaaaaULL, },
+ { 0xc71c71c71c71c71cULL, 0xaaaaaaaaaaaaaaaaULL, },
+ { 0xffffffffffffffffULL, 0x5555555555555555ULL, }, /* 24 */
+ { 0x0000000000000000ULL, 0x5555555555555555ULL, },
+ { 0xaaaaaaaaaaaaaaaaULL, 0x5555555555555555ULL, },
+ { 0x5555555555555555ULL, 0x5555555555555555ULL, },
+ { 0xccccccccccccccccULL, 0x5555555555555555ULL, },
+ { 0x3333333333333333ULL, 0x5555555555555555ULL, },
+ { 0x38e38e38e38e38e3ULL, 0x5555555555555555ULL, },
+ { 0xc71c71c71c71c71cULL, 0x5555555555555555ULL, },
+ { 0xffffffffffffffffULL, 0xccccccccccccccccULL, }, /* 32 */
+ { 0x0000000000000000ULL, 0xccccccccccccccccULL, },
+ { 0xaaaaaaaaaaaaaaaaULL, 0xccccccccccccccccULL, },
+ { 0x5555555555555555ULL, 0xccccccccccccccccULL, },
+ { 0xccccccccccccccccULL, 0xccccccccccccccccULL, },
+ { 0x3333333333333333ULL, 0xccccccccccccccccULL, },
+ { 0x38e38e38e38e38e3ULL, 0xccccccccccccccccULL, },
+ { 0xc71c71c71c71c71cULL, 0xccccccccccccccccULL, },
+ { 0xffffffffffffffffULL, 0x3333333333333333ULL, }, /* 40 */
+ { 0x0000000000000000ULL, 0x3333333333333333ULL, },
+ { 0xaaaaaaaaaaaaaaaaULL, 0x3333333333333333ULL, },
+ { 0x5555555555555555ULL, 0x3333333333333333ULL, },
+ { 0xccccccccccccccccULL, 0x3333333333333333ULL, },
+ { 0x3333333333333333ULL, 0x3333333333333333ULL, },
+ { 0x38e38e38e38e38e3ULL, 0x3333333333333333ULL, },
+ { 0xc71c71c71c71c71cULL, 0x3333333333333333ULL, },
+ { 0xffffffffffffffffULL, 0x38e38e38e38e38e3ULL, }, /* 48 */
+ { 0x0000000000000000ULL, 0x38e38e38e38e38e3ULL, },
+ { 0xaaaaaaaaaaaaaaaaULL, 0x38e38e38e38e38e3ULL, },
+ { 0x5555555555555555ULL, 0x38e38e38e38e38e3ULL, },
+ { 0xccccccccccccccccULL, 0x38e38e38e38e38e3ULL, },
+ { 0x3333333333333333ULL, 0x38e38e38e38e38e3ULL, },
+ { 0x38e38e38e38e38e3ULL, 0x38e38e38e38e38e3ULL, },
+ { 0xc71c71c71c71c71cULL, 0x38e38e38e38e38e3ULL, },
+ { 0xffffffffffffffffULL, 0xc71c71c71c71c71cULL, }, /* 56 */
+ { 0x0000000000000000ULL, 0xc71c71c71c71c71cULL, },
+ { 0xaaaaaaaaaaaaaaaaULL, 0xc71c71c71c71c71cULL, },
+ { 0x5555555555555555ULL, 0xc71c71c71c71c71cULL, },
+ { 0xccccccccccccccccULL, 0xc71c71c71c71c71cULL, },
+ { 0x3333333333333333ULL, 0xc71c71c71c71c71cULL, },
+ { 0x38e38e38e38e38e3ULL, 0xc71c71c71c71c71cULL, },
+ { 0xc71c71c71c71c71cULL, 0xc71c71c71c71c71cULL, },
+ { 0x4b670b5efe7bb00cULL, 0x4b670b5efe7bb00cULL, }, /* 64 */
+ { 0x12f7bb1a153f52fcULL, 0x4b670b5efe7bb00cULL, },
+ { 0x27d8c6ffab2b2514ULL, 0x4b670b5efe7bb00cULL, },
+ { 0x8df188d8a942e2a0ULL, 0x4b670b5efe7bb00cULL, },
+ { 0x4b670b5efe7bb00cULL, 0x12f7bb1a153f52fcULL, },
+ { 0x12f7bb1a153f52fcULL, 0x12f7bb1a153f52fcULL, },
+ { 0x27d8c6ffab2b2514ULL, 0x12f7bb1a153f52fcULL, },
+ { 0x8df188d8a942e2a0ULL, 0x12f7bb1a153f52fcULL, },
+ { 0x4b670b5efe7bb00cULL, 0x27d8c6ffab2b2514ULL, }, /* 72 */
+ { 0x12f7bb1a153f52fcULL, 0x27d8c6ffab2b2514ULL, },
+ { 0x27d8c6ffab2b2514ULL, 0x27d8c6ffab2b2514ULL, },
+ { 0x8df188d8a942e2a0ULL, 0x27d8c6ffab2b2514ULL, },
+ { 0x4b670b5efe7bb00cULL, 0x8df188d8a942e2a0ULL, },
+ { 0x12f7bb1a153f52fcULL, 0x8df188d8a942e2a0ULL, },
+ { 0x27d8c6ffab2b2514ULL, 0x8df188d8a942e2a0ULL, },
+ { 0x8df188d8a942e2a0ULL, 0x8df188d8a942e2a0ULL, },
+ };
+
+ gettimeofday(&start, NULL);
+
+ for (i = 0; i < PATTERN_INPUTS_SHORT_COUNT; i++) {
+ for (j = 0; j < PATTERN_INPUTS_SHORT_COUNT; j++) {
+ do_msa_PCKOD_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_PCKOD_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/pack/test_msa_pckod_h.c b/tests/tcg/mips/user/ase/msa/pack/test_msa_pckod_h.c
new file mode 100644
index 0000000..5c3c529
--- /dev/null
+++ b/tests/tcg/mips/user/ase/msa/pack/test_msa_pckod_h.c
@@ -0,0 +1,153 @@
+/*
+ * Test program for MSA instruction PCKOD.H
+ *
+ * Copyright (C) 2018 Wave Computing, Inc.
+ * Copyright (C) 2018 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.h"
+#include "../../../../include/test_utils.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 = "PCKOD.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 */
+ { 0x0000000000000000ULL, 0xffffffffffffffffULL, },
+ { 0xaaaaaaaaaaaaaaaaULL, 0xffffffffffffffffULL, },
+ { 0x5555555555555555ULL, 0xffffffffffffffffULL, },
+ { 0xccccccccccccccccULL, 0xffffffffffffffffULL, },
+ { 0x3333333333333333ULL, 0xffffffffffffffffULL, },
+ { 0x38e3e38ee38e8e38ULL, 0xffffffffffffffffULL, },
+ { 0xc71c1c711c7171c7ULL, 0xffffffffffffffffULL, },
+ { 0xffffffffffffffffULL, 0x0000000000000000ULL, }, /* 8 */
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xaaaaaaaaaaaaaaaaULL, 0x0000000000000000ULL, },
+ { 0x5555555555555555ULL, 0x0000000000000000ULL, },
+ { 0xccccccccccccccccULL, 0x0000000000000000ULL, },
+ { 0x3333333333333333ULL, 0x0000000000000000ULL, },
+ { 0x38e3e38ee38e8e38ULL, 0x0000000000000000ULL, },
+ { 0xc71c1c711c7171c7ULL, 0x0000000000000000ULL, },
+ { 0xffffffffffffffffULL, 0xaaaaaaaaaaaaaaaaULL, }, /* 16 */
+ { 0x0000000000000000ULL, 0xaaaaaaaaaaaaaaaaULL, },
+ { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, },
+ { 0x5555555555555555ULL, 0xaaaaaaaaaaaaaaaaULL, },
+ { 0xccccccccccccccccULL, 0xaaaaaaaaaaaaaaaaULL, },
+ { 0x3333333333333333ULL, 0xaaaaaaaaaaaaaaaaULL, },
+ { 0x38e3e38ee38e8e38ULL, 0xaaaaaaaaaaaaaaaaULL, },
+ { 0xc71c1c711c7171c7ULL, 0xaaaaaaaaaaaaaaaaULL, },
+ { 0xffffffffffffffffULL, 0x5555555555555555ULL, }, /* 24 */
+ { 0x0000000000000000ULL, 0x5555555555555555ULL, },
+ { 0xaaaaaaaaaaaaaaaaULL, 0x5555555555555555ULL, },
+ { 0x5555555555555555ULL, 0x5555555555555555ULL, },
+ { 0xccccccccccccccccULL, 0x5555555555555555ULL, },
+ { 0x3333333333333333ULL, 0x5555555555555555ULL, },
+ { 0x38e3e38ee38e8e38ULL, 0x5555555555555555ULL, },
+ { 0xc71c1c711c7171c7ULL, 0x5555555555555555ULL, },
+ { 0xffffffffffffffffULL, 0xccccccccccccccccULL, }, /* 32 */
+ { 0x0000000000000000ULL, 0xccccccccccccccccULL, },
+ { 0xaaaaaaaaaaaaaaaaULL, 0xccccccccccccccccULL, },
+ { 0x5555555555555555ULL, 0xccccccccccccccccULL, },
+ { 0xccccccccccccccccULL, 0xccccccccccccccccULL, },
+ { 0x3333333333333333ULL, 0xccccccccccccccccULL, },
+ { 0x38e3e38ee38e8e38ULL, 0xccccccccccccccccULL, },
+ { 0xc71c1c711c7171c7ULL, 0xccccccccccccccccULL, },
+ { 0xffffffffffffffffULL, 0x3333333333333333ULL, }, /* 40 */
+ { 0x0000000000000000ULL, 0x3333333333333333ULL, },
+ { 0xaaaaaaaaaaaaaaaaULL, 0x3333333333333333ULL, },
+ { 0x5555555555555555ULL, 0x3333333333333333ULL, },
+ { 0xccccccccccccccccULL, 0x3333333333333333ULL, },
+ { 0x3333333333333333ULL, 0x3333333333333333ULL, },
+ { 0x38e3e38ee38e8e38ULL, 0x3333333333333333ULL, },
+ { 0xc71c1c711c7171c7ULL, 0x3333333333333333ULL, },
+ { 0xffffffffffffffffULL, 0x38e3e38ee38e8e38ULL, }, /* 48 */
+ { 0x0000000000000000ULL, 0x38e3e38ee38e8e38ULL, },
+ { 0xaaaaaaaaaaaaaaaaULL, 0x38e3e38ee38e8e38ULL, },
+ { 0x5555555555555555ULL, 0x38e3e38ee38e8e38ULL, },
+ { 0xccccccccccccccccULL, 0x38e3e38ee38e8e38ULL, },
+ { 0x3333333333333333ULL, 0x38e3e38ee38e8e38ULL, },
+ { 0x38e3e38ee38e8e38ULL, 0x38e3e38ee38e8e38ULL, },
+ { 0xc71c1c711c7171c7ULL, 0x38e3e38ee38e8e38ULL, },
+ { 0xffffffffffffffffULL, 0xc71c1c711c7171c7ULL, }, /* 56 */
+ { 0x0000000000000000ULL, 0xc71c1c711c7171c7ULL, },
+ { 0xaaaaaaaaaaaaaaaaULL, 0xc71c1c711c7171c7ULL, },
+ { 0x5555555555555555ULL, 0xc71c1c711c7171c7ULL, },
+ { 0xccccccccccccccccULL, 0xc71c1c711c7171c7ULL, },
+ { 0x3333333333333333ULL, 0xc71c1c711c7171c7ULL, },
+ { 0x38e3e38ee38e8e38ULL, 0xc71c1c711c7171c7ULL, },
+ { 0xc71c1c711c7171c7ULL, 0xc71c1c711c7171c7ULL, },
+ { 0x4b67fe7b886a2862ULL, 0x4b67fe7b886a2862ULL, }, /* 64 */
+ { 0x12f7153ffbbe4d93ULL, 0x4b67fe7b886a2862ULL, },
+ { 0x27d8ab2bac5ab9cfULL, 0x4b67fe7b886a2862ULL, },
+ { 0x8df1a942704f5e31ULL, 0x4b67fe7b886a2862ULL, },
+ { 0x4b67fe7b886a2862ULL, 0x12f7153ffbbe4d93ULL, },
+ { 0x12f7153ffbbe4d93ULL, 0x12f7153ffbbe4d93ULL, },
+ { 0x27d8ab2bac5ab9cfULL, 0x12f7153ffbbe4d93ULL, },
+ { 0x8df1a942704f5e31ULL, 0x12f7153ffbbe4d93ULL, },
+ { 0x4b67fe7b886a2862ULL, 0x27d8ab2bac5ab9cfULL, }, /* 72 */
+ { 0x12f7153ffbbe4d93ULL, 0x27d8ab2bac5ab9cfULL, },
+ { 0x27d8ab2bac5ab9cfULL, 0x27d8ab2bac5ab9cfULL, },
+ { 0x8df1a942704f5e31ULL, 0x27d8ab2bac5ab9cfULL, },
+ { 0x4b67fe7b886a2862ULL, 0x8df1a942704f5e31ULL, },
+ { 0x12f7153ffbbe4d93ULL, 0x8df1a942704f5e31ULL, },
+ { 0x27d8ab2bac5ab9cfULL, 0x8df1a942704f5e31ULL, },
+ { 0x8df1a942704f5e31ULL, 0x8df1a942704f5e31ULL, },
+ };
+
+ gettimeofday(&start, NULL);
+
+ for (i = 0; i < PATTERN_INPUTS_SHORT_COUNT; i++) {
+ for (j = 0; j < PATTERN_INPUTS_SHORT_COUNT; j++) {
+ do_msa_PCKOD_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_PCKOD_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/pack/test_msa_pckod_w.c b/tests/tcg/mips/user/ase/msa/pack/test_msa_pckod_w.c
new file mode 100644
index 0000000..9275890
--- /dev/null
+++ b/tests/tcg/mips/user/ase/msa/pack/test_msa_pckod_w.c
@@ -0,0 +1,153 @@
+/*
+ * Test program for MSA instruction PCKOD.W
+ *
+ * Copyright (C) 2018 Wave Computing, Inc.
+ * Copyright (C) 2018 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.h"
+#include "../../../../include/test_utils.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 = "PCKOD.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, 0xffffffffffffffffULL, },
+ { 0xaaaaaaaaaaaaaaaaULL, 0xffffffffffffffffULL, },
+ { 0x5555555555555555ULL, 0xffffffffffffffffULL, },
+ { 0xccccccccccccccccULL, 0xffffffffffffffffULL, },
+ { 0x3333333333333333ULL, 0xffffffffffffffffULL, },
+ { 0x38e38e38e38e38e3ULL, 0xffffffffffffffffULL, },
+ { 0xc71c71c71c71c71cULL, 0xffffffffffffffffULL, },
+ { 0xffffffffffffffffULL, 0x0000000000000000ULL, }, /* 8 */
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xaaaaaaaaaaaaaaaaULL, 0x0000000000000000ULL, },
+ { 0x5555555555555555ULL, 0x0000000000000000ULL, },
+ { 0xccccccccccccccccULL, 0x0000000000000000ULL, },
+ { 0x3333333333333333ULL, 0x0000000000000000ULL, },
+ { 0x38e38e38e38e38e3ULL, 0x0000000000000000ULL, },
+ { 0xc71c71c71c71c71cULL, 0x0000000000000000ULL, },
+ { 0xffffffffffffffffULL, 0xaaaaaaaaaaaaaaaaULL, }, /* 16 */
+ { 0x0000000000000000ULL, 0xaaaaaaaaaaaaaaaaULL, },
+ { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, },
+ { 0x5555555555555555ULL, 0xaaaaaaaaaaaaaaaaULL, },
+ { 0xccccccccccccccccULL, 0xaaaaaaaaaaaaaaaaULL, },
+ { 0x3333333333333333ULL, 0xaaaaaaaaaaaaaaaaULL, },
+ { 0x38e38e38e38e38e3ULL, 0xaaaaaaaaaaaaaaaaULL, },
+ { 0xc71c71c71c71c71cULL, 0xaaaaaaaaaaaaaaaaULL, },
+ { 0xffffffffffffffffULL, 0x5555555555555555ULL, }, /* 24 */
+ { 0x0000000000000000ULL, 0x5555555555555555ULL, },
+ { 0xaaaaaaaaaaaaaaaaULL, 0x5555555555555555ULL, },
+ { 0x5555555555555555ULL, 0x5555555555555555ULL, },
+ { 0xccccccccccccccccULL, 0x5555555555555555ULL, },
+ { 0x3333333333333333ULL, 0x5555555555555555ULL, },
+ { 0x38e38e38e38e38e3ULL, 0x5555555555555555ULL, },
+ { 0xc71c71c71c71c71cULL, 0x5555555555555555ULL, },
+ { 0xffffffffffffffffULL, 0xccccccccccccccccULL, }, /* 32 */
+ { 0x0000000000000000ULL, 0xccccccccccccccccULL, },
+ { 0xaaaaaaaaaaaaaaaaULL, 0xccccccccccccccccULL, },
+ { 0x5555555555555555ULL, 0xccccccccccccccccULL, },
+ { 0xccccccccccccccccULL, 0xccccccccccccccccULL, },
+ { 0x3333333333333333ULL, 0xccccccccccccccccULL, },
+ { 0x38e38e38e38e38e3ULL, 0xccccccccccccccccULL, },
+ { 0xc71c71c71c71c71cULL, 0xccccccccccccccccULL, },
+ { 0xffffffffffffffffULL, 0x3333333333333333ULL, }, /* 40 */
+ { 0x0000000000000000ULL, 0x3333333333333333ULL, },
+ { 0xaaaaaaaaaaaaaaaaULL, 0x3333333333333333ULL, },
+ { 0x5555555555555555ULL, 0x3333333333333333ULL, },
+ { 0xccccccccccccccccULL, 0x3333333333333333ULL, },
+ { 0x3333333333333333ULL, 0x3333333333333333ULL, },
+ { 0x38e38e38e38e38e3ULL, 0x3333333333333333ULL, },
+ { 0xc71c71c71c71c71cULL, 0x3333333333333333ULL, },
+ { 0xffffffffffffffffULL, 0x38e38e38e38e38e3ULL, }, /* 48 */
+ { 0x0000000000000000ULL, 0x38e38e38e38e38e3ULL, },
+ { 0xaaaaaaaaaaaaaaaaULL, 0x38e38e38e38e38e3ULL, },
+ { 0x5555555555555555ULL, 0x38e38e38e38e38e3ULL, },
+ { 0xccccccccccccccccULL, 0x38e38e38e38e38e3ULL, },
+ { 0x3333333333333333ULL, 0x38e38e38e38e38e3ULL, },
+ { 0x38e38e38e38e38e3ULL, 0x38e38e38e38e38e3ULL, },
+ { 0xc71c71c71c71c71cULL, 0x38e38e38e38e38e3ULL, },
+ { 0xffffffffffffffffULL, 0xc71c71c71c71c71cULL, }, /* 56 */
+ { 0x0000000000000000ULL, 0xc71c71c71c71c71cULL, },
+ { 0xaaaaaaaaaaaaaaaaULL, 0xc71c71c71c71c71cULL, },
+ { 0x5555555555555555ULL, 0xc71c71c71c71c71cULL, },
+ { 0xccccccccccccccccULL, 0xc71c71c71c71c71cULL, },
+ { 0x3333333333333333ULL, 0xc71c71c71c71c71cULL, },
+ { 0x38e38e38e38e38e3ULL, 0xc71c71c71c71c71cULL, },
+ { 0xc71c71c71c71c71cULL, 0xc71c71c71c71c71cULL, },
+ { 0x4b670b5e886ae6ccULL, 0x4b670b5e886ae6ccULL, }, /* 64 */
+ { 0x12f7bb1afbbe0063ULL, 0x4b670b5e886ae6ccULL, },
+ { 0x27d8c6ffac5aaeaaULL, 0x4b670b5e886ae6ccULL, },
+ { 0x8df188d8704f164dULL, 0x4b670b5e886ae6ccULL, },
+ { 0x4b670b5e886ae6ccULL, 0x12f7bb1afbbe0063ULL, },
+ { 0x12f7bb1afbbe0063ULL, 0x12f7bb1afbbe0063ULL, },
+ { 0x27d8c6ffac5aaeaaULL, 0x12f7bb1afbbe0063ULL, },
+ { 0x8df188d8704f164dULL, 0x12f7bb1afbbe0063ULL, },
+ { 0x4b670b5e886ae6ccULL, 0x27d8c6ffac5aaeaaULL, }, /* 72 */
+ { 0x12f7bb1afbbe0063ULL, 0x27d8c6ffac5aaeaaULL, },
+ { 0x27d8c6ffac5aaeaaULL, 0x27d8c6ffac5aaeaaULL, },
+ { 0x8df188d8704f164dULL, 0x27d8c6ffac5aaeaaULL, },
+ { 0x4b670b5e886ae6ccULL, 0x8df188d8704f164dULL, },
+ { 0x12f7bb1afbbe0063ULL, 0x8df188d8704f164dULL, },
+ { 0x27d8c6ffac5aaeaaULL, 0x8df188d8704f164dULL, },
+ { 0x8df188d8704f164dULL, 0x8df188d8704f164dULL, },
+ };
+
+ gettimeofday(&start, NULL);
+
+ for (i = 0; i < PATTERN_INPUTS_SHORT_COUNT; i++) {
+ for (j = 0; j < PATTERN_INPUTS_SHORT_COUNT; j++) {
+ do_msa_PCKOD_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_PCKOD_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/pack/test_msa_vshf_b.c b/tests/tcg/mips/user/ase/msa/pack/test_msa_vshf_b.c
new file mode 100644
index 0000000..fcf857a
--- /dev/null
+++ b/tests/tcg/mips/user/ase/msa/pack/test_msa_vshf_b.c
@@ -0,0 +1,153 @@
+/*
+ * Test program for MSA instruction VSHF.B
+ *
+ * Copyright (C) 2018 Wave Computing, Inc.
+ * Copyright (C) 2018 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.h"
+#include "../../../../include/test_utils.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 = "VSHF.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 */
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xccccccccccccccccULL, 0xccccccccccccccccULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x8e8e8e8e8e8e8e8eULL, 0x8e8e8e8e8e8e8e8eULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 8 */
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xccccccccccccccccULL, 0xccccccccccccccccULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x8e8e8e8e8e8e8e8eULL, 0x8e8e8e8e8e8e8e8eULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 16 */
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xccccccccccccccccULL, 0xccccccccccccccccULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x8e8e8e8e8e8e8e8eULL, 0x8e8e8e8e8e8e8e8eULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 24 */
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xccccccccccccccccULL, 0xccccccccccccccccULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x8e8e8e8e8e8e8e8eULL, 0x8e8e8e8e8e8e8e8eULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 32 */
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xccccccccccccccccULL, 0xccccccccccccccccULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x8e8e8e8e8e8e8e8eULL, 0x8e8e8e8e8e8e8e8eULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 40 */
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xccccccccccccccccULL, 0xccccccccccccccccULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x8e8e8e8e8e8e8e8eULL, 0x8e8e8e8e8e8e8e8eULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 48 */
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xccccccccccccccccULL, 0xccccccccccccccccULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x8e8e8e8e8e8e8e8eULL, 0x8e8e8e8e8e8e8e8eULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 56 */
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xccccccccccccccccULL, 0xccccccccccccccccULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x8e8e8e8e8e8e8e8eULL, 0x8e8e8e8e8e8e8e8eULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x4040404040404040ULL, 0x4040404040404040ULL, }, /* 64 */
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x8080808080808080ULL, 0x8080808080808080ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x4040404040404040ULL, 0x4040404040404040ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x8080808080808080ULL, 0x8080808080808080ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x4040404040404040ULL, 0x4040404040404040ULL, }, /* 72 */
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x8080808080808080ULL, 0x8080808080808080ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x4040404040404040ULL, 0x4040404040404040ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x8080808080808080ULL, 0x8080808080808080ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ };
+
+ gettimeofday(&start, NULL);
+
+ for (i = 0; i < PATTERN_INPUTS_SHORT_COUNT; i++) {
+ for (j = 0; j < PATTERN_INPUTS_SHORT_COUNT; j++) {
+ do_msa_VSHF_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_VSHF_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/pack/test_msa_vshf_d.c b/tests/tcg/mips/user/ase/msa/pack/test_msa_vshf_d.c
new file mode 100644
index 0000000..700c159
--- /dev/null
+++ b/tests/tcg/mips/user/ase/msa/pack/test_msa_vshf_d.c
@@ -0,0 +1,153 @@
+/*
+ * Test program for MSA instruction VSHF.D
+ *
+ * Copyright (C) 2018 Wave Computing, Inc.
+ * Copyright (C) 2018 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.h"
+#include "../../../../include/test_utils.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 = "VSHF.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 */
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xccccccccccccccccULL, 0xccccccccccccccccULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xe38e38e38e38e38eULL, 0xe38e38e38e38e38eULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 8 */
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xccccccccccccccccULL, 0xccccccccccccccccULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xe38e38e38e38e38eULL, 0xe38e38e38e38e38eULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 16 */
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xccccccccccccccccULL, 0xccccccccccccccccULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xe38e38e38e38e38eULL, 0xe38e38e38e38e38eULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 24 */
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xccccccccccccccccULL, 0xccccccccccccccccULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xe38e38e38e38e38eULL, 0xe38e38e38e38e38eULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 32 */
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xccccccccccccccccULL, 0xccccccccccccccccULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xe38e38e38e38e38eULL, 0xe38e38e38e38e38eULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 40 */
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xccccccccccccccccULL, 0xccccccccccccccccULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xe38e38e38e38e38eULL, 0xe38e38e38e38e38eULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 48 */
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xccccccccccccccccULL, 0xccccccccccccccccULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xe38e38e38e38e38eULL, 0xe38e38e38e38e38eULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 56 */
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xccccccccccccccccULL, 0xccccccccccccccccULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xe38e38e38e38e38eULL, 0xe38e38e38e38e38eULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x886ae6cc28625540ULL, 0x886ae6cc28625540ULL, }, /* 64 */
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xac5aaeaab9cf8b80ULL, 0xac5aaeaab9cf8b80ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x886ae6cc28625540ULL, 0x886ae6cc28625540ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xac5aaeaab9cf8b80ULL, 0xac5aaeaab9cf8b80ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x886ae6cc28625540ULL, 0x886ae6cc28625540ULL, }, /* 72 */
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xac5aaeaab9cf8b80ULL, 0xac5aaeaab9cf8b80ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x886ae6cc28625540ULL, 0x886ae6cc28625540ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xac5aaeaab9cf8b80ULL, 0xac5aaeaab9cf8b80ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ };
+
+ gettimeofday(&start, NULL);
+
+ for (i = 0; i < PATTERN_INPUTS_SHORT_COUNT; i++) {
+ for (j = 0; j < PATTERN_INPUTS_SHORT_COUNT; j++) {
+ do_msa_VSHF_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_VSHF_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/pack/test_msa_vshf_h.c b/tests/tcg/mips/user/ase/msa/pack/test_msa_vshf_h.c
new file mode 100644
index 0000000..3d6c1dc
--- /dev/null
+++ b/tests/tcg/mips/user/ase/msa/pack/test_msa_vshf_h.c
@@ -0,0 +1,153 @@
+/*
+ * Test program for MSA instruction VSHF.H
+ *
+ * Copyright (C) 2018 Wave Computing, Inc.
+ * Copyright (C) 2018 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.h"
+#include "../../../../include/test_utils.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 = "VSHF.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 */
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xccccccccccccccccULL, 0xccccccccccccccccULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xe38ee38ee38ee38eULL, 0xe38ee38ee38ee38eULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 8 */
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xccccccccccccccccULL, 0xccccccccccccccccULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xe38ee38ee38ee38eULL, 0xe38ee38ee38ee38eULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 16 */
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xccccccccccccccccULL, 0xccccccccccccccccULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xe38ee38ee38ee38eULL, 0xe38ee38ee38ee38eULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 24 */
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xccccccccccccccccULL, 0xccccccccccccccccULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xe38ee38ee38ee38eULL, 0xe38ee38ee38ee38eULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 32 */
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xccccccccccccccccULL, 0xccccccccccccccccULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xe38ee38ee38ee38eULL, 0xe38ee38ee38ee38eULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 40 */
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xccccccccccccccccULL, 0xccccccccccccccccULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xe38ee38ee38ee38eULL, 0xe38ee38ee38ee38eULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 48 */
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xccccccccccccccccULL, 0xccccccccccccccccULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xe38ee38ee38ee38eULL, 0xe38ee38ee38ee38eULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 56 */
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xccccccccccccccccULL, 0xccccccccccccccccULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xe38ee38ee38ee38eULL, 0xe38ee38ee38ee38eULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x5540554055405540ULL, 0x5540554055405540ULL, }, /* 64 */
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x8b808b808b808b80ULL, 0x8b808b808b808b80ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x5540554055405540ULL, 0x5540554055405540ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x8b808b808b808b80ULL, 0x8b808b808b808b80ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x5540554055405540ULL, 0x5540554055405540ULL, }, /* 72 */
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x8b808b808b808b80ULL, 0x8b808b808b808b80ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x5540554055405540ULL, 0x5540554055405540ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x8b808b808b808b80ULL, 0x8b808b808b808b80ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ };
+
+ gettimeofday(&start, NULL);
+
+ for (i = 0; i < PATTERN_INPUTS_SHORT_COUNT; i++) {
+ for (j = 0; j < PATTERN_INPUTS_SHORT_COUNT; j++) {
+ do_msa_VSHF_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_VSHF_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/pack/test_msa_vshf_w.c b/tests/tcg/mips/user/ase/msa/pack/test_msa_vshf_w.c
new file mode 100644
index 0000000..6030762
--- /dev/null
+++ b/tests/tcg/mips/user/ase/msa/pack/test_msa_vshf_w.c
@@ -0,0 +1,153 @@
+/*
+ * Test program for MSA instruction VSHF.W
+ *
+ * Copyright (C) 2018 Wave Computing, Inc.
+ * Copyright (C) 2018 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.h"
+#include "../../../../include/test_utils.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 = "VSHF.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 */
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xccccccccccccccccULL, 0xccccccccccccccccULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x8e38e38e8e38e38eULL, 0x8e38e38e8e38e38eULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 8 */
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xccccccccccccccccULL, 0xccccccccccccccccULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x8e38e38e8e38e38eULL, 0x8e38e38e8e38e38eULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 16 */
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xccccccccccccccccULL, 0xccccccccccccccccULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x8e38e38e8e38e38eULL, 0x8e38e38e8e38e38eULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 24 */
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xccccccccccccccccULL, 0xccccccccccccccccULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x8e38e38e8e38e38eULL, 0x8e38e38e8e38e38eULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 32 */
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xccccccccccccccccULL, 0xccccccccccccccccULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x8e38e38e8e38e38eULL, 0x8e38e38e8e38e38eULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 40 */
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xccccccccccccccccULL, 0xccccccccccccccccULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x8e38e38e8e38e38eULL, 0x8e38e38e8e38e38eULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 48 */
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xccccccccccccccccULL, 0xccccccccccccccccULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x8e38e38e8e38e38eULL, 0x8e38e38e8e38e38eULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL, }, /* 56 */
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xccccccccccccccccULL, 0xccccccccccccccccULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x8e38e38e8e38e38eULL, 0x8e38e38e8e38e38eULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x2862554028625540ULL, 0x2862554028625540ULL, }, /* 64 */
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xb9cf8b80b9cf8b80ULL, 0xb9cf8b80b9cf8b80ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x2862554028625540ULL, 0x2862554028625540ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xb9cf8b80b9cf8b80ULL, 0xb9cf8b80b9cf8b80ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x2862554028625540ULL, 0x2862554028625540ULL, }, /* 72 */
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xb9cf8b80b9cf8b80ULL, 0xb9cf8b80b9cf8b80ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0x2862554028625540ULL, 0x2862554028625540ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ { 0xb9cf8b80b9cf8b80ULL, 0xb9cf8b80b9cf8b80ULL, },
+ { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+ };
+
+ gettimeofday(&start, NULL);
+
+ for (i = 0; i < PATTERN_INPUTS_SHORT_COUNT; i++) {
+ for (j = 0; j < PATTERN_INPUTS_SHORT_COUNT; j++) {
+ do_msa_VSHF_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_VSHF_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/isa/mips64r6/bit-count/test_mips64r6_clo.c b/tests/tcg/mips/user/isa/mips64r6/bit-count/test_mips64r6_clo.c
new file mode 100644
index 0000000..ca9a739
--- /dev/null
+++ b/tests/tcg/mips/user/isa/mips64r6/bit-count/test_mips64r6_clo.c
@@ -0,0 +1,144 @@
+/*
+ * Test program for MIPS64R6 instruction CLO
+ *
+ * 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_mips64r6.h"
+#include "../../../../include/test_inputs_64.h"
+#include "../../../../include/test_utils_64.h"
+
+#define TEST_COUNT_TOTAL (PATTERN_INPUTS_64_COUNT + RANDOM_INPUTS_64_COUNT)
+
+
+int32_t main(void)
+{
+ char *instruction_name = "CLO";
+ int32_t ret;
+ uint32_t i;
+ struct timeval start, end;
+ double elapsed_time;
+
+ uint64_t b64_result[TEST_COUNT_TOTAL];
+ uint64_t b64_expect[TEST_COUNT_TOTAL] = {
+ 0x0000000000000020ULL, /* 0 */
+ 0x0000000000000000ULL,
+ 0x0000000000000001ULL,
+ 0x0000000000000000ULL,
+ 0x0000000000000002ULL,
+ 0x0000000000000000ULL,
+ 0x0000000000000003ULL,
+ 0x0000000000000000ULL,
+ 0x0000000000000004ULL, /* 8 */
+ 0x0000000000000000ULL,
+ 0x0000000000000005ULL,
+ 0x0000000000000000ULL,
+ 0x0000000000000006ULL,
+ 0x0000000000000000ULL,
+ 0x0000000000000007ULL,
+ 0x0000000000000000ULL,
+ 0x0000000000000008ULL, /* 16 */
+ 0x0000000000000000ULL,
+ 0x0000000000000009ULL,
+ 0x0000000000000000ULL,
+ 0x000000000000000aULL,
+ 0x0000000000000000ULL,
+ 0x000000000000000bULL,
+ 0x0000000000000000ULL,
+ 0x000000000000000cULL, /* 24 */
+ 0x0000000000000000ULL,
+ 0x000000000000000dULL,
+ 0x0000000000000000ULL,
+ 0x000000000000000eULL,
+ 0x0000000000000000ULL,
+ 0x000000000000000fULL,
+ 0x0000000000000000ULL,
+ 0x0000000000000010ULL, /* 32 */
+ 0x0000000000000000ULL,
+ 0x0000000000000011ULL,
+ 0x0000000000000000ULL,
+ 0x0000000000000012ULL,
+ 0x0000000000000000ULL,
+ 0x0000000000000013ULL,
+ 0x0000000000000000ULL,
+ 0x0000000000000014ULL, /* 40 */
+ 0x0000000000000000ULL,
+ 0x0000000000000015ULL,
+ 0x0000000000000000ULL,
+ 0x0000000000000016ULL,
+ 0x0000000000000000ULL,
+ 0x0000000000000017ULL,
+ 0x0000000000000000ULL,
+ 0x0000000000000018ULL, /* 48 */
+ 0x0000000000000000ULL,
+ 0x0000000000000019ULL,
+ 0x0000000000000000ULL,
+ 0x000000000000001aULL,
+ 0x0000000000000000ULL,
+ 0x000000000000001bULL,
+ 0x0000000000000000ULL,
+ 0x000000000000001cULL, /* 56 */
+ 0x0000000000000000ULL,
+ 0x000000000000001dULL,
+ 0x0000000000000000ULL,
+ 0x000000000000001eULL,
+ 0x0000000000000000ULL,
+ 0x000000000000001fULL,
+ 0x0000000000000000ULL,
+ 0x0000000000000001ULL, /* 64 */
+ 0x0000000000000005ULL,
+ 0x0000000000000001ULL,
+ 0x0000000000000000ULL,
+ 0x0000000000000001ULL,
+ 0x0000000000000002ULL,
+ 0x0000000000000001ULL,
+ 0x0000000000000006ULL,
+ 0x0000000000000000ULL, /* 72 */
+ 0x0000000000000001ULL,
+ 0x0000000000000001ULL,
+ 0x0000000000000001ULL,
+ 0x0000000000000003ULL,
+ 0x0000000000000001ULL,
+ 0x0000000000000000ULL,
+ 0x0000000000000001ULL,
+ };
+
+ gettimeofday(&start, NULL);
+
+ for (i = 0; i < TEST_COUNT_TOTAL; i++) {
+ if (i < PATTERN_INPUTS_64_COUNT) {
+ do_mips64r6_CLO(b64_pattern_se + i, b64_result + i);
+ } else {
+ do_mips64r6_CLO(b64_random_se + (i - PATTERN_INPUTS_64_COUNT),
+ b64_result + i);
+ }
+ }
+
+ 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_64(instruction_name, TEST_COUNT_TOTAL, elapsed_time,
+ b64_result, b64_expect);
+
+ return ret;
+}
diff --git a/tests/tcg/mips/user/isa/mips64r6/bit-count/test_mips64r6_clz.c b/tests/tcg/mips/user/isa/mips64r6/bit-count/test_mips64r6_clz.c
new file mode 100644
index 0000000..0a7d21d
--- /dev/null
+++ b/tests/tcg/mips/user/isa/mips64r6/bit-count/test_mips64r6_clz.c
@@ -0,0 +1,144 @@
+/*
+ * Test program for MIPS64R6 instruction CLZ
+ *
+ * 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_mips64r6.h"
+#include "../../../../include/test_inputs_64.h"
+#include "../../../../include/test_utils_64.h"
+
+#define TEST_COUNT_TOTAL (PATTERN_INPUTS_64_COUNT + RANDOM_INPUTS_64_COUNT)
+
+
+int32_t main(void)
+{
+ char *instruction_name = "CLZ";
+ int32_t ret;
+ uint32_t i;
+ struct timeval start, end;
+ double elapsed_time;
+
+ uint64_t b64_result[TEST_COUNT_TOTAL];
+ uint64_t b64_expect[TEST_COUNT_TOTAL] = {
+ 0x0000000000000000ULL, /* 0 */
+ 0x0000000000000020ULL,
+ 0x0000000000000000ULL,
+ 0x0000000000000001ULL,
+ 0x0000000000000000ULL,
+ 0x0000000000000002ULL,
+ 0x0000000000000000ULL,
+ 0x0000000000000003ULL,
+ 0x0000000000000000ULL, /* 8 */
+ 0x0000000000000004ULL,
+ 0x0000000000000000ULL,
+ 0x0000000000000005ULL,
+ 0x0000000000000000ULL,
+ 0x0000000000000006ULL,
+ 0x0000000000000000ULL,
+ 0x0000000000000007ULL,
+ 0x0000000000000000ULL, /* 16 */
+ 0x0000000000000008ULL,
+ 0x0000000000000000ULL,
+ 0x0000000000000009ULL,
+ 0x0000000000000000ULL,
+ 0x000000000000000aULL,
+ 0x0000000000000000ULL,
+ 0x000000000000000bULL,
+ 0x0000000000000000ULL, /* 24 */
+ 0x000000000000000cULL,
+ 0x0000000000000000ULL,
+ 0x000000000000000dULL,
+ 0x0000000000000000ULL,
+ 0x000000000000000eULL,
+ 0x0000000000000000ULL,
+ 0x000000000000000fULL,
+ 0x0000000000000000ULL, /* 32 */
+ 0x0000000000000010ULL,
+ 0x0000000000000000ULL,
+ 0x0000000000000011ULL,
+ 0x0000000000000000ULL,
+ 0x0000000000000012ULL,
+ 0x0000000000000000ULL,
+ 0x0000000000000013ULL,
+ 0x0000000000000000ULL, /* 40 */
+ 0x0000000000000014ULL,
+ 0x0000000000000000ULL,
+ 0x0000000000000015ULL,
+ 0x0000000000000000ULL,
+ 0x0000000000000016ULL,
+ 0x0000000000000000ULL,
+ 0x0000000000000017ULL,
+ 0x0000000000000000ULL, /* 48 */
+ 0x0000000000000018ULL,
+ 0x0000000000000000ULL,
+ 0x0000000000000019ULL,
+ 0x0000000000000000ULL,
+ 0x000000000000001aULL,
+ 0x0000000000000000ULL,
+ 0x000000000000001bULL,
+ 0x0000000000000000ULL, /* 56 */
+ 0x000000000000001cULL,
+ 0x0000000000000000ULL,
+ 0x000000000000001dULL,
+ 0x0000000000000000ULL,
+ 0x000000000000001eULL,
+ 0x0000000000000000ULL,
+ 0x000000000000001fULL,
+ 0x0000000000000000ULL, /* 64 */
+ 0x0000000000000000ULL,
+ 0x0000000000000000ULL,
+ 0x0000000000000001ULL,
+ 0x0000000000000000ULL,
+ 0x0000000000000000ULL,
+ 0x0000000000000000ULL,
+ 0x0000000000000000ULL,
+ 0x0000000000000002ULL, /* 72 */
+ 0x0000000000000000ULL,
+ 0x0000000000000000ULL,
+ 0x0000000000000000ULL,
+ 0x0000000000000000ULL,
+ 0x0000000000000000ULL,
+ 0x0000000000000001ULL,
+ 0x0000000000000000ULL,
+ };
+
+ gettimeofday(&start, NULL);
+
+ for (i = 0; i < TEST_COUNT_TOTAL; i++) {
+ if (i < PATTERN_INPUTS_64_COUNT) {
+ do_mips64r6_CLZ(b64_pattern_se + i, b64_result + i);
+ } else {
+ do_mips64r6_CLZ(b64_random_se + (i - PATTERN_INPUTS_64_COUNT),
+ b64_result + i);
+ }
+ }
+
+ 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_64(instruction_name, TEST_COUNT_TOTAL, elapsed_time,
+ b64_result, b64_expect);
+
+ return ret;
+}
diff --git a/tests/tcg/mips/user/isa/mips64r6/bit-count/test_mips64r6_dclo.c b/tests/tcg/mips/user/isa/mips64r6/bit-count/test_mips64r6_dclo.c
new file mode 100644
index 0000000..72bb473
--- /dev/null
+++ b/tests/tcg/mips/user/isa/mips64r6/bit-count/test_mips64r6_dclo.c
@@ -0,0 +1,144 @@
+/*
+ * Test program for MIPS64R6 instruction DCLO
+ *
+ * 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_mips64r6.h"
+#include "../../../../include/test_inputs_64.h"
+#include "../../../../include/test_utils_64.h"
+
+#define TEST_COUNT_TOTAL (PATTERN_INPUTS_64_COUNT + RANDOM_INPUTS_64_COUNT)
+
+
+int32_t main(void)
+{
+ char *instruction_name = "DCLO";
+ int32_t ret;
+ uint32_t i;
+ struct timeval start, end;
+ double elapsed_time;
+
+ uint64_t b64_result[TEST_COUNT_TOTAL];
+ uint64_t b64_expect[TEST_COUNT_TOTAL] = {
+ 0x0000000000000040ULL, /* 0 */
+ 0x0000000000000000ULL,
+ 0x0000000000000001ULL,
+ 0x0000000000000000ULL,
+ 0x0000000000000002ULL,
+ 0x0000000000000000ULL,
+ 0x0000000000000003ULL,
+ 0x0000000000000000ULL,
+ 0x0000000000000004ULL, /* 8 */
+ 0x0000000000000000ULL,
+ 0x0000000000000005ULL,
+ 0x0000000000000000ULL,
+ 0x0000000000000006ULL,
+ 0x0000000000000000ULL,
+ 0x0000000000000007ULL,
+ 0x0000000000000000ULL,
+ 0x0000000000000008ULL, /* 16 */
+ 0x0000000000000000ULL,
+ 0x0000000000000009ULL,
+ 0x0000000000000000ULL,
+ 0x000000000000000aULL,
+ 0x0000000000000000ULL,
+ 0x000000000000000bULL,
+ 0x0000000000000000ULL,
+ 0x000000000000000cULL, /* 24 */
+ 0x0000000000000000ULL,
+ 0x000000000000000dULL,
+ 0x0000000000000000ULL,
+ 0x000000000000000eULL,
+ 0x0000000000000000ULL,
+ 0x000000000000000fULL,
+ 0x0000000000000000ULL,
+ 0x0000000000000010ULL, /* 32 */
+ 0x0000000000000000ULL,
+ 0x0000000000000011ULL,
+ 0x0000000000000000ULL,
+ 0x0000000000000012ULL,
+ 0x0000000000000000ULL,
+ 0x0000000000000013ULL,
+ 0x0000000000000000ULL,
+ 0x0000000000000014ULL, /* 40 */
+ 0x0000000000000000ULL,
+ 0x0000000000000015ULL,
+ 0x0000000000000000ULL,
+ 0x0000000000000016ULL,
+ 0x0000000000000000ULL,
+ 0x0000000000000017ULL,
+ 0x0000000000000000ULL,
+ 0x0000000000000018ULL, /* 48 */
+ 0x0000000000000000ULL,
+ 0x0000000000000019ULL,
+ 0x0000000000000000ULL,
+ 0x000000000000001aULL,
+ 0x0000000000000000ULL,
+ 0x000000000000001bULL,
+ 0x0000000000000000ULL,
+ 0x000000000000001cULL, /* 56 */
+ 0x0000000000000000ULL,
+ 0x000000000000001dULL,
+ 0x0000000000000000ULL,
+ 0x000000000000001eULL,
+ 0x0000000000000000ULL,
+ 0x000000000000001fULL,
+ 0x0000000000000000ULL,
+ 0x0000000000000001ULL, /* 64 */
+ 0x0000000000000005ULL,
+ 0x0000000000000001ULL,
+ 0x0000000000000000ULL,
+ 0x0000000000000001ULL,
+ 0x0000000000000002ULL,
+ 0x0000000000000001ULL,
+ 0x0000000000000006ULL,
+ 0x0000000000000000ULL, /* 72 */
+ 0x0000000000000001ULL,
+ 0x0000000000000001ULL,
+ 0x0000000000000001ULL,
+ 0x0000000000000003ULL,
+ 0x0000000000000001ULL,
+ 0x0000000000000000ULL,
+ 0x0000000000000001ULL,
+ };
+
+ gettimeofday(&start, NULL);
+
+ for (i = 0; i < TEST_COUNT_TOTAL; i++) {
+ if (i < PATTERN_INPUTS_64_COUNT) {
+ do_mips64r6_DCLO((void *)&b64_pattern[i], (void *)&b64_result[i]);
+ } else {
+ do_mips64r6_DCLO((void *)&b64_random[i - PATTERN_INPUTS_64_COUNT],
+ (void *)&b64_result[i]);
+ }
+ }
+
+ 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_64(instruction_name, TEST_COUNT_TOTAL, elapsed_time,
+ b64_result, b64_expect);
+
+ return ret;
+}
diff --git a/tests/tcg/mips/user/isa/mips64r6/bit-count/test_mips64r6_dclz.c b/tests/tcg/mips/user/isa/mips64r6/bit-count/test_mips64r6_dclz.c
new file mode 100644
index 0000000..87df12b
--- /dev/null
+++ b/tests/tcg/mips/user/isa/mips64r6/bit-count/test_mips64r6_dclz.c
@@ -0,0 +1,144 @@
+/*
+ * Test program for MIPS64R6 instruction DCLZ
+ *
+ * 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_mips64r6.h"
+#include "../../../../include/test_inputs_64.h"
+#include "../../../../include/test_utils_64.h"
+
+#define TEST_COUNT_TOTAL (PATTERN_INPUTS_64_COUNT + RANDOM_INPUTS_64_COUNT)
+
+
+int32_t main(void)
+{
+ char *instruction_name = "DCLZ";
+ int32_t ret;
+ uint32_t i;
+ struct timeval start, end;
+ double elapsed_time;
+
+ uint64_t b64_result[TEST_COUNT_TOTAL];
+ uint64_t b64_expect[TEST_COUNT_TOTAL] = {
+ 0x0000000000000000ULL, /* 0 */
+ 0x0000000000000040ULL,
+ 0x0000000000000000ULL,
+ 0x0000000000000001ULL,
+ 0x0000000000000000ULL,
+ 0x0000000000000002ULL,
+ 0x0000000000000000ULL,
+ 0x0000000000000003ULL,
+ 0x0000000000000000ULL, /* 8 */
+ 0x0000000000000004ULL,
+ 0x0000000000000000ULL,
+ 0x0000000000000005ULL,
+ 0x0000000000000000ULL,
+ 0x0000000000000006ULL,
+ 0x0000000000000000ULL,
+ 0x0000000000000007ULL,
+ 0x0000000000000000ULL, /* 16 */
+ 0x0000000000000008ULL,
+ 0x0000000000000000ULL,
+ 0x0000000000000009ULL,
+ 0x0000000000000000ULL,
+ 0x000000000000000aULL,
+ 0x0000000000000000ULL,
+ 0x000000000000000bULL,
+ 0x0000000000000000ULL, /* 24 */
+ 0x000000000000000cULL,
+ 0x0000000000000000ULL,
+ 0x000000000000000dULL,
+ 0x0000000000000000ULL,
+ 0x000000000000000eULL,
+ 0x0000000000000000ULL,
+ 0x000000000000000fULL,
+ 0x0000000000000000ULL, /* 32 */
+ 0x0000000000000010ULL,
+ 0x0000000000000000ULL,
+ 0x0000000000000011ULL,
+ 0x0000000000000000ULL,
+ 0x0000000000000012ULL,
+ 0x0000000000000000ULL,
+ 0x0000000000000013ULL,
+ 0x0000000000000000ULL, /* 40 */
+ 0x0000000000000014ULL,
+ 0x0000000000000000ULL,
+ 0x0000000000000015ULL,
+ 0x0000000000000000ULL,
+ 0x0000000000000016ULL,
+ 0x0000000000000000ULL,
+ 0x0000000000000017ULL,
+ 0x0000000000000000ULL, /* 48 */
+ 0x0000000000000018ULL,
+ 0x0000000000000000ULL,
+ 0x0000000000000019ULL,
+ 0x0000000000000000ULL,
+ 0x000000000000001aULL,
+ 0x0000000000000000ULL,
+ 0x000000000000001bULL,
+ 0x0000000000000000ULL, /* 56 */
+ 0x000000000000001cULL,
+ 0x0000000000000000ULL,
+ 0x000000000000001dULL,
+ 0x0000000000000000ULL,
+ 0x000000000000001eULL,
+ 0x0000000000000000ULL,
+ 0x000000000000001fULL,
+ 0x0000000000000000ULL, /* 64 */
+ 0x0000000000000000ULL,
+ 0x0000000000000000ULL,
+ 0x0000000000000001ULL,
+ 0x0000000000000000ULL,
+ 0x0000000000000000ULL,
+ 0x0000000000000000ULL,
+ 0x0000000000000000ULL,
+ 0x0000000000000002ULL, /* 72 */
+ 0x0000000000000000ULL,
+ 0x0000000000000000ULL,
+ 0x0000000000000000ULL,
+ 0x0000000000000000ULL,
+ 0x0000000000000000ULL,
+ 0x0000000000000001ULL,
+ 0x0000000000000000ULL,
+ };
+
+ gettimeofday(&start, NULL);
+
+ for (i = 0; i < TEST_COUNT_TOTAL; i++) {
+ if (i < PATTERN_INPUTS_64_COUNT) {
+ do_mips64r6_DCLZ(b64_pattern + i, b64_result + i);
+ } else {
+ do_mips64r6_DCLZ(b64_random + (i - PATTERN_INPUTS_64_COUNT),
+ b64_result + i);
+ }
+ }
+
+ 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_64(instruction_name, TEST_COUNT_TOTAL, elapsed_time,
+ b64_result, b64_expect);
+
+ return ret;
+}
diff --git a/tests/tcg/mips/user/isa/mips64r6/bit-swap/test_mips64r6_bitswap.c b/tests/tcg/mips/user/isa/mips64r6/bit-swap/test_mips64r6_bitswap.c
new file mode 100644
index 0000000..639850d
--- /dev/null
+++ b/tests/tcg/mips/user/isa/mips64r6/bit-swap/test_mips64r6_bitswap.c
@@ -0,0 +1,144 @@
+/*
+ * Test program for MIPS64R6 instruction BITSWAP
+ *
+ * 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_mips64r6.h"
+#include "../../../../include/test_inputs_64.h"
+#include "../../../../include/test_utils_64.h"
+
+#define TEST_COUNT_TOTAL (PATTERN_INPUTS_64_COUNT + RANDOM_INPUTS_64_COUNT)
+
+
+int32_t main(void)
+{
+ char *instruction_name = "BITSWAP";
+ int32_t ret;
+ uint32_t i;
+ struct timeval start, end;
+ double elapsed_time;
+
+ uint64_t b64_result[TEST_COUNT_TOTAL];
+ uint64_t b64_expect[TEST_COUNT_TOTAL] = {
+ 0xffffffffffffffffULL, /* 0 */
+ 0x0000000000000000ULL,
+ 0x0000000055555555ULL,
+ 0xffffffffaaaaaaaaULL,
+ 0x0000000033333333ULL,
+ 0xffffffffccccccccULL,
+ 0x00000000711cc771ULL,
+ 0xffffffff8ee3388eULL,
+ 0x000000000f0f0f0fULL, /* 8 */
+ 0xfffffffff0f0f0f0ULL,
+ 0x00000000071f7cf0ULL,
+ 0xfffffffff8e0830fULL,
+ 0xfffffffff0033ff0ULL,
+ 0x000000000ffcc00fULL,
+ 0x0000000007fc017fULL,
+ 0xfffffffff803fe80ULL,
+ 0xffffffffff00ff00ULL, /* 16 */
+ 0x0000000000ff00ffULL,
+ 0xfffffffff01fc07fULL,
+ 0x000000000fe03f80ULL,
+ 0x0000000000ff03f0ULL,
+ 0xffffffffff00fc0fULL,
+ 0x0000000001f07f00ULL,
+ 0xfffffffffe0f80ffULL,
+ 0x000000000f00ff0fULL, /* 24 */
+ 0xfffffffff0ff00f0ULL,
+ 0x000000007f00f0ffULL,
+ 0xffffffff80ff0f00ULL,
+ 0xffffffffff0300ffULL,
+ 0x0000000000fcff00ULL,
+ 0xffffffffff1f00f0ULL,
+ 0x0000000000e0ff0fULL,
+ 0xffffffffffff0000ULL, /* 32 */
+ 0x000000000000ffffULL,
+ 0xfffffffffcff0700ULL,
+ 0x000000000300f8ffULL,
+ 0xfffffffff0ff3f00ULL,
+ 0x000000000f00c0ffULL,
+ 0xffffffffc0ffff01ULL,
+ 0x000000003f0000feULL,
+ 0x0000000000ffff0fULL, /* 40 */
+ 0xffffffffff0000f0ULL,
+ 0x0000000000fcff7fULL,
+ 0xffffffffff030080ULL,
+ 0x0000000000f0ffffULL,
+ 0xffffffffff0f0000ULL,
+ 0x0000000000c0ffffULL,
+ 0xffffffffff3f0000ULL,
+ 0x000000000000ffffULL, /* 48 */
+ 0xffffffffffff0000ULL,
+ 0x000000000000fcffULL,
+ 0xffffffffffff0300ULL,
+ 0x000000000000f0ffULL,
+ 0xffffffffffff0f00ULL,
+ 0x000000000000c0ffULL,
+ 0xffffffffffff3f00ULL,
+ 0x00000000000000ffULL, /* 56 */
+ 0xffffffffffffff00ULL,
+ 0x00000000000000fcULL,
+ 0xffffffffffffff03ULL,
+ 0x00000000000000f0ULL,
+ 0xffffffffffffff0fULL,
+ 0x00000000000000c0ULL,
+ 0xffffffffffffff3fULL,
+ 0x000000001446aa02ULL, /* 64 */
+ 0xffffffffb2c9e310ULL,
+ 0xffffffff9df3d101ULL,
+ 0x000000007a8c4772ULL,
+ 0xffffffffbef5421aULL,
+ 0xffffffffff50749fULL,
+ 0xffffffffa6533d52ULL,
+ 0x000000005965ed41ULL,
+ 0x000000006a756792ULL, /* 72 */
+ 0xffffffffa69ba7ebULL,
+ 0xffffffff93d363d8ULL,
+ 0xffffffff8c152675ULL,
+ 0x00000000654a5750ULL,
+ 0xffffffff98c48615ULL,
+ 0x00000000447def39ULL,
+ 0x000000004f9a7bb5ULL,
+ };
+
+ gettimeofday(&start, NULL);
+
+ for (i = 0; i < TEST_COUNT_TOTAL; i++) {
+ if (i < PATTERN_INPUTS_64_COUNT) {
+ do_mips64r6_BITSWAP(b64_pattern + i, b64_result + i);
+ } else {
+ do_mips64r6_BITSWAP(b64_random + (i - PATTERN_INPUTS_64_COUNT),
+ b64_result + i);
+ }
+ }
+
+ 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_64(instruction_name, TEST_COUNT_TOTAL, elapsed_time,
+ b64_result, b64_expect);
+
+ return ret;
+}
diff --git a/tests/tcg/mips/user/isa/mips64r6/bit-swap/test_mips64r6_dbitswap.c b/tests/tcg/mips/user/isa/mips64r6/bit-swap/test_mips64r6_dbitswap.c
new file mode 100644
index 0000000..366fe61
--- /dev/null
+++ b/tests/tcg/mips/user/isa/mips64r6/bit-swap/test_mips64r6_dbitswap.c
@@ -0,0 +1,144 @@
+/*
+ * Test program for MIPS64R6 instruction DBITSWAP
+ *
+ * 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_mips64r6.h"
+#include "../../../../include/test_inputs_64.h"
+#include "../../../../include/test_utils_64.h"
+
+#define TEST_COUNT_TOTAL (PATTERN_INPUTS_64_COUNT + RANDOM_INPUTS_64_COUNT)
+
+
+int32_t main(void)
+{
+ char *instruction_name = "DBITSWAP";
+ int32_t ret;
+ uint32_t i;
+ struct timeval start, end;
+ double elapsed_time;
+
+ uint64_t b64_result[TEST_COUNT_TOTAL];
+ uint64_t b64_expect[TEST_COUNT_TOTAL] = {
+ 0xffffffffffffffffULL, /* 0 */
+ 0x0000000000000000ULL,
+ 0x5555555555555555ULL,
+ 0xaaaaaaaaaaaaaaaaULL,
+ 0x3333333333333333ULL,
+ 0xccccccccccccccccULL,
+ 0xc7711cc7711cc771ULL,
+ 0x388ee3388ee3388eULL,
+ 0x0f0f0f0f0f0f0f0fULL, /* 8 */
+ 0xf0f0f0f0f0f0f0f0ULL,
+ 0x1f7cf0c1071f7cf0ULL,
+ 0xe0830f3ef8e0830fULL,
+ 0x3ff0033ff0033ff0ULL,
+ 0xc00ffcc00ffcc00fULL,
+ 0x7fc01ff007fc017fULL,
+ 0x803fe00ff803fe80ULL,
+ 0xff00ff00ff00ff00ULL, /* 16 */
+ 0x00ff00ff00ff00ffULL,
+ 0xff01fc07f01fc07fULL,
+ 0x00fe03f80fe03f80ULL,
+ 0xff03f03f00ff03f0ULL,
+ 0x00fc0fc0ff00fc0fULL,
+ 0xff07c0ff01f07f00ULL,
+ 0x00f83f00fe0f80ffULL,
+ 0xff0f00ff0f00ff0fULL, /* 24 */
+ 0x00f0ff00f0ff00f0ULL,
+ 0xff1f00fc7f00f0ffULL,
+ 0x00e0ff0380ff0f00ULL,
+ 0xff3f00f0ff0300ffULL,
+ 0x00c0ff0f00fcff00ULL,
+ 0xff7f00c0ff1f00f0ULL,
+ 0x0080ff3f00e0ff0fULL,
+ 0xffff0000ffff0000ULL, /* 32 */
+ 0x0000ffff0000ffffULL,
+ 0xffff0100fcff0700ULL,
+ 0x0000feff0300f8ffULL,
+ 0xffff0300f0ff3f00ULL,
+ 0x0000fcff0f00c0ffULL,
+ 0xffff0700c0ffff01ULL,
+ 0x0000f8ff3f0000feULL,
+ 0xffff0f0000ffff0fULL, /* 40 */
+ 0x0000f0ffff0000f0ULL,
+ 0xffff1f0000fcff7fULL,
+ 0x0000e0ffff030080ULL,
+ 0xffff3f0000f0ffffULL,
+ 0x0000c0ffff0f0000ULL,
+ 0xffff7f0000c0ffffULL,
+ 0x000080ffff3f0000ULL,
+ 0xffffff000000ffffULL, /* 48 */
+ 0x000000ffffff0000ULL,
+ 0xffffff010000fcffULL,
+ 0x000000feffff0300ULL,
+ 0xffffff030000f0ffULL,
+ 0x000000fcffff0f00ULL,
+ 0xffffff070000c0ffULL,
+ 0x000000f8ffff3f00ULL,
+ 0xffffff0f000000ffULL, /* 56 */
+ 0x000000f0ffffff00ULL,
+ 0xffffff1f000000fcULL,
+ 0x000000e0ffffff03ULL,
+ 0xffffff3f000000f0ULL,
+ 0x000000c0ffffff0fULL,
+ 0xffffff7f000000c0ULL,
+ 0x00000080ffffff3fULL,
+ 0x115667331446aa02ULL, /* 64 */
+ 0xdf7d00c6b2c9e310ULL,
+ 0x355a75559df3d101ULL,
+ 0x0ef268b27a8c4772ULL,
+ 0x9d49d63ebef5421aULL,
+ 0x0be47d91ff50749fULL,
+ 0x1ddc1a60a6533d52ULL,
+ 0x3ff1c40f5965ed41ULL,
+ 0x047890b36a756792ULL, /* 72 */
+ 0xa53e9bc8a69ba7ebULL,
+ 0x45176faf93d363d8ULL,
+ 0x15394f8f8c152675ULL,
+ 0x67281c97654a5750ULL,
+ 0x2952acbf98c48615ULL,
+ 0x620c42c6447def39ULL,
+ 0xd15ae5454f9a7bb5ULL,
+ };
+
+ gettimeofday(&start, NULL);
+
+ for (i = 0; i < TEST_COUNT_TOTAL; i++) {
+ if (i < PATTERN_INPUTS_64_COUNT) {
+ do_mips64r6_DBITSWAP(b64_pattern + i, b64_result + i);
+ } else {
+ do_mips64r6_DBITSWAP(b64_random + (i - PATTERN_INPUTS_64_COUNT),
+ b64_result + i);
+ }
+ }
+
+ 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_64(instruction_name, TEST_COUNT_TOTAL, elapsed_time,
+ b64_result, b64_expect);
+
+ return ret;
+}
diff --git a/tests/tcg/mips/user/isa/mips64r6/int-multiply/test_mips64r6_dmuh.c b/tests/tcg/mips/user/isa/mips64r6/int-multiply/test_mips64r6_dmuh.c
new file mode 100644
index 0000000..c049378
--- /dev/null
+++ b/tests/tcg/mips/user/isa/mips64r6/int-multiply/test_mips64r6_dmuh.c
@@ -0,0 +1,151 @@
+/*
+ * Test program for MIPS64R6 instruction DMUH
+ *
+ * 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_mips64r6.h"
+#include "../../../../include/test_inputs_64.h"
+#include "../../../../include/test_utils_64.h"
+
+#define TEST_COUNT_TOTAL (PATTERN_INPUTS_64_COUNT + RANDOM_INPUTS_64_COUNT)
+
+
+int32_t main(void)
+{
+ char *instruction_name = "DMUH";
+ int32_t ret;
+ uint32_t i, j;
+ struct timeval start, end;
+ double elapsed_time;
+
+ uint64_t b64_result[TEST_COUNT_TOTAL];
+ uint64_t b64_expect[TEST_COUNT_TOTAL] = {
+ 0x0000000000000000ULL, /* 0 */
+ 0x0000000000000000ULL,
+ 0x0000000000000000ULL,
+ 0xffffffffffffffffULL,
+ 0x0000000000000000ULL,
+ 0xffffffffffffffffULL,
+ 0x0000000000000000ULL,
+ 0xffffffffffffffffULL,
+ 0x0000000000000000ULL, /* 8 */
+ 0x0000000000000000ULL,
+ 0x0000000000000000ULL,
+ 0x0000000000000000ULL,
+ 0x0000000000000000ULL,
+ 0x0000000000000000ULL,
+ 0x0000000000000000ULL,
+ 0x0000000000000000ULL,
+ 0x0000000000000000ULL, /* 16 */
+ 0x0000000000000000ULL,
+ 0x1c71c71c71c71c72ULL,
+ 0xe38e38e38e38e38eULL,
+ 0x1111111111111111ULL,
+ 0xeeeeeeeeeeeeeeeeULL,
+ 0x097b425ed097b426ULL,
+ 0xf684bda12f684bdaULL,
+ 0xffffffffffffffffULL, /* 24 */
+ 0x0000000000000000ULL,
+ 0xe38e38e38e38e38eULL,
+ 0x1c71c71c71c71c71ULL,
+ 0xeeeeeeeeeeeeeeeeULL,
+ 0x1111111111111110ULL,
+ 0xf684bda12f684bdaULL,
+ 0x097b425ed097b425ULL,
+ 0x0000000000000000ULL, /* 32 */
+ 0x0000000000000000ULL,
+ 0x1111111111111111ULL,
+ 0xeeeeeeeeeeeeeeeeULL,
+ 0x0a3d70a3d70a3d70ULL,
+ 0xf5c28f5c28f5c28fULL,
+ 0x05b05b05b05b05b0ULL,
+ 0xfa4fa4fa4fa4fa4fULL,
+ 0xffffffffffffffffULL, /* 40 */
+ 0x0000000000000000ULL,
+ 0xeeeeeeeeeeeeeeeeULL,
+ 0x1111111111111110ULL,
+ 0xf5c28f5c28f5c28fULL,
+ 0x0a3d70a3d70a3d70ULL,
+ 0xfa4fa4fa4fa4fa4fULL,
+ 0x05b05b05b05b05b0ULL,
+ 0x0000000000000000ULL, /* 48 */
+ 0x0000000000000000ULL,
+ 0x097b425ed097b426ULL,
+ 0xf684bda12f684bdaULL,
+ 0x05b05b05b05b05b0ULL,
+ 0xfa4fa4fa4fa4fa4fULL,
+ 0x0329161f9add3c0cULL,
+ 0xfcd6e9e06522c3f3ULL,
+ 0xffffffffffffffffULL, /* 56 */
+ 0x0000000000000000ULL,
+ 0xf684bda12f684bdaULL,
+ 0x097b425ed097b425ULL,
+ 0xfa4fa4fa4fa4fa4fULL,
+ 0x05b05b05b05b05b0ULL,
+ 0xfcd6e9e06522c3f3ULL,
+ 0x0329161f9add3c0cULL,
+ 0x37dbf4448b48bce3ULL, /* 64 */
+ 0x01fd28a6ebd66e19ULL,
+ 0x271290430f9643afULL,
+ 0xcb89d38b96a86603ULL,
+ 0x01fd28a6ebd66e19ULL,
+ 0x00122100b25f881aULL,
+ 0x016425c3dacd63e9ULL,
+ 0xfe21cf6e9b332df5ULL,
+ 0x271290430f9643afULL, /* 72 */
+ 0x016425c3dacd63e9ULL,
+ 0x1b549d7f3d46f8d3ULL,
+ 0xdb4dd51d1b7c58f2ULL,
+ 0xcb89d38b96a86603ULL,
+ 0xfe21cf6e9b332df5ULL,
+ 0xdb4dd51d1b7c58f2ULL,
+ 0x31454bf2781d2c60ULL,
+ };
+
+ gettimeofday(&start, NULL);
+
+ for (i = 0; i < PATTERN_INPUTS_64_SHORT_COUNT; i++) {
+ for (j = 0; j < PATTERN_INPUTS_64_SHORT_COUNT; j++) {
+ do_mips64r6_DMUH(b64_pattern + i, b64_pattern + j,
+ b64_result + (PATTERN_INPUTS_64_SHORT_COUNT * i + j));
+ }
+ }
+
+ for (i = 0; i < RANDOM_INPUTS_64_SHORT_COUNT; i++) {
+ for (j = 0; j < RANDOM_INPUTS_64_SHORT_COUNT; j++) {
+ do_mips64r6_DMUH(b64_random + i, b64_random + j,
+ b64_result + (((PATTERN_INPUTS_64_SHORT_COUNT) *
+ (PATTERN_INPUTS_64_SHORT_COUNT)) +
+ RANDOM_INPUTS_64_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_64(instruction_name, TEST_COUNT_TOTAL, elapsed_time,
+ b64_result, b64_expect);
+
+ return ret;
+}
diff --git a/tests/tcg/mips/user/isa/mips64r6/int-multiply/test_mips64r6_dmuhu.c b/tests/tcg/mips/user/isa/mips64r6/int-multiply/test_mips64r6_dmuhu.c
new file mode 100644
index 0000000..dfb4195
--- /dev/null
+++ b/tests/tcg/mips/user/isa/mips64r6/int-multiply/test_mips64r6_dmuhu.c
@@ -0,0 +1,151 @@
+/*
+ * Test program for MIPS64R6 instruction DMUHU
+ *
+ * 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_mips64r6.h"
+#include "../../../../include/test_inputs_64.h"
+#include "../../../../include/test_utils_64.h"
+
+#define TEST_COUNT_TOTAL (PATTERN_INPUTS_64_COUNT + RANDOM_INPUTS_64_COUNT)
+
+
+int32_t main(void)
+{
+ char *instruction_name = "DMUHU";
+ int32_t ret;
+ uint32_t i, j;
+ struct timeval start, end;
+ double elapsed_time;
+
+ uint64_t b64_result[TEST_COUNT_TOTAL];
+ uint64_t b64_expect[TEST_COUNT_TOTAL] = {
+ 0xfffffffffffffffeULL, /* 0 */
+ 0x0000000000000000ULL,
+ 0xaaaaaaaaaaaaaaa9ULL,
+ 0x5555555555555554ULL,
+ 0xcccccccccccccccbULL,
+ 0x3333333333333332ULL,
+ 0xe38e38e38e38e38dULL,
+ 0x1c71c71c71c71c70ULL,
+ 0x0000000000000000ULL, /* 8 */
+ 0x0000000000000000ULL,
+ 0x0000000000000000ULL,
+ 0x0000000000000000ULL,
+ 0x0000000000000000ULL,
+ 0x0000000000000000ULL,
+ 0x0000000000000000ULL,
+ 0x0000000000000000ULL,
+ 0xaaaaaaaaaaaaaaa9ULL, /* 16 */
+ 0x0000000000000000ULL,
+ 0x71c71c71c71c71c6ULL,
+ 0x38e38e38e38e38e3ULL,
+ 0x8888888888888887ULL,
+ 0x2222222222222221ULL,
+ 0x97b425ed097b425eULL,
+ 0x12f684bda12f684bULL,
+ 0x5555555555555554ULL, /* 24 */
+ 0x0000000000000000ULL,
+ 0x38e38e38e38e38e3ULL,
+ 0x1c71c71c71c71c71ULL,
+ 0x4444444444444443ULL,
+ 0x1111111111111110ULL,
+ 0x4bda12f684bda12fULL,
+ 0x097b425ed097b425ULL,
+ 0xcccccccccccccccbULL, /* 32 */
+ 0x0000000000000000ULL,
+ 0x8888888888888887ULL,
+ 0x4444444444444443ULL,
+ 0xa3d70a3d70a3d708ULL,
+ 0x28f5c28f5c28f5c2ULL,
+ 0xb60b60b60b60b60aULL,
+ 0x16c16c16c16c16c0ULL,
+ 0x3333333333333332ULL, /* 40 */
+ 0x0000000000000000ULL,
+ 0x2222222222222221ULL,
+ 0x1111111111111110ULL,
+ 0x28f5c28f5c28f5c2ULL,
+ 0x0a3d70a3d70a3d70ULL,
+ 0x2d82d82d82d82d82ULL,
+ 0x05b05b05b05b05b0ULL,
+ 0xe38e38e38e38e38dULL, /* 48 */
+ 0x0000000000000000ULL,
+ 0x97b425ed097b425eULL,
+ 0x4bda12f684bda12fULL,
+ 0xb60b60b60b60b60aULL,
+ 0x2d82d82d82d82d82ULL,
+ 0xca4587e6b74f0328ULL,
+ 0x1948b0fcd6e9e064ULL,
+ 0x1c71c71c71c71c70ULL, /* 56 */
+ 0x0000000000000000ULL,
+ 0x12f684bda12f684bULL,
+ 0x097b425ed097b425ULL,
+ 0x16c16c16c16c16c0ULL,
+ 0x05b05b05b05b05b0ULL,
+ 0x1948b0fcd6e9e064ULL,
+ 0x0329161f9add3c0cULL,
+ 0x48b1c1dcdc0d6763ULL, /* 64 */
+ 0x86260fd661cc8a61ULL,
+ 0x5bd825b9f1c8246fULL,
+ 0x3bd8e9d8f4da4851ULL,
+ 0x86260fd661cc8a61ULL,
+ 0xf78e21c74d87162aULL,
+ 0xa97cd4d1e230b671ULL,
+ 0x6e70e5bbf9651043ULL,
+ 0x5bd825b9f1c8246fULL, /* 72 */
+ 0xa97cd4d1e230b671ULL,
+ 0x7409fad4b0e60fd3ULL,
+ 0x4b9ceb6a79ae3b40ULL,
+ 0x3bd8e9d8f4da4851ULL,
+ 0x6e70e5bbf9651043ULL,
+ 0x4b9ceb6a79ae3b40ULL,
+ 0x31454bf2781d2c60ULL,
+ };
+
+ gettimeofday(&start, NULL);
+
+ for (i = 0; i < PATTERN_INPUTS_64_SHORT_COUNT; i++) {
+ for (j = 0; j < PATTERN_INPUTS_64_SHORT_COUNT; j++) {
+ do_mips64r6_DMUHU(b64_pattern + i, b64_pattern + j,
+ b64_result + (PATTERN_INPUTS_64_SHORT_COUNT * i + j));
+ }
+ }
+
+ for (i = 0; i < RANDOM_INPUTS_64_SHORT_COUNT; i++) {
+ for (j = 0; j < RANDOM_INPUTS_64_SHORT_COUNT; j++) {
+ do_mips64r6_DMUHU(b64_random + i, b64_random + j,
+ b64_result + (((PATTERN_INPUTS_64_SHORT_COUNT) *
+ (PATTERN_INPUTS_64_SHORT_COUNT)) +
+ RANDOM_INPUTS_64_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_64(instruction_name, TEST_COUNT_TOTAL, elapsed_time,
+ b64_result, b64_expect);
+
+ return ret;
+}
diff --git a/tests/tcg/mips/user/isa/mips64r6/int-multiply/test_mips64r6_dmul.c b/tests/tcg/mips/user/isa/mips64r6/int-multiply/test_mips64r6_dmul.c
new file mode 100644
index 0000000..3c337dd
--- /dev/null
+++ b/tests/tcg/mips/user/isa/mips64r6/int-multiply/test_mips64r6_dmul.c
@@ -0,0 +1,151 @@
+/*
+ * Test program for MIPS64R6 instruction DMUL
+ *
+ * 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_mips64r6.h"
+#include "../../../../include/test_inputs_64.h"
+#include "../../../../include/test_utils_64.h"
+
+#define TEST_COUNT_TOTAL (PATTERN_INPUTS_64_COUNT + RANDOM_INPUTS_64_COUNT)
+
+
+int32_t main(void)
+{
+ char *instruction_name = "DMUL";
+ int32_t ret;
+ uint32_t i, j;
+ struct timeval start, end;
+ double elapsed_time;
+
+ uint64_t b64_result[TEST_COUNT_TOTAL];
+ uint64_t b64_expect[TEST_COUNT_TOTAL] = {
+ 0x0000000000000001ULL, /* 0 */
+ 0x0000000000000000ULL,
+ 0x5555555555555556ULL,
+ 0xaaaaaaaaaaaaaaabULL,
+ 0x3333333333333334ULL,
+ 0xcccccccccccccccdULL,
+ 0x1c71c71c71c71c72ULL,
+ 0xe38e38e38e38e38fULL,
+ 0x0000000000000000ULL, /* 8 */
+ 0x0000000000000000ULL,
+ 0x0000000000000000ULL,
+ 0x0000000000000000ULL,
+ 0x0000000000000000ULL,
+ 0x0000000000000000ULL,
+ 0x0000000000000000ULL,
+ 0x0000000000000000ULL,
+ 0x5555555555555556ULL, /* 16 */
+ 0x0000000000000000ULL,
+ 0x38e38e38e38e38e4ULL,
+ 0x1c71c71c71c71c72ULL,
+ 0x7777777777777778ULL,
+ 0xdddddddddddddddeULL,
+ 0x12f684bda12f684cULL,
+ 0x425ed097b425ed0aULL,
+ 0xaaaaaaaaaaaaaaabULL, /* 24 */
+ 0x0000000000000000ULL,
+ 0x1c71c71c71c71c72ULL,
+ 0x8e38e38e38e38e39ULL,
+ 0xbbbbbbbbbbbbbbbcULL,
+ 0xeeeeeeeeeeeeeeefULL,
+ 0x097b425ed097b426ULL,
+ 0xa12f684bda12f685ULL,
+ 0x3333333333333334ULL, /* 32 */
+ 0x0000000000000000ULL,
+ 0x7777777777777778ULL,
+ 0xbbbbbbbbbbbbbbbcULL,
+ 0xf5c28f5c28f5c290ULL,
+ 0x3d70a3d70a3d70a4ULL,
+ 0x7d27d27d27d27d28ULL,
+ 0xb60b60b60b60b60cULL,
+ 0xcccccccccccccccdULL, /* 40 */
+ 0x0000000000000000ULL,
+ 0xdddddddddddddddeULL,
+ 0xeeeeeeeeeeeeeeefULL,
+ 0x3d70a3d70a3d70a4ULL,
+ 0x8f5c28f5c28f5c29ULL,
+ 0x9f49f49f49f49f4aULL,
+ 0x2d82d82d82d82d83ULL,
+ 0x1c71c71c71c71c72ULL, /* 48 */
+ 0x0000000000000000ULL,
+ 0x12f684bda12f684cULL,
+ 0x097b425ed097b426ULL,
+ 0x7d27d27d27d27d28ULL,
+ 0x9f49f49f49f49f4aULL,
+ 0xb0fcd6e9e06522c4ULL,
+ 0x6b74f0329161f9aeULL,
+ 0xe38e38e38e38e38fULL, /* 56 */
+ 0x0000000000000000ULL,
+ 0x425ed097b425ed0aULL,
+ 0xa12f684bda12f685ULL,
+ 0xb60b60b60b60b60cULL,
+ 0x2d82d82d82d82d83ULL,
+ 0x6b74f0329161f9aeULL,
+ 0x781948b0fcd6e9e1ULL,
+ 0xad45be6961639000ULL, /* 64 */
+ 0xefa7a5a0e7176a00ULL,
+ 0x08c6139fc4346000ULL,
+ 0xfbe1883aee787980ULL,
+ 0xefa7a5a0e7176a00ULL,
+ 0x37ae2b38fded7040ULL,
+ 0x6acb3d68be6cdc00ULL,
+ 0xedbf72842143b470ULL,
+ 0x08c6139fc4346000ULL, /* 72 */
+ 0x6acb3d68be6cdc00ULL,
+ 0x8624e5e1e5044000ULL,
+ 0x76a5ab8089e38100ULL,
+ 0xfbe1883aee787980ULL,
+ 0xedbf72842143b470ULL,
+ 0x76a5ab8089e38100ULL,
+ 0x4bb436d5b1e9cfc4ULL,
+ };
+
+ gettimeofday(&start, NULL);
+
+ for (i = 0; i < PATTERN_INPUTS_64_SHORT_COUNT; i++) {
+ for (j = 0; j < PATTERN_INPUTS_64_SHORT_COUNT; j++) {
+ do_mips64r6_DMUL(b64_pattern + i, b64_pattern + j,
+ b64_result + (PATTERN_INPUTS_64_SHORT_COUNT * i + j));
+ }
+ }
+
+ for (i = 0; i < RANDOM_INPUTS_64_SHORT_COUNT; i++) {
+ for (j = 0; j < RANDOM_INPUTS_64_SHORT_COUNT; j++) {
+ do_mips64r6_DMUL(b64_random + i, b64_random + j,
+ b64_result + (((PATTERN_INPUTS_64_SHORT_COUNT) *
+ (PATTERN_INPUTS_64_SHORT_COUNT)) +
+ RANDOM_INPUTS_64_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_64(instruction_name, TEST_COUNT_TOTAL, elapsed_time,
+ b64_result, b64_expect);
+
+ return ret;
+}
diff --git a/tests/tcg/mips/user/isa/mips64r6/int-multiply/test_mips64r6_dmulu.c b/tests/tcg/mips/user/isa/mips64r6/int-multiply/test_mips64r6_dmulu.c
new file mode 100644
index 0000000..b20a1ba
--- /dev/null
+++ b/tests/tcg/mips/user/isa/mips64r6/int-multiply/test_mips64r6_dmulu.c
@@ -0,0 +1,151 @@
+/*
+ * Test program for MIPS64R6 instruction DMULU
+ *
+ * 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_mips64r6.h"
+#include "../../../../include/test_inputs_64.h"
+#include "../../../../include/test_utils_64.h"
+
+#define TEST_COUNT_TOTAL (PATTERN_INPUTS_64_COUNT + RANDOM_INPUTS_64_COUNT)
+
+
+int32_t main(void)
+{
+ char *instruction_name = "DMULU";
+ int32_t ret;
+ uint32_t i, j;
+ struct timeval start, end;
+ double elapsed_time;
+
+ uint64_t b64_result[TEST_COUNT_TOTAL];
+ uint64_t b64_expect[TEST_COUNT_TOTAL] = {
+ 0x0000000000000001ULL, /* 0 */
+ 0x0000000000000000ULL,
+ 0x5555555555555556ULL,
+ 0xaaaaaaaaaaaaaaabULL,
+ 0x3333333333333334ULL,
+ 0xcccccccccccccccdULL,
+ 0x1c71c71c71c71c72ULL,
+ 0xe38e38e38e38e38fULL,
+ 0x0000000000000000ULL, /* 8 */
+ 0x0000000000000000ULL,
+ 0x0000000000000000ULL,
+ 0x0000000000000000ULL,
+ 0x0000000000000000ULL,
+ 0x0000000000000000ULL,
+ 0x0000000000000000ULL,
+ 0x0000000000000000ULL,
+ 0x5555555555555556ULL, /* 16 */
+ 0x0000000000000000ULL,
+ 0x38e38e38e38e38e4ULL,
+ 0x1c71c71c71c71c72ULL,
+ 0x7777777777777778ULL,
+ 0xdddddddddddddddeULL,
+ 0x12f684bda12f684cULL,
+ 0x425ed097b425ed0aULL,
+ 0xaaaaaaaaaaaaaaabULL, /* 24 */
+ 0x0000000000000000ULL,
+ 0x1c71c71c71c71c72ULL,
+ 0x8e38e38e38e38e39ULL,
+ 0xbbbbbbbbbbbbbbbcULL,
+ 0xeeeeeeeeeeeeeeefULL,
+ 0x097b425ed097b426ULL,
+ 0xa12f684bda12f685ULL,
+ 0x3333333333333334ULL, /* 32 */
+ 0x0000000000000000ULL,
+ 0x7777777777777778ULL,
+ 0xbbbbbbbbbbbbbbbcULL,
+ 0xf5c28f5c28f5c290ULL,
+ 0x3d70a3d70a3d70a4ULL,
+ 0x7d27d27d27d27d28ULL,
+ 0xb60b60b60b60b60cULL,
+ 0xcccccccccccccccdULL, /* 40 */
+ 0x0000000000000000ULL,
+ 0xdddddddddddddddeULL,
+ 0xeeeeeeeeeeeeeeefULL,
+ 0x3d70a3d70a3d70a4ULL,
+ 0x8f5c28f5c28f5c29ULL,
+ 0x9f49f49f49f49f4aULL,
+ 0x2d82d82d82d82d83ULL,
+ 0x1c71c71c71c71c72ULL, /* 48 */
+ 0x0000000000000000ULL,
+ 0x12f684bda12f684cULL,
+ 0x097b425ed097b426ULL,
+ 0x7d27d27d27d27d28ULL,
+ 0x9f49f49f49f49f4aULL,
+ 0xb0fcd6e9e06522c4ULL,
+ 0x6b74f0329161f9aeULL,
+ 0xe38e38e38e38e38fULL, /* 56 */
+ 0x0000000000000000ULL,
+ 0x425ed097b425ed0aULL,
+ 0xa12f684bda12f685ULL,
+ 0xb60b60b60b60b60cULL,
+ 0x2d82d82d82d82d83ULL,
+ 0x6b74f0329161f9aeULL,
+ 0x781948b0fcd6e9e1ULL,
+ 0xad45be6961639000ULL, /* 64 */
+ 0xefa7a5a0e7176a00ULL,
+ 0x08c6139fc4346000ULL,
+ 0xfbe1883aee787980ULL,
+ 0xefa7a5a0e7176a00ULL,
+ 0x37ae2b38fded7040ULL,
+ 0x6acb3d68be6cdc00ULL,
+ 0xedbf72842143b470ULL,
+ 0x08c6139fc4346000ULL, /* 72 */
+ 0x6acb3d68be6cdc00ULL,
+ 0x8624e5e1e5044000ULL,
+ 0x76a5ab8089e38100ULL,
+ 0xfbe1883aee787980ULL,
+ 0xedbf72842143b470ULL,
+ 0x76a5ab8089e38100ULL,
+ 0x4bb436d5b1e9cfc4ULL,
+ };
+
+ gettimeofday(&start, NULL);
+
+ for (i = 0; i < PATTERN_INPUTS_64_SHORT_COUNT; i++) {
+ for (j = 0; j < PATTERN_INPUTS_64_SHORT_COUNT; j++) {
+ do_mips64r6_DMULU(b64_pattern + i, b64_pattern + j,
+ b64_result + (PATTERN_INPUTS_64_SHORT_COUNT * i + j));
+ }
+ }
+
+ for (i = 0; i < RANDOM_INPUTS_64_SHORT_COUNT; i++) {
+ for (j = 0; j < RANDOM_INPUTS_64_SHORT_COUNT; j++) {
+ do_mips64r6_DMULU(b64_random + i, b64_random + j,
+ b64_result + (((PATTERN_INPUTS_64_SHORT_COUNT) *
+ (PATTERN_INPUTS_64_SHORT_COUNT)) +
+ RANDOM_INPUTS_64_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_64(instruction_name, TEST_COUNT_TOTAL, elapsed_time,
+ b64_result, b64_expect);
+
+ return ret;
+}
diff --git a/tests/tcg/mips/user/isa/mips64r6/int-multiply/test_mips64r6_muh.c b/tests/tcg/mips/user/isa/mips64r6/int-multiply/test_mips64r6_muh.c
new file mode 100644
index 0000000..9134074
--- /dev/null
+++ b/tests/tcg/mips/user/isa/mips64r6/int-multiply/test_mips64r6_muh.c
@@ -0,0 +1,151 @@
+/*
+ * Test program for MIPS64R6 instruction MUH
+ *
+ * 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_mips64r6.h"
+#include "../../../../include/test_inputs_64.h"
+#include "../../../../include/test_utils_64.h"
+
+#define TEST_COUNT_TOTAL (PATTERN_INPUTS_64_COUNT + RANDOM_INPUTS_64_COUNT)
+
+
+int32_t main(void)
+{
+ char *instruction_name = "MUH";
+ int32_t ret;
+ uint32_t i, j;
+ struct timeval start, end;
+ double elapsed_time;
+
+ uint64_t b64_result[TEST_COUNT_TOTAL];
+ uint64_t b64_expect[TEST_COUNT_TOTAL] = {
+ 0x0000000000000000ULL, /* 0 */
+ 0x0000000000000000ULL,
+ 0x0000000000000000ULL,
+ 0xffffffffffffffffULL,
+ 0x0000000000000000ULL,
+ 0xffffffffffffffffULL,
+ 0x0000000000000000ULL,
+ 0xffffffffffffffffULL,
+ 0x0000000000000000ULL, /* 8 */
+ 0x0000000000000000ULL,
+ 0x0000000000000000ULL,
+ 0x0000000000000000ULL,
+ 0x0000000000000000ULL,
+ 0x0000000000000000ULL,
+ 0x0000000000000000ULL,
+ 0x0000000000000000ULL,
+ 0x0000000000000000ULL, /* 16 */
+ 0x0000000000000000ULL,
+ 0x000000001c71c71cULL,
+ 0xffffffffe38e38e3ULL,
+ 0x0000000011111111ULL,
+ 0xffffffffeeeeeeeeULL,
+ 0x00000000097b425fULL,
+ 0xfffffffff684bda1ULL,
+ 0xffffffffffffffffULL, /* 24 */
+ 0x0000000000000000ULL,
+ 0xffffffffe38e38e3ULL,
+ 0x000000001c71c71cULL,
+ 0xffffffffeeeeeeeeULL,
+ 0x0000000011111110ULL,
+ 0xfffffffff684bda1ULL,
+ 0x00000000097b425eULL,
+ 0x0000000000000000ULL, /* 32 */
+ 0x0000000000000000ULL,
+ 0x0000000011111111ULL,
+ 0xffffffffeeeeeeeeULL,
+ 0x000000000a3d70a4ULL,
+ 0xfffffffff5c28f5cULL,
+ 0x0000000005b05b05ULL,
+ 0xfffffffffa4fa4faULL,
+ 0xffffffffffffffffULL, /* 40 */
+ 0x0000000000000000ULL,
+ 0xffffffffeeeeeeeeULL,
+ 0x0000000011111110ULL,
+ 0xfffffffff5c28f5cULL,
+ 0x000000000a3d70a3ULL,
+ 0xfffffffffa4fa4faULL,
+ 0x0000000005b05b05ULL,
+ 0x0000000000000000ULL, /* 48 */
+ 0x0000000000000000ULL,
+ 0x00000000097b425fULL,
+ 0xfffffffff684bda1ULL,
+ 0x0000000005b05b05ULL,
+ 0xfffffffffa4fa4faULL,
+ 0x000000000329161fULL,
+ 0xfffffffffcd6e9e0ULL,
+ 0xffffffffffffffffULL, /* 56 */
+ 0x0000000000000000ULL,
+ 0xfffffffff684bda1ULL,
+ 0x00000000097b425eULL,
+ 0xfffffffffa4fa4faULL,
+ 0x0000000005b05b05ULL,
+ 0xfffffffffcd6e9e0ULL,
+ 0x000000000329161fULL,
+ 0x0000000037dbf444ULL, /* 64 */
+ 0x0000000001fd28a7ULL,
+ 0x0000000027129043ULL,
+ 0xffffffffcb89d38bULL,
+ 0x0000000001fd28a7ULL,
+ 0x0000000000122100ULL,
+ 0x00000000016425c3ULL,
+ 0xfffffffffe21cf6eULL,
+ 0x0000000027129043ULL, /* 72 */
+ 0x00000000016425c3ULL,
+ 0x000000001b549d7fULL,
+ 0xffffffffdb4dd51cULL,
+ 0xffffffffcb89d38bULL,
+ 0xfffffffffe21cf6eULL,
+ 0xffffffffdb4dd51cULL,
+ 0x0000000031454bf2ULL,
+ };
+
+ gettimeofday(&start, NULL);
+
+ for (i = 0; i < PATTERN_INPUTS_64_SHORT_COUNT; i++) {
+ for (j = 0; j < PATTERN_INPUTS_64_SHORT_COUNT; j++) {
+ do_mips64r6_MUH(b64_pattern_se + i, b64_pattern_se + j,
+ b64_result + (PATTERN_INPUTS_64_SHORT_COUNT * i + j));
+ }
+ }
+
+ for (i = 0; i < RANDOM_INPUTS_64_SHORT_COUNT; i++) {
+ for (j = 0; j < RANDOM_INPUTS_64_SHORT_COUNT; j++) {
+ do_mips64r6_MUH(b64_random_se + i, b64_random_se + j,
+ b64_result + (((PATTERN_INPUTS_64_SHORT_COUNT) *
+ (PATTERN_INPUTS_64_SHORT_COUNT)) +
+ RANDOM_INPUTS_64_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_64(instruction_name, TEST_COUNT_TOTAL, elapsed_time,
+ b64_result, b64_expect);
+
+ return ret;
+}
diff --git a/tests/tcg/mips/user/isa/mips64r6/int-multiply/test_mips64r6_muhu.c b/tests/tcg/mips/user/isa/mips64r6/int-multiply/test_mips64r6_muhu.c
new file mode 100644
index 0000000..2485060
--- /dev/null
+++ b/tests/tcg/mips/user/isa/mips64r6/int-multiply/test_mips64r6_muhu.c
@@ -0,0 +1,151 @@
+/*
+ * Test program for MIPS64R6 instruction MUHU
+ *
+ * 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_mips64r6.h"
+#include "../../../../include/test_inputs_64.h"
+#include "../../../../include/test_utils_64.h"
+
+#define TEST_COUNT_TOTAL (PATTERN_INPUTS_64_COUNT + RANDOM_INPUTS_64_COUNT)
+
+
+int32_t main(void)
+{
+ char *instruction_name = "MUHU";
+ int32_t ret;
+ uint32_t i, j;
+ struct timeval start, end;
+ double elapsed_time;
+
+ uint64_t b64_result[TEST_COUNT_TOTAL];
+ uint64_t b64_expect[TEST_COUNT_TOTAL] = {
+ 0xfffffffffffffffeULL, /* 0 */
+ 0x0000000000000000ULL,
+ 0xffffffffaaaaaaa9ULL,
+ 0x0000000055555554ULL,
+ 0xffffffffcccccccbULL,
+ 0x0000000033333332ULL,
+ 0xffffffffe38e38e2ULL,
+ 0x000000001c71c71bULL,
+ 0x0000000000000000ULL, /* 8 */
+ 0x0000000000000000ULL,
+ 0x0000000000000000ULL,
+ 0x0000000000000000ULL,
+ 0x0000000000000000ULL,
+ 0x0000000000000000ULL,
+ 0x0000000000000000ULL,
+ 0x0000000000000000ULL,
+ 0xffffffffaaaaaaa9ULL, /* 16 */
+ 0x0000000000000000ULL,
+ 0x0000000071c71c70ULL,
+ 0x0000000038e38e38ULL,
+ 0xffffffff88888887ULL,
+ 0x0000000022222221ULL,
+ 0xffffffff97b425ecULL,
+ 0x0000000012f684bdULL,
+ 0x0000000055555554ULL, /* 24 */
+ 0x0000000000000000ULL,
+ 0x0000000038e38e38ULL,
+ 0x000000001c71c71cULL,
+ 0x0000000044444443ULL,
+ 0x0000000011111110ULL,
+ 0x000000004bda12f6ULL,
+ 0x00000000097b425eULL,
+ 0xffffffffcccccccbULL, /* 32 */
+ 0x0000000000000000ULL,
+ 0xffffffff88888887ULL,
+ 0x0000000044444443ULL,
+ 0xffffffffa3d70a3cULL,
+ 0x0000000028f5c28fULL,
+ 0xffffffffb60b60b4ULL,
+ 0x0000000016c16c16ULL,
+ 0x0000000033333332ULL, /* 40 */
+ 0x0000000000000000ULL,
+ 0x0000000022222221ULL,
+ 0x0000000011111110ULL,
+ 0x0000000028f5c28fULL,
+ 0x000000000a3d70a3ULL,
+ 0x000000002d82d82dULL,
+ 0x0000000005b05b05ULL,
+ 0xffffffffe38e38e2ULL, /* 48 */
+ 0x0000000000000000ULL,
+ 0xffffffff97b425ecULL,
+ 0x000000004bda12f6ULL,
+ 0xffffffffb60b60b4ULL,
+ 0x000000002d82d82dULL,
+ 0xffffffffca4587e5ULL,
+ 0x000000001948b0fcULL,
+ 0x000000001c71c71bULL, /* 56 */
+ 0x0000000000000000ULL,
+ 0x0000000012f684bdULL,
+ 0x00000000097b425eULL,
+ 0x0000000016c16c16ULL,
+ 0x0000000005b05b05ULL,
+ 0x000000001948b0fcULL,
+ 0x000000000329161fULL,
+ 0x0000000048b1c1dcULL, /* 64 */
+ 0xffffffff86260fd6ULL,
+ 0x000000005bd825b9ULL,
+ 0x000000003bd8e9d8ULL,
+ 0xffffffff86260fd6ULL,
+ 0xfffffffff78e21c6ULL,
+ 0xffffffffa97cd4d0ULL,
+ 0x000000006e70e5bbULL,
+ 0x000000005bd825b9ULL, /* 72 */
+ 0xffffffffa97cd4d0ULL,
+ 0x000000007409fad3ULL,
+ 0x000000004b9ceb69ULL,
+ 0x000000003bd8e9d8ULL,
+ 0x000000006e70e5bbULL,
+ 0x000000004b9ceb69ULL,
+ 0x0000000031454bf2ULL,
+ };
+
+ gettimeofday(&start, NULL);
+
+ for (i = 0; i < PATTERN_INPUTS_64_SHORT_COUNT; i++) {
+ for (j = 0; j < PATTERN_INPUTS_64_SHORT_COUNT; j++) {
+ do_mips64r6_MUHU(b64_pattern_se + i, b64_pattern_se + j,
+ b64_result + (PATTERN_INPUTS_64_SHORT_COUNT * i + j));
+ }
+ }
+
+ for (i = 0; i < RANDOM_INPUTS_64_SHORT_COUNT; i++) {
+ for (j = 0; j < RANDOM_INPUTS_64_SHORT_COUNT; j++) {
+ do_mips64r6_MUHU(b64_random_se + i, b64_random_se + j,
+ b64_result + (((PATTERN_INPUTS_64_SHORT_COUNT) *
+ (PATTERN_INPUTS_64_SHORT_COUNT)) +
+ RANDOM_INPUTS_64_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_64(instruction_name, TEST_COUNT_TOTAL, elapsed_time,
+ b64_result, b64_expect);
+
+ return ret;
+}
diff --git a/tests/tcg/mips/user/isa/mips64r6/int-multiply/test_mips64r6_mul.c b/tests/tcg/mips/user/isa/mips64r6/int-multiply/test_mips64r6_mul.c
new file mode 100644
index 0000000..acf779c
--- /dev/null
+++ b/tests/tcg/mips/user/isa/mips64r6/int-multiply/test_mips64r6_mul.c
@@ -0,0 +1,151 @@
+/*
+ * Test program for MIPS64R6 instruction MUL
+ *
+ * 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_mips64r6.h"
+#include "../../../../include/test_inputs_64.h"
+#include "../../../../include/test_utils_64.h"
+
+#define TEST_COUNT_TOTAL (PATTERN_INPUTS_64_COUNT + RANDOM_INPUTS_64_COUNT)
+
+
+int32_t main(void)
+{
+ char *instruction_name = "MUL";
+ int32_t ret;
+ uint32_t i, j;
+ struct timeval start, end;
+ double elapsed_time;
+
+ uint64_t b64_result[TEST_COUNT_TOTAL];
+ uint64_t b64_expect[TEST_COUNT_TOTAL] = {
+ 0x0000000000000001ULL, /* 0 */
+ 0x0000000000000000ULL,
+ 0x0000000055555556ULL,
+ 0xffffffffaaaaaaabULL,
+ 0x0000000033333334ULL,
+ 0xffffffffcccccccdULL,
+ 0x0000000071c71c72ULL,
+ 0xffffffff8e38e38fULL,
+ 0x0000000000000000ULL, /* 8 */
+ 0x0000000000000000ULL,
+ 0x0000000000000000ULL,
+ 0x0000000000000000ULL,
+ 0x0000000000000000ULL,
+ 0x0000000000000000ULL,
+ 0x0000000000000000ULL,
+ 0x0000000000000000ULL,
+ 0x0000000055555556ULL, /* 16 */
+ 0x0000000000000000ULL,
+ 0xffffffffe38e38e4ULL,
+ 0x0000000071c71c72ULL,
+ 0x0000000077777778ULL,
+ 0xffffffffdddddddeULL,
+ 0xffffffffa12f684cULL,
+ 0xffffffffb425ed0aULL,
+ 0xffffffffaaaaaaabULL, /* 24 */
+ 0x0000000000000000ULL,
+ 0x0000000071c71c72ULL,
+ 0x0000000038e38e39ULL,
+ 0xffffffffbbbbbbbcULL,
+ 0xffffffffeeeeeeefULL,
+ 0xffffffffd097b426ULL,
+ 0xffffffffda12f685ULL,
+ 0x0000000033333334ULL, /* 32 */
+ 0x0000000000000000ULL,
+ 0x0000000077777778ULL,
+ 0xffffffffbbbbbbbcULL,
+ 0x0000000028f5c290ULL,
+ 0x000000000a3d70a4ULL,
+ 0x0000000027d27d28ULL,
+ 0x000000000b60b60cULL,
+ 0xffffffffcccccccdULL, /* 40 */
+ 0x0000000000000000ULL,
+ 0xffffffffdddddddeULL,
+ 0xffffffffeeeeeeefULL,
+ 0x000000000a3d70a4ULL,
+ 0xffffffffc28f5c29ULL,
+ 0x0000000049f49f4aULL,
+ 0xffffffff82d82d83ULL,
+ 0x0000000071c71c72ULL, /* 48 */
+ 0x0000000000000000ULL,
+ 0xffffffffa12f684cULL,
+ 0xffffffffd097b426ULL,
+ 0x0000000027d27d28ULL,
+ 0x0000000049f49f4aULL,
+ 0xffffffffe06522c4ULL,
+ 0xffffffff9161f9aeULL,
+ 0xffffffff8e38e38fULL, /* 56 */
+ 0x0000000000000000ULL,
+ 0xffffffffb425ed0aULL,
+ 0xffffffffda12f685ULL,
+ 0x000000000b60b60cULL,
+ 0xffffffff82d82d83ULL,
+ 0xffffffff9161f9aeULL,
+ 0xfffffffffcd6e9e1ULL,
+ 0x0000000061639000ULL, /* 64 */
+ 0xffffffffe7176a00ULL,
+ 0xffffffffc4346000ULL,
+ 0xffffffffee787980ULL,
+ 0xffffffffe7176a00ULL,
+ 0xfffffffffded7040ULL,
+ 0xffffffffbe6cdc00ULL,
+ 0x000000002143b470ULL,
+ 0xffffffffc4346000ULL, /* 72 */
+ 0xffffffffbe6cdc00ULL,
+ 0xffffffffe5044000ULL,
+ 0xffffffff89e38100ULL,
+ 0xffffffffee787980ULL,
+ 0x000000002143b470ULL,
+ 0xffffffff89e38100ULL,
+ 0xffffffffb1e9cfc4ULL,
+ };
+
+ gettimeofday(&start, NULL);
+
+ for (i = 0; i < PATTERN_INPUTS_64_SHORT_COUNT; i++) {
+ for (j = 0; j < PATTERN_INPUTS_64_SHORT_COUNT; j++) {
+ do_mips64r6_MUL(b64_pattern + i, b64_pattern + j,
+ b64_result + (PATTERN_INPUTS_64_SHORT_COUNT * i + j));
+ }
+ }
+
+ for (i = 0; i < RANDOM_INPUTS_64_SHORT_COUNT; i++) {
+ for (j = 0; j < RANDOM_INPUTS_64_SHORT_COUNT; j++) {
+ do_mips64r6_MUL(b64_random + i, b64_random + j,
+ b64_result + (((PATTERN_INPUTS_64_SHORT_COUNT) *
+ (PATTERN_INPUTS_64_SHORT_COUNT)) +
+ RANDOM_INPUTS_64_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_64(instruction_name, TEST_COUNT_TOTAL, elapsed_time,
+ b64_result, b64_expect);
+
+ return ret;
+}
diff --git a/tests/tcg/mips/user/isa/mips64r6/int-multiply/test_mips64r6_mulu.c b/tests/tcg/mips/user/isa/mips64r6/int-multiply/test_mips64r6_mulu.c
new file mode 100644
index 0000000..65d5803
--- /dev/null
+++ b/tests/tcg/mips/user/isa/mips64r6/int-multiply/test_mips64r6_mulu.c
@@ -0,0 +1,151 @@
+/*
+ * Test program for MIPS64R6 instruction MULU
+ *
+ * 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_mips64r6.h"
+#include "../../../../include/test_inputs_64.h"
+#include "../../../../include/test_utils_64.h"
+
+#define TEST_COUNT_TOTAL (PATTERN_INPUTS_64_COUNT + RANDOM_INPUTS_64_COUNT)
+
+
+int32_t main(void)
+{
+ char *instruction_name = "MULU";
+ int32_t ret;
+ uint32_t i, j;
+ struct timeval start, end;
+ double elapsed_time;
+
+ uint64_t b64_result[TEST_COUNT_TOTAL];
+ uint64_t b64_expect[TEST_COUNT_TOTAL] = {
+ 0x0000000000000001ULL, /* 0 */
+ 0x0000000000000000ULL,
+ 0x0000000055555556ULL,
+ 0xffffffffaaaaaaabULL,
+ 0x0000000033333334ULL,
+ 0xffffffffcccccccdULL,
+ 0x0000000071c71c72ULL,
+ 0xffffffff8e38e38fULL,
+ 0x0000000000000000ULL, /* 8 */
+ 0x0000000000000000ULL,
+ 0x0000000000000000ULL,
+ 0x0000000000000000ULL,
+ 0x0000000000000000ULL,
+ 0x0000000000000000ULL,
+ 0x0000000000000000ULL,
+ 0x0000000000000000ULL,
+ 0x0000000055555556ULL, /* 16 */
+ 0x0000000000000000ULL,
+ 0xffffffffe38e38e4ULL,
+ 0x0000000071c71c72ULL,
+ 0x0000000077777778ULL,
+ 0xffffffffdddddddeULL,
+ 0xffffffffa12f684cULL,
+ 0xffffffffb425ed0aULL,
+ 0xffffffffaaaaaaabULL, /* 24 */
+ 0x0000000000000000ULL,
+ 0x0000000071c71c72ULL,
+ 0x0000000038e38e39ULL,
+ 0xffffffffbbbbbbbcULL,
+ 0xffffffffeeeeeeefULL,
+ 0xffffffffd097b426ULL,
+ 0xffffffffda12f685ULL,
+ 0x0000000033333334ULL, /* 32 */
+ 0x0000000000000000ULL,
+ 0x0000000077777778ULL,
+ 0xffffffffbbbbbbbcULL,
+ 0x0000000028f5c290ULL,
+ 0x000000000a3d70a4ULL,
+ 0x0000000027d27d28ULL,
+ 0x000000000b60b60cULL,
+ 0xffffffffcccccccdULL, /* 40 */
+ 0x0000000000000000ULL,
+ 0xffffffffdddddddeULL,
+ 0xffffffffeeeeeeefULL,
+ 0x000000000a3d70a4ULL,
+ 0xffffffffc28f5c29ULL,
+ 0x0000000049f49f4aULL,
+ 0xffffffff82d82d83ULL,
+ 0x0000000071c71c72ULL, /* 48 */
+ 0x0000000000000000ULL,
+ 0xffffffffa12f684cULL,
+ 0xffffffffd097b426ULL,
+ 0x0000000027d27d28ULL,
+ 0x0000000049f49f4aULL,
+ 0xffffffffe06522c4ULL,
+ 0xffffffff9161f9aeULL,
+ 0xffffffff8e38e38fULL, /* 56 */
+ 0x0000000000000000ULL,
+ 0xffffffffb425ed0aULL,
+ 0xffffffffda12f685ULL,
+ 0x000000000b60b60cULL,
+ 0xffffffff82d82d83ULL,
+ 0xffffffff9161f9aeULL,
+ 0xfffffffffcd6e9e1ULL,
+ 0x0000000061639000ULL, /* 64 */
+ 0xffffffffe7176a00ULL,
+ 0xffffffffc4346000ULL,
+ 0xffffffffee787980ULL,
+ 0xffffffffe7176a00ULL,
+ 0xfffffffffded7040ULL,
+ 0xffffffffbe6cdc00ULL,
+ 0x000000002143b470ULL,
+ 0xffffffffc4346000ULL, /* 72 */
+ 0xffffffffbe6cdc00ULL,
+ 0xffffffffe5044000ULL,
+ 0xffffffff89e38100ULL,
+ 0xffffffffee787980ULL,
+ 0x000000002143b470ULL,
+ 0xffffffff89e38100ULL,
+ 0xffffffffb1e9cfc4ULL,
+ };
+
+ gettimeofday(&start, NULL);
+
+ for (i = 0; i < PATTERN_INPUTS_64_SHORT_COUNT; i++) {
+ for (j = 0; j < PATTERN_INPUTS_64_SHORT_COUNT; j++) {
+ do_mips64r6_MULU(b64_pattern + i, b64_pattern + j,
+ b64_result + (PATTERN_INPUTS_64_SHORT_COUNT * i + j));
+ }
+ }
+
+ for (i = 0; i < RANDOM_INPUTS_64_SHORT_COUNT; i++) {
+ for (j = 0; j < RANDOM_INPUTS_64_SHORT_COUNT; j++) {
+ do_mips64r6_MULU(b64_random + i, b64_random + j,
+ b64_result + (((PATTERN_INPUTS_64_SHORT_COUNT) *
+ (PATTERN_INPUTS_64_SHORT_COUNT)) +
+ RANDOM_INPUTS_64_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_64(instruction_name, TEST_COUNT_TOTAL, elapsed_time,
+ b64_result, b64_expect);
+
+ return ret;
+}
diff --git a/tests/tcg/mips/user/isa/mips64r6/logic/test_mips64r6_and.c b/tests/tcg/mips/user/isa/mips64r6/logic/test_mips64r6_and.c
new file mode 100644
index 0000000..2039dd9
--- /dev/null
+++ b/tests/tcg/mips/user/isa/mips64r6/logic/test_mips64r6_and.c
@@ -0,0 +1,151 @@
+/*
+ * Test program for MIPS64R6 instruction AND
+ *
+ * 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_mips64r6.h"
+#include "../../../../include/test_inputs_64.h"
+#include "../../../../include/test_utils_64.h"
+
+#define TEST_COUNT_TOTAL (PATTERN_INPUTS_64_COUNT + RANDOM_INPUTS_64_COUNT)
+
+
+int32_t main(void)
+{
+ char *instruction_name = "AND";
+ int32_t ret;
+ uint32_t i, j;
+ struct timeval start, end;
+ double elapsed_time;
+
+ uint64_t b64_result[TEST_COUNT_TOTAL];
+ uint64_t b64_expect[TEST_COUNT_TOTAL] = {
+ 0x8000000000000000ULL, /* 0 */
+ 0xffffffffffffffffULL,
+ 0xfffffc0000000000ULL,
+ 0xffffffffffe00000ULL,
+ 0xfffffffffffff000ULL,
+ 0xfff8000000000000ULL,
+ 0xffffffffffffc000ULL,
+ 0xfffe000000000000ULL,
+ 0x0000000000000000ULL, /* 8 */
+ 0x0000000000000000ULL,
+ 0x0000000000000000ULL,
+ 0x0000000000000000ULL,
+ 0x0000000000000000ULL,
+ 0x0000000000000000ULL,
+ 0x0000000000000000ULL,
+ 0x0000000000000000ULL,
+ 0x0000000000000000ULL, /* 16 */
+ 0xaaaaaaaaaaaaaaaaULL,
+ 0xaaaaa80000000000ULL,
+ 0x5555555555400000ULL,
+ 0xaaaaaaaaaaaaa000ULL,
+ 0x5550000000000000ULL,
+ 0xaaaaaaaaaaaa8000ULL,
+ 0x5554000000000000ULL,
+ 0x8000000000000000ULL, /* 24 */
+ 0x5555555555555555ULL,
+ 0x5555540000000000ULL,
+ 0xaaaaaaaaaaa00000ULL,
+ 0x5555555555555000ULL,
+ 0xaaa8000000000000ULL,
+ 0x5555555555554000ULL,
+ 0xaaaa000000000000ULL,
+ 0x0000000000000000ULL, /* 32 */
+ 0xccccccccccccccccULL,
+ 0x3333300000000000ULL,
+ 0x9999999999800000ULL,
+ 0xccccccccccccc000ULL,
+ 0x6660000000000000ULL,
+ 0x3333333333330000ULL,
+ 0x9998000000000000ULL,
+ 0x8000000000000000ULL, /* 40 */
+ 0x3333333333333333ULL,
+ 0xcccccc0000000000ULL,
+ 0x6666666666600000ULL,
+ 0x3333333333333000ULL,
+ 0x9998000000000000ULL,
+ 0xccccccccccccc000ULL,
+ 0x6666000000000000ULL,
+ 0x0000000000000000ULL, /* 48 */
+ 0xe38e38e38e38e38eULL,
+ 0xe38e380000000000ULL,
+ 0x1c71c71c71c00000ULL,
+ 0xe38e38e38e38e000ULL,
+ 0x1c70000000000000ULL,
+ 0x8e38e38e38e38000ULL,
+ 0xc71c000000000000ULL,
+ 0x8000000000000000ULL, /* 56 */
+ 0x1c71c71c71c71c71ULL,
+ 0x1c71c40000000000ULL,
+ 0xe38e38e38e200000ULL,
+ 0x1c71c71c71c71000ULL,
+ 0xe388000000000000ULL,
+ 0x71c71c71c71c4000ULL,
+ 0x38e2000000000000ULL,
+ 0x886ae6cc28625540ULL, /* 64 */
+ 0x6ae6cc2862554000ULL,
+ 0x886ae6cc28625540ULL,
+ 0xb9b30a1895500000ULL,
+ 0xfbbe00634d93c708ULL,
+ 0xbe00634d93c70800ULL,
+ 0xfbbe00634d93c708ULL,
+ 0x8018d364f1c20000ULL,
+ 0xac5aaeaab9cf8b80ULL, /* 72 */
+ 0x5aaeaab9cf8b8000ULL,
+ 0xac5aaeaab9cf8b80ULL,
+ 0xabaaae73e2e00000ULL,
+ 0x704f164d5e31e24eULL,
+ 0x4f164d5e31e24e00ULL,
+ 0x704f164d5e31e24eULL,
+ 0xc593578c78938000ULL,
+ };
+
+ gettimeofday(&start, NULL);
+
+ for (i = 0; i < PATTERN_INPUTS_64_SHORT_COUNT; i++) {
+ for (j = 0; j < PATTERN_INPUTS_64_SHORT_COUNT; j++) {
+ do_mips64r6_AND(b64_pattern + i, b64_pattern + j,
+ b64_result + (PATTERN_INPUTS_64_SHORT_COUNT * i + j));
+ }
+ }
+
+ for (i = 0; i < RANDOM_INPUTS_64_SHORT_COUNT; i++) {
+ for (j = 0; j < RANDOM_INPUTS_64_SHORT_COUNT; j++) {
+ do_mips64r6_AND(b64_random + i, b64_random + j,
+ b64_result + (((PATTERN_INPUTS_64_SHORT_COUNT) *
+ (PATTERN_INPUTS_64_SHORT_COUNT)) +
+ RANDOM_INPUTS_64_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_64(instruction_name, TEST_COUNT_TOTAL, elapsed_time,
+ b64_result, b64_expect);
+
+ return ret;
+}
diff --git a/tests/tcg/mips/user/isa/mips64r6/logic/test_mips64r6_nor.c b/tests/tcg/mips/user/isa/mips64r6/logic/test_mips64r6_nor.c
new file mode 100644
index 0000000..f22393b
--- /dev/null
+++ b/tests/tcg/mips/user/isa/mips64r6/logic/test_mips64r6_nor.c
@@ -0,0 +1,151 @@
+/*
+ * Test program for MIPS64R6 instruction NOR
+ *
+ * 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_mips64r6.h"
+#include "../../../../include/test_inputs_64.h"
+#include "../../../../include/test_utils_64.h"
+
+#define TEST_COUNT_TOTAL (PATTERN_INPUTS_64_COUNT + RANDOM_INPUTS_64_COUNT)
+
+
+int32_t main(void)
+{
+ char *instruction_name = "NOR";
+ int32_t ret;
+ uint32_t i, j;
+ struct timeval start, end;
+ double elapsed_time;
+
+ uint64_t b64_result[TEST_COUNT_TOTAL];
+ uint64_t b64_expect[TEST_COUNT_TOTAL] = {
+ 0x8000000000000000ULL, /* 0 */
+ 0xffffffffffffffffULL,
+ 0xfffffc0000000000ULL,
+ 0xffffffffffe00000ULL,
+ 0xfffffffffffff000ULL,
+ 0xfff8000000000000ULL,
+ 0xffffffffffffc000ULL,
+ 0xfffe000000000000ULL,
+ 0x0000000000000000ULL, /* 8 */
+ 0x0000000000000000ULL,
+ 0x0000000000000000ULL,
+ 0x0000000000000000ULL,
+ 0x0000000000000000ULL,
+ 0x0000000000000000ULL,
+ 0x0000000000000000ULL,
+ 0x0000000000000000ULL,
+ 0x0000000000000000ULL, /* 16 */
+ 0xaaaaaaaaaaaaaaaaULL,
+ 0xaaaaa80000000000ULL,
+ 0x5555555555400000ULL,
+ 0xaaaaaaaaaaaaa000ULL,
+ 0x5550000000000000ULL,
+ 0xaaaaaaaaaaaa8000ULL,
+ 0x5554000000000000ULL,
+ 0x8000000000000000ULL, /* 24 */
+ 0x5555555555555555ULL,
+ 0x5555540000000000ULL,
+ 0xaaaaaaaaaaa00000ULL,
+ 0x5555555555555000ULL,
+ 0xaaa8000000000000ULL,
+ 0x5555555555554000ULL,
+ 0xaaaa000000000000ULL,
+ 0x0000000000000000ULL, /* 32 */
+ 0xccccccccccccccccULL,
+ 0x3333300000000000ULL,
+ 0x9999999999800000ULL,
+ 0xccccccccccccc000ULL,
+ 0x6660000000000000ULL,
+ 0x3333333333330000ULL,
+ 0x9998000000000000ULL,
+ 0x8000000000000000ULL, /* 40 */
+ 0x3333333333333333ULL,
+ 0xcccccc0000000000ULL,
+ 0x6666666666600000ULL,
+ 0x3333333333333000ULL,
+ 0x9998000000000000ULL,
+ 0xccccccccccccc000ULL,
+ 0x6666000000000000ULL,
+ 0x0000000000000000ULL, /* 48 */
+ 0xe38e38e38e38e38eULL,
+ 0xe38e380000000000ULL,
+ 0x1c71c71c71c00000ULL,
+ 0xe38e38e38e38e000ULL,
+ 0x1c70000000000000ULL,
+ 0x8e38e38e38e38000ULL,
+ 0xc71c000000000000ULL,
+ 0x8000000000000000ULL, /* 56 */
+ 0x1c71c71c71c71c71ULL,
+ 0x1c71c40000000000ULL,
+ 0xe38e38e38e200000ULL,
+ 0x1c71c71c71c71000ULL,
+ 0xe388000000000000ULL,
+ 0x71c71c71c71c4000ULL,
+ 0x38e2000000000000ULL,
+ 0x886ae6cc28625540ULL, /* 64 */
+ 0x6ae6cc2862554000ULL,
+ 0x886ae6cc28625540ULL,
+ 0xb9b30a1895500000ULL,
+ 0xfbbe00634d93c708ULL,
+ 0xbe00634d93c70800ULL,
+ 0xfbbe00634d93c708ULL,
+ 0x8018d364f1c20000ULL,
+ 0xac5aaeaab9cf8b80ULL, /* 72 */
+ 0x5aaeaab9cf8b8000ULL,
+ 0xac5aaeaab9cf8b80ULL,
+ 0xabaaae73e2e00000ULL,
+ 0x704f164d5e31e24eULL,
+ 0x4f164d5e31e24e00ULL,
+ 0x704f164d5e31e24eULL,
+ 0xc593578c78938000ULL,
+ };
+
+ gettimeofday(&start, NULL);
+
+ for (i = 0; i < PATTERN_INPUTS_64_SHORT_COUNT; i++) {
+ for (j = 0; j < PATTERN_INPUTS_64_SHORT_COUNT; j++) {
+ do_mips64r6_NOR(b64_pattern + i, b64_pattern + j,
+ b64_result + (PATTERN_INPUTS_64_SHORT_COUNT * i + j));
+ }
+ }
+
+ for (i = 0; i < RANDOM_INPUTS_64_SHORT_COUNT; i++) {
+ for (j = 0; j < RANDOM_INPUTS_64_SHORT_COUNT; j++) {
+ do_mips64r6_NOR(b64_random + i, b64_random + j,
+ b64_result + (((PATTERN_INPUTS_64_SHORT_COUNT) *
+ (PATTERN_INPUTS_64_SHORT_COUNT)) +
+ RANDOM_INPUTS_64_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_64(instruction_name, TEST_COUNT_TOTAL, elapsed_time,
+ b64_result, b64_expect);
+
+ return ret;
+}
diff --git a/tests/tcg/mips/user/isa/mips64r6/logic/test_mips64r6_or.c b/tests/tcg/mips/user/isa/mips64r6/logic/test_mips64r6_or.c
new file mode 100644
index 0000000..ed8bac1
--- /dev/null
+++ b/tests/tcg/mips/user/isa/mips64r6/logic/test_mips64r6_or.c
@@ -0,0 +1,151 @@
+/*
+ * Test program for MIPS64R6 instruction OR
+ *
+ * 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_mips64r6.h"
+#include "../../../../include/test_inputs_64.h"
+#include "../../../../include/test_utils_64.h"
+
+#define TEST_COUNT_TOTAL (PATTERN_INPUTS_64_COUNT + RANDOM_INPUTS_64_COUNT)
+
+
+int32_t main(void)
+{
+ char *instruction_name = "OR";
+ int32_t ret;
+ uint32_t i, j;
+ struct timeval start, end;
+ double elapsed_time;
+
+ uint64_t b64_result[TEST_COUNT_TOTAL];
+ uint64_t b64_expect[TEST_COUNT_TOTAL] = {
+ 0x8000000000000000ULL, /* 0 */
+ 0xffffffffffffffffULL,
+ 0xfffffc0000000000ULL,
+ 0xffffffffffe00000ULL,
+ 0xfffffffffffff000ULL,
+ 0xfff8000000000000ULL,
+ 0xffffffffffffc000ULL,
+ 0xfffe000000000000ULL,
+ 0x0000000000000000ULL, /* 8 */
+ 0x0000000000000000ULL,
+ 0x0000000000000000ULL,
+ 0x0000000000000000ULL,
+ 0x0000000000000000ULL,
+ 0x0000000000000000ULL,
+ 0x0000000000000000ULL,
+ 0x0000000000000000ULL,
+ 0x0000000000000000ULL, /* 16 */
+ 0xaaaaaaaaaaaaaaaaULL,
+ 0xaaaaa80000000000ULL,
+ 0x5555555555400000ULL,
+ 0xaaaaaaaaaaaaa000ULL,
+ 0x5550000000000000ULL,
+ 0xaaaaaaaaaaaa8000ULL,
+ 0x5554000000000000ULL,
+ 0x8000000000000000ULL, /* 24 */
+ 0x5555555555555555ULL,
+ 0x5555540000000000ULL,
+ 0xaaaaaaaaaaa00000ULL,
+ 0x5555555555555000ULL,
+ 0xaaa8000000000000ULL,
+ 0x5555555555554000ULL,
+ 0xaaaa000000000000ULL,
+ 0x0000000000000000ULL, /* 32 */
+ 0xccccccccccccccccULL,
+ 0x3333300000000000ULL,
+ 0x9999999999800000ULL,
+ 0xccccccccccccc000ULL,
+ 0x6660000000000000ULL,
+ 0x3333333333330000ULL,
+ 0x9998000000000000ULL,
+ 0x8000000000000000ULL, /* 40 */
+ 0x3333333333333333ULL,
+ 0xcccccc0000000000ULL,
+ 0x6666666666600000ULL,
+ 0x3333333333333000ULL,
+ 0x9998000000000000ULL,
+ 0xccccccccccccc000ULL,
+ 0x6666000000000000ULL,
+ 0x0000000000000000ULL, /* 48 */
+ 0xe38e38e38e38e38eULL,
+ 0xe38e380000000000ULL,
+ 0x1c71c71c71c00000ULL,
+ 0xe38e38e38e38e000ULL,
+ 0x1c70000000000000ULL,
+ 0x8e38e38e38e38000ULL,
+ 0xc71c000000000000ULL,
+ 0x8000000000000000ULL, /* 56 */
+ 0x1c71c71c71c71c71ULL,
+ 0x1c71c40000000000ULL,
+ 0xe38e38e38e200000ULL,
+ 0x1c71c71c71c71000ULL,
+ 0xe388000000000000ULL,
+ 0x71c71c71c71c4000ULL,
+ 0x38e2000000000000ULL,
+ 0x886ae6cc28625540ULL, /* 64 */
+ 0x6ae6cc2862554000ULL,
+ 0x886ae6cc28625540ULL,
+ 0xb9b30a1895500000ULL,
+ 0xfbbe00634d93c708ULL,
+ 0xbe00634d93c70800ULL,
+ 0xfbbe00634d93c708ULL,
+ 0x8018d364f1c20000ULL,
+ 0xac5aaeaab9cf8b80ULL, /* 72 */
+ 0x5aaeaab9cf8b8000ULL,
+ 0xac5aaeaab9cf8b80ULL,
+ 0xabaaae73e2e00000ULL,
+ 0x704f164d5e31e24eULL,
+ 0x4f164d5e31e24e00ULL,
+ 0x704f164d5e31e24eULL,
+ 0xc593578c78938000ULL,
+ };
+
+ gettimeofday(&start, NULL);
+
+ for (i = 0; i < PATTERN_INPUTS_64_SHORT_COUNT; i++) {
+ for (j = 0; j < PATTERN_INPUTS_64_SHORT_COUNT; j++) {
+ do_mips64r6_OR(b64_pattern + i, b64_pattern + j,
+ b64_result + (PATTERN_INPUTS_64_SHORT_COUNT * i + j));
+ }
+ }
+
+ for (i = 0; i < RANDOM_INPUTS_64_SHORT_COUNT; i++) {
+ for (j = 0; j < RANDOM_INPUTS_64_SHORT_COUNT; j++) {
+ do_mips64r6_OR(b64_random + i, b64_random + j,
+ b64_result + (((PATTERN_INPUTS_64_SHORT_COUNT) *
+ (PATTERN_INPUTS_64_SHORT_COUNT)) +
+ RANDOM_INPUTS_64_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_64(instruction_name, TEST_COUNT_TOTAL, elapsed_time,
+ b64_result, b64_expect);
+
+ return ret;
+}
diff --git a/tests/tcg/mips/user/isa/mips64r6/logic/test_mips64r6_xor.c b/tests/tcg/mips/user/isa/mips64r6/logic/test_mips64r6_xor.c
new file mode 100644
index 0000000..a8ba2b4
--- /dev/null
+++ b/tests/tcg/mips/user/isa/mips64r6/logic/test_mips64r6_xor.c
@@ -0,0 +1,151 @@
+/*
+ * Test program for MIPS64R6 instruction XOR
+ *
+ * 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_mips64r6.h"
+#include "../../../../include/test_inputs_64.h"
+#include "../../../../include/test_utils_64.h"
+
+#define TEST_COUNT_TOTAL (PATTERN_INPUTS_64_COUNT + RANDOM_INPUTS_64_COUNT)
+
+
+int32_t main(void)
+{
+ char *instruction_name = "XOR";
+ int32_t ret;
+ uint32_t i, j;
+ struct timeval start, end;
+ double elapsed_time;
+
+ uint64_t b64_result[TEST_COUNT_TOTAL];
+ uint64_t b64_expect[TEST_COUNT_TOTAL] = {
+ 0x8000000000000000ULL, /* 0 */
+ 0xffffffffffffffffULL,
+ 0xfffffc0000000000ULL,
+ 0xffffffffffe00000ULL,
+ 0xfffffffffffff000ULL,
+ 0xfff8000000000000ULL,
+ 0xffffffffffffc000ULL,
+ 0xfffe000000000000ULL,
+ 0x0000000000000000ULL, /* 8 */
+ 0x0000000000000000ULL,
+ 0x0000000000000000ULL,
+ 0x0000000000000000ULL,
+ 0x0000000000000000ULL,
+ 0x0000000000000000ULL,
+ 0x0000000000000000ULL,
+ 0x0000000000000000ULL,
+ 0x0000000000000000ULL, /* 16 */
+ 0xaaaaaaaaaaaaaaaaULL,
+ 0xaaaaa80000000000ULL,
+ 0x5555555555400000ULL,
+ 0xaaaaaaaaaaaaa000ULL,
+ 0x5550000000000000ULL,
+ 0xaaaaaaaaaaaa8000ULL,
+ 0x5554000000000000ULL,
+ 0x8000000000000000ULL, /* 24 */
+ 0x5555555555555555ULL,
+ 0x5555540000000000ULL,
+ 0xaaaaaaaaaaa00000ULL,
+ 0x5555555555555000ULL,
+ 0xaaa8000000000000ULL,
+ 0x5555555555554000ULL,
+ 0xaaaa000000000000ULL,
+ 0x0000000000000000ULL, /* 32 */
+ 0xccccccccccccccccULL,
+ 0x3333300000000000ULL,
+ 0x9999999999800000ULL,
+ 0xccccccccccccc000ULL,
+ 0x6660000000000000ULL,
+ 0x3333333333330000ULL,
+ 0x9998000000000000ULL,
+ 0x8000000000000000ULL, /* 40 */
+ 0x3333333333333333ULL,
+ 0xcccccc0000000000ULL,
+ 0x6666666666600000ULL,
+ 0x3333333333333000ULL,
+ 0x9998000000000000ULL,
+ 0xccccccccccccc000ULL,
+ 0x6666000000000000ULL,
+ 0x0000000000000000ULL, /* 48 */
+ 0xe38e38e38e38e38eULL,
+ 0xe38e380000000000ULL,
+ 0x1c71c71c71c00000ULL,
+ 0xe38e38e38e38e000ULL,
+ 0x1c70000000000000ULL,
+ 0x8e38e38e38e38000ULL,
+ 0xc71c000000000000ULL,
+ 0x8000000000000000ULL, /* 56 */
+ 0x1c71c71c71c71c71ULL,
+ 0x1c71c40000000000ULL,
+ 0xe38e38e38e200000ULL,
+ 0x1c71c71c71c71000ULL,
+ 0xe388000000000000ULL,
+ 0x71c71c71c71c4000ULL,
+ 0x38e2000000000000ULL,
+ 0x886ae6cc28625540ULL, /* 64 */
+ 0x6ae6cc2862554000ULL,
+ 0x886ae6cc28625540ULL,
+ 0xb9b30a1895500000ULL,
+ 0xfbbe00634d93c708ULL,
+ 0xbe00634d93c70800ULL,
+ 0xfbbe00634d93c708ULL,
+ 0x8018d364f1c20000ULL,
+ 0xac5aaeaab9cf8b80ULL, /* 72 */
+ 0x5aaeaab9cf8b8000ULL,
+ 0xac5aaeaab9cf8b80ULL,
+ 0xabaaae73e2e00000ULL,
+ 0x704f164d5e31e24eULL,
+ 0x4f164d5e31e24e00ULL,
+ 0x704f164d5e31e24eULL,
+ 0xc593578c78938000ULL,
+ };
+
+ gettimeofday(&start, NULL);
+
+ for (i = 0; i < PATTERN_INPUTS_64_SHORT_COUNT; i++) {
+ for (j = 0; j < PATTERN_INPUTS_64_SHORT_COUNT; j++) {
+ do_mips64r6_XOR(b64_pattern + i, b64_pattern + j,
+ b64_result + (PATTERN_INPUTS_64_SHORT_COUNT * i + j));
+ }
+ }
+
+ for (i = 0; i < RANDOM_INPUTS_64_SHORT_COUNT; i++) {
+ for (j = 0; j < RANDOM_INPUTS_64_SHORT_COUNT; j++) {
+ do_mips64r6_XOR(b64_random + i, b64_random + j,
+ b64_result + (((PATTERN_INPUTS_64_SHORT_COUNT) *
+ (PATTERN_INPUTS_64_SHORT_COUNT)) +
+ RANDOM_INPUTS_64_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_64(instruction_name, TEST_COUNT_TOTAL, elapsed_time,
+ b64_result, b64_expect);
+
+ return ret;
+}
diff --git a/tests/tcg/mips/user/isa/mips64r6/shift/test_mips64r6_dsllv.c b/tests/tcg/mips/user/isa/mips64r6/shift/test_mips64r6_dsllv.c
new file mode 100644
index 0000000..b3eb86e
--- /dev/null
+++ b/tests/tcg/mips/user/isa/mips64r6/shift/test_mips64r6_dsllv.c
@@ -0,0 +1,151 @@
+/*
+ * Test program for MIPS64R6 instruction DSLLV
+ *
+ * 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_mips64r6.h"
+#include "../../../../include/test_inputs_64.h"
+#include "../../../../include/test_utils_64.h"
+
+#define TEST_COUNT_TOTAL (PATTERN_INPUTS_64_COUNT + RANDOM_INPUTS_64_COUNT)
+
+
+int32_t main(void)
+{
+ char *instruction_name = "DSLLV";
+ int32_t ret;
+ uint32_t i, j;
+ struct timeval start, end;
+ double elapsed_time;
+
+ uint64_t b64_result[TEST_COUNT_TOTAL];
+ uint64_t b64_expect[TEST_COUNT_TOTAL] = {
+ 0x8000000000000000ULL, /* 0 */
+ 0xffffffffffffffffULL,
+ 0xfffffc0000000000ULL,
+ 0xffffffffffe00000ULL,
+ 0xfffffffffffff000ULL,
+ 0xfff8000000000000ULL,
+ 0xffffffffffffc000ULL,
+ 0xfffe000000000000ULL,
+ 0x0000000000000000ULL, /* 8 */
+ 0x0000000000000000ULL,
+ 0x0000000000000000ULL,
+ 0x0000000000000000ULL,
+ 0x0000000000000000ULL,
+ 0x0000000000000000ULL,
+ 0x0000000000000000ULL,
+ 0x0000000000000000ULL,
+ 0x0000000000000000ULL, /* 16 */
+ 0xaaaaaaaaaaaaaaaaULL,
+ 0xaaaaa80000000000ULL,
+ 0x5555555555400000ULL,
+ 0xaaaaaaaaaaaaa000ULL,
+ 0x5550000000000000ULL,
+ 0xaaaaaaaaaaaa8000ULL,
+ 0x5554000000000000ULL,
+ 0x8000000000000000ULL, /* 24 */
+ 0x5555555555555555ULL,
+ 0x5555540000000000ULL,
+ 0xaaaaaaaaaaa00000ULL,
+ 0x5555555555555000ULL,
+ 0xaaa8000000000000ULL,
+ 0x5555555555554000ULL,
+ 0xaaaa000000000000ULL,
+ 0x0000000000000000ULL, /* 32 */
+ 0xccccccccccccccccULL,
+ 0x3333300000000000ULL,
+ 0x9999999999800000ULL,
+ 0xccccccccccccc000ULL,
+ 0x6660000000000000ULL,
+ 0x3333333333330000ULL,
+ 0x9998000000000000ULL,
+ 0x8000000000000000ULL, /* 40 */
+ 0x3333333333333333ULL,
+ 0xcccccc0000000000ULL,
+ 0x6666666666600000ULL,
+ 0x3333333333333000ULL,
+ 0x9998000000000000ULL,
+ 0xccccccccccccc000ULL,
+ 0x6666000000000000ULL,
+ 0x0000000000000000ULL, /* 48 */
+ 0xe38e38e38e38e38eULL,
+ 0xe38e380000000000ULL,
+ 0x1c71c71c71c00000ULL,
+ 0xe38e38e38e38e000ULL,
+ 0x1c70000000000000ULL,
+ 0x8e38e38e38e38000ULL,
+ 0xc71c000000000000ULL,
+ 0x8000000000000000ULL, /* 56 */
+ 0x1c71c71c71c71c71ULL,
+ 0x1c71c40000000000ULL,
+ 0xe38e38e38e200000ULL,
+ 0x1c71c71c71c71000ULL,
+ 0xe388000000000000ULL,
+ 0x71c71c71c71c4000ULL,
+ 0x38e2000000000000ULL,
+ 0x886ae6cc28625540ULL, /* 64 */
+ 0x6ae6cc2862554000ULL,
+ 0x886ae6cc28625540ULL,
+ 0xb9b30a1895500000ULL,
+ 0xfbbe00634d93c708ULL,
+ 0xbe00634d93c70800ULL,
+ 0xfbbe00634d93c708ULL,
+ 0x8018d364f1c20000ULL,
+ 0xac5aaeaab9cf8b80ULL, /* 72 */
+ 0x5aaeaab9cf8b8000ULL,
+ 0xac5aaeaab9cf8b80ULL,
+ 0xabaaae73e2e00000ULL,
+ 0x704f164d5e31e24eULL,
+ 0x4f164d5e31e24e00ULL,
+ 0x704f164d5e31e24eULL,
+ 0xc593578c78938000ULL,
+ };
+
+ gettimeofday(&start, NULL);
+
+ for (i = 0; i < PATTERN_INPUTS_64_SHORT_COUNT; i++) {
+ for (j = 0; j < PATTERN_INPUTS_64_SHORT_COUNT; j++) {
+ do_mips64r6_DSLLV(b64_pattern + i, b64_pattern + j,
+ b64_result + (PATTERN_INPUTS_64_SHORT_COUNT * i + j));
+ }
+ }
+
+ for (i = 0; i < RANDOM_INPUTS_64_SHORT_COUNT; i++) {
+ for (j = 0; j < RANDOM_INPUTS_64_SHORT_COUNT; j++) {
+ do_mips64r6_DSLLV(b64_random + i, b64_random + j,
+ b64_result + (((PATTERN_INPUTS_64_SHORT_COUNT) *
+ (PATTERN_INPUTS_64_SHORT_COUNT)) +
+ RANDOM_INPUTS_64_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_64(instruction_name, TEST_COUNT_TOTAL, elapsed_time,
+ b64_result, b64_expect);
+
+ return ret;
+}
diff --git a/tests/tcg/mips/user/isa/mips64r6/shift/test_mips64r6_dsrav.c b/tests/tcg/mips/user/isa/mips64r6/shift/test_mips64r6_dsrav.c
new file mode 100644
index 0000000..025e8f8
--- /dev/null
+++ b/tests/tcg/mips/user/isa/mips64r6/shift/test_mips64r6_dsrav.c
@@ -0,0 +1,151 @@
+/*
+ * Test program for MIPS64R6 instruction DSRAV
+ *
+ * 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_mips64r6.h"
+#include "../../../../include/test_inputs_64.h"
+#include "../../../../include/test_utils_64.h"
+
+#define TEST_COUNT_TOTAL (PATTERN_INPUTS_64_COUNT + RANDOM_INPUTS_64_COUNT)
+
+
+int32_t main(void)
+{
+ char *instruction_name = "DSRAV";
+ int32_t ret;
+ uint32_t i, j;
+ struct timeval start, end;
+ double elapsed_time;
+
+ uint64_t b64_result[TEST_COUNT_TOTAL];
+ uint64_t b64_expect[TEST_COUNT_TOTAL] = {
+ 0xffffffffffffffffULL, /* 0 */
+ 0xffffffffffffffffULL,
+ 0xffffffffffffffffULL,
+ 0xffffffffffffffffULL,
+ 0xffffffffffffffffULL,
+ 0xffffffffffffffffULL,
+ 0xffffffffffffffffULL,
+ 0xffffffffffffffffULL,
+ 0x0000000000000000ULL, /* 8 */
+ 0x0000000000000000ULL,
+ 0x0000000000000000ULL,
+ 0x0000000000000000ULL,
+ 0x0000000000000000ULL,
+ 0x0000000000000000ULL,
+ 0x0000000000000000ULL,
+ 0x0000000000000000ULL,
+ 0xffffffffffffffffULL, /* 16 */
+ 0xaaaaaaaaaaaaaaaaULL,
+ 0xffffffffffeaaaaaULL,
+ 0xfffffd5555555555ULL,
+ 0xfffaaaaaaaaaaaaaULL,
+ 0xfffffffffffff555ULL,
+ 0xfffeaaaaaaaaaaaaULL,
+ 0xffffffffffffd555ULL,
+ 0x0000000000000000ULL, /* 24 */
+ 0x5555555555555555ULL,
+ 0x0000000000155555ULL,
+ 0x000002aaaaaaaaaaULL,
+ 0x0005555555555555ULL,
+ 0x0000000000000aaaULL,
+ 0x0001555555555555ULL,
+ 0x0000000000002aaaULL,
+ 0xffffffffffffffffULL, /* 32 */
+ 0xccccccccccccccccULL,
+ 0xfffffffffff33333ULL,
+ 0xfffffe6666666666ULL,
+ 0xfffcccccccccccccULL,
+ 0xfffffffffffff999ULL,
+ 0xffff333333333333ULL,
+ 0xffffffffffffe666ULL,
+ 0x0000000000000000ULL, /* 40 */
+ 0x3333333333333333ULL,
+ 0x00000000000cccccULL,
+ 0x0000019999999999ULL,
+ 0x0003333333333333ULL,
+ 0x0000000000000666ULL,
+ 0x0000ccccccccccccULL,
+ 0x0000000000001999ULL,
+ 0xffffffffffffffffULL, /* 48 */
+ 0xe38e38e38e38e38eULL,
+ 0xfffffffffff8e38eULL,
+ 0xffffff1c71c71c71ULL,
+ 0xfffe38e38e38e38eULL,
+ 0xfffffffffffffc71ULL,
+ 0xffff8e38e38e38e3ULL,
+ 0xfffffffffffff1c7ULL,
+ 0x0000000000000000ULL, /* 56 */
+ 0x1c71c71c71c71c71ULL,
+ 0x0000000000071c71ULL,
+ 0x000000e38e38e38eULL,
+ 0x0001c71c71c71c71ULL,
+ 0x000000000000038eULL,
+ 0x000071c71c71c71cULL,
+ 0x0000000000000e38ULL,
+ 0x886ae6cc28625540ULL, /* 64 */
+ 0xff886ae6cc286255ULL,
+ 0x886ae6cc28625540ULL,
+ 0xfffe21ab9b30a189ULL,
+ 0xfbbe00634d93c708ULL,
+ 0xfffbbe00634d93c7ULL,
+ 0xfbbe00634d93c708ULL,
+ 0xffffeef8018d364fULL,
+ 0xac5aaeaab9cf8b80ULL, /* 72 */
+ 0xffac5aaeaab9cf8bULL,
+ 0xac5aaeaab9cf8b80ULL,
+ 0xfffeb16abaaae73eULL,
+ 0x704f164d5e31e24eULL,
+ 0x00704f164d5e31e2ULL,
+ 0x704f164d5e31e24eULL,
+ 0x0001c13c593578c7ULL,
+ };
+
+ gettimeofday(&start, NULL);
+
+ for (i = 0; i < PATTERN_INPUTS_64_SHORT_COUNT; i++) {
+ for (j = 0; j < PATTERN_INPUTS_64_SHORT_COUNT; j++) {
+ do_mips64r6_DSRAV(b64_pattern + i, b64_pattern + j,
+ b64_result + (PATTERN_INPUTS_64_SHORT_COUNT * i + j));
+ }
+ }
+
+ for (i = 0; i < RANDOM_INPUTS_64_SHORT_COUNT; i++) {
+ for (j = 0; j < RANDOM_INPUTS_64_SHORT_COUNT; j++) {
+ do_mips64r6_DSRAV(b64_random + i, b64_random + j,
+ b64_result + (((PATTERN_INPUTS_64_SHORT_COUNT) *
+ (PATTERN_INPUTS_64_SHORT_COUNT)) +
+ RANDOM_INPUTS_64_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_64(instruction_name, TEST_COUNT_TOTAL, elapsed_time,
+ b64_result, b64_expect);
+
+ return ret;
+}
diff --git a/tests/tcg/mips/user/isa/mips64r6/shift/test_mips64r6_dsrlv.c b/tests/tcg/mips/user/isa/mips64r6/shift/test_mips64r6_dsrlv.c
new file mode 100644
index 0000000..680f8a1
--- /dev/null
+++ b/tests/tcg/mips/user/isa/mips64r6/shift/test_mips64r6_dsrlv.c
@@ -0,0 +1,151 @@
+/*
+ * Test program for MIPS64R6 instruction DSRLV
+ *
+ * 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_mips64r6.h"
+#include "../../../../include/test_inputs_64.h"
+#include "../../../../include/test_utils_64.h"
+
+#define TEST_COUNT_TOTAL (PATTERN_INPUTS_64_COUNT + RANDOM_INPUTS_64_COUNT)
+
+
+int32_t main(void)
+{
+ char *instruction_name = "DSRLV";
+ int32_t ret;
+ uint32_t i, j;
+ struct timeval start, end;
+ double elapsed_time;
+
+ uint64_t b64_result[TEST_COUNT_TOTAL];
+ uint64_t b64_expect[TEST_COUNT_TOTAL] = {
+ 0x0000000000000001ULL, /* 0 */
+ 0xffffffffffffffffULL,
+ 0x00000000003fffffULL,
+ 0x000007ffffffffffULL,
+ 0x000fffffffffffffULL,
+ 0x0000000000001fffULL,
+ 0x0003ffffffffffffULL,
+ 0x0000000000007fffULL,
+ 0x0000000000000000ULL, /* 8 */
+ 0x0000000000000000ULL,
+ 0x0000000000000000ULL,
+ 0x0000000000000000ULL,
+ 0x0000000000000000ULL,
+ 0x0000000000000000ULL,
+ 0x0000000000000000ULL,
+ 0x0000000000000000ULL,
+ 0x0000000000000001ULL, /* 16 */
+ 0xaaaaaaaaaaaaaaaaULL,
+ 0x00000000002aaaaaULL,
+ 0x0000055555555555ULL,
+ 0x000aaaaaaaaaaaaaULL,
+ 0x0000000000001555ULL,
+ 0x0002aaaaaaaaaaaaULL,
+ 0x0000000000005555ULL,
+ 0x0000000000000000ULL, /* 24 */
+ 0x5555555555555555ULL,
+ 0x0000000000155555ULL,
+ 0x000002aaaaaaaaaaULL,
+ 0x0005555555555555ULL,
+ 0x0000000000000aaaULL,
+ 0x0001555555555555ULL,
+ 0x0000000000002aaaULL,
+ 0x0000000000000001ULL, /* 32 */
+ 0xccccccccccccccccULL,
+ 0x0000000000333333ULL,
+ 0x0000066666666666ULL,
+ 0x000cccccccccccccULL,
+ 0x0000000000001999ULL,
+ 0x0003333333333333ULL,
+ 0x0000000000006666ULL,
+ 0x0000000000000000ULL, /* 40 */
+ 0x3333333333333333ULL,
+ 0x00000000000cccccULL,
+ 0x0000019999999999ULL,
+ 0x0003333333333333ULL,
+ 0x0000000000000666ULL,
+ 0x0000ccccccccccccULL,
+ 0x0000000000001999ULL,
+ 0x0000000000000001ULL, /* 48 */
+ 0xe38e38e38e38e38eULL,
+ 0x000000000038e38eULL,
+ 0x0000071c71c71c71ULL,
+ 0x000e38e38e38e38eULL,
+ 0x0000000000001c71ULL,
+ 0x00038e38e38e38e3ULL,
+ 0x00000000000071c7ULL,
+ 0x0000000000000000ULL, /* 56 */
+ 0x1c71c71c71c71c71ULL,
+ 0x0000000000071c71ULL,
+ 0x000000e38e38e38eULL,
+ 0x0001c71c71c71c71ULL,
+ 0x000000000000038eULL,
+ 0x000071c71c71c71cULL,
+ 0x0000000000000e38ULL,
+ 0x886ae6cc28625540ULL, /* 64 */
+ 0x00886ae6cc286255ULL,
+ 0x886ae6cc28625540ULL,
+ 0x000221ab9b30a189ULL,
+ 0xfbbe00634d93c708ULL,
+ 0x00fbbe00634d93c7ULL,
+ 0xfbbe00634d93c708ULL,
+ 0x0003eef8018d364fULL,
+ 0xac5aaeaab9cf8b80ULL, /* 72 */
+ 0x00ac5aaeaab9cf8bULL,
+ 0xac5aaeaab9cf8b80ULL,
+ 0x0002b16abaaae73eULL,
+ 0x704f164d5e31e24eULL,
+ 0x00704f164d5e31e2ULL,
+ 0x704f164d5e31e24eULL,
+ 0x0001c13c593578c7ULL,
+ };
+
+ gettimeofday(&start, NULL);
+
+ for (i = 0; i < PATTERN_INPUTS_64_SHORT_COUNT; i++) {
+ for (j = 0; j < PATTERN_INPUTS_64_SHORT_COUNT; j++) {
+ do_mips64r6_DSRLV(b64_pattern + i, b64_pattern + j,
+ b64_result + (PATTERN_INPUTS_64_SHORT_COUNT * i + j));
+ }
+ }
+
+ for (i = 0; i < RANDOM_INPUTS_64_SHORT_COUNT; i++) {
+ for (j = 0; j < RANDOM_INPUTS_64_SHORT_COUNT; j++) {
+ do_mips64r6_DSRLV(b64_random + i, b64_random + j,
+ b64_result + (((PATTERN_INPUTS_64_SHORT_COUNT) *
+ (PATTERN_INPUTS_64_SHORT_COUNT)) +
+ RANDOM_INPUTS_64_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_64(instruction_name, TEST_COUNT_TOTAL, elapsed_time,
+ b64_result, b64_expect);
+
+ return ret;
+}
diff --git a/tests/tcg/mips/user/isa/mips64r6/shift/test_mips64r6_sllv.c b/tests/tcg/mips/user/isa/mips64r6/shift/test_mips64r6_sllv.c
new file mode 100644
index 0000000..288d087
--- /dev/null
+++ b/tests/tcg/mips/user/isa/mips64r6/shift/test_mips64r6_sllv.c
@@ -0,0 +1,151 @@
+/*
+ * Test program for MIPS64R6 instruction SLLV
+ *
+ * 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_mips64r6.h"
+#include "../../../../include/test_inputs_64.h"
+#include "../../../../include/test_utils_64.h"
+
+#define TEST_COUNT_TOTAL (PATTERN_INPUTS_64_COUNT + RANDOM_INPUTS_64_COUNT)
+
+
+int32_t main(void)
+{
+ char *instruction_name = "SLLV";
+ int32_t ret;
+ uint32_t i, j;
+ struct timeval start, end;
+ double elapsed_time;
+
+ uint64_t b64_result[TEST_COUNT_TOTAL];
+ uint64_t b64_expect[TEST_COUNT_TOTAL] = {
+ 0xffffffff80000000ULL, /* 0 */
+ 0xffffffffffffffffULL,
+ 0xfffffffffffffc00ULL,
+ 0xffffffffffe00000ULL,
+ 0xfffffffffffff000ULL,
+ 0xfffffffffff80000ULL,
+ 0xffffffffffffc000ULL,
+ 0xfffffffffffe0000ULL,
+ 0x0000000000000000ULL, /* 8 */
+ 0x0000000000000000ULL,
+ 0x0000000000000000ULL,
+ 0x0000000000000000ULL,
+ 0x0000000000000000ULL,
+ 0x0000000000000000ULL,
+ 0x0000000000000000ULL,
+ 0x0000000000000000ULL,
+ 0x0000000000000000ULL, /* 16 */
+ 0xffffffffaaaaaaaaULL,
+ 0xffffffffaaaaa800ULL,
+ 0x0000000055400000ULL,
+ 0xffffffffaaaaa000ULL,
+ 0x0000000055500000ULL,
+ 0xffffffffaaaa8000ULL,
+ 0x0000000055540000ULL,
+ 0xffffffff80000000ULL, /* 24 */
+ 0x0000000055555555ULL,
+ 0x0000000055555400ULL,
+ 0xffffffffaaa00000ULL,
+ 0x0000000055555000ULL,
+ 0xffffffffaaa80000ULL,
+ 0x0000000055554000ULL,
+ 0xffffffffaaaa0000ULL,
+ 0x0000000000000000ULL, /* 32 */
+ 0xffffffffccccccccULL,
+ 0x0000000033333000ULL,
+ 0xffffffff99800000ULL,
+ 0xffffffffccccc000ULL,
+ 0x0000000066600000ULL,
+ 0x0000000033330000ULL,
+ 0xffffffff99980000ULL,
+ 0xffffffff80000000ULL, /* 40 */
+ 0x0000000033333333ULL,
+ 0xffffffffcccccc00ULL,
+ 0x0000000066600000ULL,
+ 0x0000000033333000ULL,
+ 0xffffffff99980000ULL,
+ 0xffffffffccccc000ULL,
+ 0x0000000066660000ULL,
+ 0x0000000000000000ULL, /* 48 */
+ 0xffffffff8e38e38eULL,
+ 0xffffffffe38e3800ULL,
+ 0x0000000071c00000ULL,
+ 0xffffffff8e38e000ULL,
+ 0x000000001c700000ULL,
+ 0x0000000038e38000ULL,
+ 0xffffffffc71c0000ULL,
+ 0xffffffff80000000ULL, /* 56 */
+ 0x0000000071c71c71ULL,
+ 0x000000001c71c400ULL,
+ 0xffffffff8e200000ULL,
+ 0x0000000071c71000ULL,
+ 0xffffffffe3880000ULL,
+ 0xffffffffc71c4000ULL,
+ 0x0000000038e20000ULL,
+ 0x0000000028625540ULL, /* 64 */
+ 0x0000000062554000ULL,
+ 0x0000000028625540ULL,
+ 0xffffffff95500000ULL,
+ 0x000000004d93c708ULL,
+ 0xffffffff93c70800ULL,
+ 0x000000004d93c708ULL,
+ 0xfffffffff1c20000ULL,
+ 0xffffffffb9cf8b80ULL, /* 72 */
+ 0xffffffffcf8b8000ULL,
+ 0xffffffffb9cf8b80ULL,
+ 0xffffffffe2e00000ULL,
+ 0x000000005e31e24eULL,
+ 0x0000000031e24e00ULL,
+ 0x000000005e31e24eULL,
+ 0x0000000078938000ULL,
+ };
+
+ gettimeofday(&start, NULL);
+
+ for (i = 0; i < PATTERN_INPUTS_64_SHORT_COUNT; i++) {
+ for (j = 0; j < PATTERN_INPUTS_64_SHORT_COUNT; j++) {
+ do_mips64r6_SLLV(b64_pattern + i, b64_pattern + j,
+ b64_result + (PATTERN_INPUTS_64_SHORT_COUNT * i + j));
+ }
+ }
+
+ for (i = 0; i < RANDOM_INPUTS_64_SHORT_COUNT; i++) {
+ for (j = 0; j < RANDOM_INPUTS_64_SHORT_COUNT; j++) {
+ do_mips64r6_SLLV(b64_random + i, b64_random + j,
+ b64_result + (((PATTERN_INPUTS_64_SHORT_COUNT) *
+ (PATTERN_INPUTS_64_SHORT_COUNT)) +
+ RANDOM_INPUTS_64_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_64(instruction_name, TEST_COUNT_TOTAL, elapsed_time,
+ b64_result, b64_expect);
+
+ return ret;
+}
diff --git a/tests/tcg/mips/user/isa/mips64r6/shift/test_mips64r6_srav.c b/tests/tcg/mips/user/isa/mips64r6/shift/test_mips64r6_srav.c
new file mode 100644
index 0000000..f547d9e
--- /dev/null
+++ b/tests/tcg/mips/user/isa/mips64r6/shift/test_mips64r6_srav.c
@@ -0,0 +1,151 @@
+/*
+ * Test program for MIPS64R6 instruction SRAV
+ *
+ * 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_mips64r6.h"
+#include "../../../../include/test_inputs_64.h"
+#include "../../../../include/test_utils_64.h"
+
+#define TEST_COUNT_TOTAL (PATTERN_INPUTS_64_COUNT + RANDOM_INPUTS_64_COUNT)
+
+
+int32_t main(void)
+{
+ char *instruction_name = "SRAV";
+ int32_t ret;
+ uint32_t i, j;
+ struct timeval start, end;
+ double elapsed_time;
+
+ uint64_t b64_result[TEST_COUNT_TOTAL];
+ uint64_t b64_expect[TEST_COUNT_TOTAL] = {
+ 0xffffffffffffffffULL, /* 0 */
+ 0xffffffffffffffffULL,
+ 0xffffffffffffffffULL,
+ 0xffffffffffffffffULL,
+ 0xffffffffffffffffULL,
+ 0xffffffffffffffffULL,
+ 0xffffffffffffffffULL,
+ 0xffffffffffffffffULL,
+ 0x0000000000000000ULL, /* 8 */
+ 0x0000000000000000ULL,
+ 0x0000000000000000ULL,
+ 0x0000000000000000ULL,
+ 0x0000000000000000ULL,
+ 0x0000000000000000ULL,
+ 0x0000000000000000ULL,
+ 0x0000000000000000ULL,
+ 0xffffffffffffffffULL, /* 16 */
+ 0xffffffffaaaaaaaaULL,
+ 0xffffffffffeaaaaaULL,
+ 0xfffffffffffffd55ULL,
+ 0xfffffffffffaaaaaULL,
+ 0xfffffffffffff555ULL,
+ 0xfffffffffffeaaaaULL,
+ 0xffffffffffffd555ULL,
+ 0x0000000000000000ULL, /* 24 */
+ 0x0000000055555555ULL,
+ 0x0000000000155555ULL,
+ 0x00000000000002aaULL,
+ 0x0000000000055555ULL,
+ 0x0000000000000aaaULL,
+ 0x0000000000015555ULL,
+ 0x0000000000002aaaULL,
+ 0xffffffffffffffffULL, /* 32 */
+ 0xffffffffccccccccULL,
+ 0xfffffffffff33333ULL,
+ 0xfffffffffffffe66ULL,
+ 0xfffffffffffcccccULL,
+ 0xfffffffffffff999ULL,
+ 0xffffffffffff3333ULL,
+ 0xffffffffffffe666ULL,
+ 0x0000000000000000ULL, /* 40 */
+ 0x0000000033333333ULL,
+ 0x00000000000cccccULL,
+ 0x0000000000000199ULL,
+ 0x0000000000033333ULL,
+ 0x0000000000000666ULL,
+ 0x000000000000ccccULL,
+ 0x0000000000001999ULL,
+ 0xffffffffffffffffULL, /* 48 */
+ 0xffffffff8e38e38eULL,
+ 0xffffffffffe38e38ULL,
+ 0xfffffffffffffc71ULL,
+ 0xfffffffffff8e38eULL,
+ 0xfffffffffffff1c7ULL,
+ 0xfffffffffffe38e3ULL,
+ 0xffffffffffffc71cULL,
+ 0x0000000000000000ULL, /* 56 */
+ 0x0000000071c71c71ULL,
+ 0x00000000001c71c7ULL,
+ 0x000000000000038eULL,
+ 0x0000000000071c71ULL,
+ 0x0000000000000e38ULL,
+ 0x000000000001c71cULL,
+ 0x00000000000038e3ULL,
+ 0x0000000028625540ULL, /* 64 */
+ 0x0000000000286255ULL,
+ 0x0000000028625540ULL,
+ 0x000000000000a189ULL,
+ 0x000000004d93c708ULL,
+ 0x00000000004d93c7ULL,
+ 0x000000004d93c708ULL,
+ 0x000000000001364fULL,
+ 0xffffffffb9cf8b80ULL, /* 72 */
+ 0xffffffffffb9cf8bULL,
+ 0xffffffffb9cf8b80ULL,
+ 0xfffffffffffee73eULL,
+ 0x000000005e31e24eULL,
+ 0x00000000005e31e2ULL,
+ 0x000000005e31e24eULL,
+ 0x00000000000178c7ULL,
+ };
+
+ gettimeofday(&start, NULL);
+
+ for (i = 0; i < PATTERN_INPUTS_64_SHORT_COUNT; i++) {
+ for (j = 0; j < PATTERN_INPUTS_64_SHORT_COUNT; j++) {
+ do_mips64r6_SRAV(b64_pattern + i, b64_pattern + j,
+ b64_result + (PATTERN_INPUTS_64_SHORT_COUNT * i + j));
+ }
+ }
+
+ for (i = 0; i < RANDOM_INPUTS_64_SHORT_COUNT; i++) {
+ for (j = 0; j < RANDOM_INPUTS_64_SHORT_COUNT; j++) {
+ do_mips64r6_SRAV(b64_random + i, b64_random + j,
+ b64_result + (((PATTERN_INPUTS_64_SHORT_COUNT) *
+ (PATTERN_INPUTS_64_SHORT_COUNT)) +
+ RANDOM_INPUTS_64_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_64(instruction_name, TEST_COUNT_TOTAL, elapsed_time,
+ b64_result, b64_expect);
+
+ return ret;
+}
diff --git a/tests/tcg/mips/user/isa/mips64r6/shift/test_mips64r6_srlv.c b/tests/tcg/mips/user/isa/mips64r6/shift/test_mips64r6_srlv.c
new file mode 100644
index 0000000..8b8075c
--- /dev/null
+++ b/tests/tcg/mips/user/isa/mips64r6/shift/test_mips64r6_srlv.c
@@ -0,0 +1,151 @@
+/*
+ * Test program for MIPS64R6 instruction SRLV
+ *
+ * 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_mips64r6.h"
+#include "../../../../include/test_inputs_64.h"
+#include "../../../../include/test_utils_64.h"
+
+#define TEST_COUNT_TOTAL (PATTERN_INPUTS_64_COUNT + RANDOM_INPUTS_64_COUNT)
+
+
+int32_t main(void)
+{
+ char *instruction_name = "SRLV";
+ int32_t ret;
+ uint32_t i, j;
+ struct timeval start, end;
+ double elapsed_time;
+
+ uint64_t b64_result[TEST_COUNT_TOTAL];
+ uint64_t b64_expect[TEST_COUNT_TOTAL] = {
+ 0x0000000000000001ULL, /* 0 */
+ 0xffffffffffffffffULL,
+ 0x00000000003fffffULL,
+ 0x00000000000007ffULL,
+ 0x00000000000fffffULL,
+ 0x0000000000001fffULL,
+ 0x000000000003ffffULL,
+ 0x0000000000007fffULL,
+ 0x0000000000000000ULL, /* 8 */
+ 0x0000000000000000ULL,
+ 0x0000000000000000ULL,
+ 0x0000000000000000ULL,
+ 0x0000000000000000ULL,
+ 0x0000000000000000ULL,
+ 0x0000000000000000ULL,
+ 0x0000000000000000ULL,
+ 0x0000000000000001ULL, /* 16 */
+ 0xffffffffaaaaaaaaULL,
+ 0x00000000002aaaaaULL,
+ 0x0000000000000555ULL,
+ 0x00000000000aaaaaULL,
+ 0x0000000000001555ULL,
+ 0x000000000002aaaaULL,
+ 0x0000000000005555ULL,
+ 0x0000000000000000ULL, /* 24 */
+ 0x0000000055555555ULL,
+ 0x0000000000155555ULL,
+ 0x00000000000002aaULL,
+ 0x0000000000055555ULL,
+ 0x0000000000000aaaULL,
+ 0x0000000000015555ULL,
+ 0x0000000000002aaaULL,
+ 0x0000000000000001ULL, /* 32 */
+ 0xffffffffccccccccULL,
+ 0x0000000000333333ULL,
+ 0x0000000000000666ULL,
+ 0x00000000000cccccULL,
+ 0x0000000000001999ULL,
+ 0x0000000000033333ULL,
+ 0x0000000000006666ULL,
+ 0x0000000000000000ULL, /* 40 */
+ 0x0000000033333333ULL,
+ 0x00000000000cccccULL,
+ 0x0000000000000199ULL,
+ 0x0000000000033333ULL,
+ 0x0000000000000666ULL,
+ 0x000000000000ccccULL,
+ 0x0000000000001999ULL,
+ 0x0000000000000001ULL, /* 48 */
+ 0xffffffff8e38e38eULL,
+ 0x0000000000238e38ULL,
+ 0x0000000000000471ULL,
+ 0x000000000008e38eULL,
+ 0x00000000000011c7ULL,
+ 0x00000000000238e3ULL,
+ 0x000000000000471cULL,
+ 0x0000000000000000ULL, /* 56 */
+ 0x0000000071c71c71ULL,
+ 0x00000000001c71c7ULL,
+ 0x000000000000038eULL,
+ 0x0000000000071c71ULL,
+ 0x0000000000000e38ULL,
+ 0x000000000001c71cULL,
+ 0x00000000000038e3ULL,
+ 0x0000000028625540ULL, /* 64 */
+ 0x0000000000286255ULL,
+ 0x0000000028625540ULL,
+ 0x000000000000a189ULL,
+ 0x000000004d93c708ULL,
+ 0x00000000004d93c7ULL,
+ 0x000000004d93c708ULL,
+ 0x000000000001364fULL,
+ 0xffffffffb9cf8b80ULL, /* 72 */
+ 0x0000000000b9cf8bULL,
+ 0xffffffffb9cf8b80ULL,
+ 0x000000000002e73eULL,
+ 0x000000005e31e24eULL,
+ 0x00000000005e31e2ULL,
+ 0x000000005e31e24eULL,
+ 0x00000000000178c7ULL,
+ };
+
+ gettimeofday(&start, NULL);
+
+ for (i = 0; i < PATTERN_INPUTS_64_SHORT_COUNT; i++) {
+ for (j = 0; j < PATTERN_INPUTS_64_SHORT_COUNT; j++) {
+ do_mips64r6_SRLV(b64_pattern + i, b64_pattern + j,
+ b64_result + (PATTERN_INPUTS_64_SHORT_COUNT * i + j));
+ }
+ }
+
+ for (i = 0; i < RANDOM_INPUTS_64_SHORT_COUNT; i++) {
+ for (j = 0; j < RANDOM_INPUTS_64_SHORT_COUNT; j++) {
+ do_mips64r6_SRLV(b64_random + i, b64_random + j,
+ b64_result + (((PATTERN_INPUTS_64_SHORT_COUNT) *
+ (PATTERN_INPUTS_64_SHORT_COUNT)) +
+ RANDOM_INPUTS_64_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_64(instruction_name, TEST_COUNT_TOTAL, elapsed_time,
+ b64_result, b64_expect);
+
+ return ret;
+}
diff --git a/tests/tcg/xtensa/Makefile b/tests/tcg/xtensa/Makefile
index 2f5691f..2bd4491 100644
--- a/tests/tcg/xtensa/Makefile
+++ b/tests/tcg/xtensa/Makefile
@@ -18,6 +18,9 @@
AS = $(CROSS)gcc -x assembler-with-cpp
LD = $(CROSS)ld
+ASFLAGS = -Wa,--no-absolute-literals
+vectors_ASFLAGS = -mtext-section-literals
+
XTENSA_SRC_PATH = $(SRC_PATH)/tests/tcg/xtensa
INCLUDE_DIRS = $(XTENSA_SRC_PATH) $(SRC_PATH)/target/xtensa/core-$(CORE)
XTENSA_INC = $(addprefix -I,$(INCLUDE_DIRS))
@@ -28,15 +31,21 @@
TESTCASES += test_b.tst
TESTCASES += test_bi.tst
-#TESTCASES += test_boolean.tst
+TESTCASES += test_boolean.tst
TESTCASES += test_break.tst
TESTCASES += test_bz.tst
TESTCASES += test_cache.tst
TESTCASES += test_clamps.tst
TESTCASES += test_extui.tst
TESTCASES += test_fail.tst
+TESTCASES += test_flix.tst
+TESTCASES += test_fp0_arith.tst
+TESTCASES += test_fp0_conv.tst
+TESTCASES += test_fp1.tst
+TESTCASES += test_fp_cpenable.tst
TESTCASES += test_interrupt.tst
TESTCASES += test_loop.tst
+TESTCASES += test_lsc.tst
TESTCASES += test_mac16.tst
TESTCASES += test_max.tst
TESTCASES += test_min.tst
@@ -68,7 +77,7 @@
$(CC) $(XTENSA_INC) $(CFLAGS) -c $< -o $@
%.o: $(XTENSA_SRC_PATH)/%.S
- $(CC) $(XTENSA_INC) $(ASFLAGS) -c $< -o $@
+ $(CC) $(XTENSA_INC) $($*_ASFLAGS) $(ASFLAGS) -c $< -o $@
%.tst: %.o linker.ld $(XTENSA_SRC_PATH)/macros.inc $(CRT) Makefile
$(LD) $(LDFLAGS) $(NOSTDFLAGS) $(CRT) $< -o $@
diff --git a/tests/tcg/xtensa/linker.ld.S b/tests/tcg/xtensa/linker.ld.S
index d0f3315..ac89b00 100644
--- a/tests/tcg/xtensa/linker.ld.S
+++ b/tests/tcg/xtensa/linker.ld.S
@@ -1,17 +1,29 @@
#include "core-isa.h"
-#if XTENSA_HAVE_BE
+#ifndef XCHAL_VECBASE_RESET_VADDR
+#define XCHAL_VECBASE_RESET_VADDR XCHAL_WINDOW_VECTORS_VADDR
+#define XCHAL_WINDOW_OF4_VECOFS 0x00000000
+#define XCHAL_WINDOW_UF4_VECOFS 0x00000040
+#define XCHAL_WINDOW_OF8_VECOFS 0x00000080
+#define XCHAL_WINDOW_UF8_VECOFS 0x000000C0
+#define XCHAL_WINDOW_OF12_VECOFS 0x00000100
+#define XCHAL_WINDOW_UF12_VECOFS 0x00000140
+#endif
+
+#define RAM_SIZE 0x08000000 /* 128M */
+#define ROM_SIZE 0x00001000 /* 4k */
+#define VECTORS_RESERVED_SIZE 0x1000
+
+#if XCHAL_HAVE_BE
OUTPUT_FORMAT("elf32-xtensa-be")
#else
OUTPUT_FORMAT("elf32-xtensa-le")
#endif
ENTRY(_start)
-__DYNAMIC = 0;
-
MEMORY {
- ram : ORIGIN = XCHAL_VECBASE_RESET_VADDR, LENGTH = 0x08000000 /* 128M */
- rom : ORIGIN = XCHAL_RESET_VECTOR_VADDR, LENGTH = 0x00001000 /* 4k */
+ ram : ORIGIN = XCHAL_VECBASE_RESET_VADDR, LENGTH = RAM_SIZE
+ rom : ORIGIN = XCHAL_RESET_VECTOR_VADDR, LENGTH = ROM_SIZE
}
SECTIONS
@@ -22,9 +34,9 @@
*(.init.*)
} > rom
- .vector :
- {
#if XCHAL_HAVE_WINDOWED
+ .vector.window XCHAL_WINDOW_VECTORS_VADDR :
+ {
. = XCHAL_WINDOW_OF4_VECOFS;
*(.vector.window_overflow_4)
. = XCHAL_WINDOW_UF4_VECOFS;
@@ -37,41 +49,58 @@
*(.vector.window_overflow_12)
. = XCHAL_WINDOW_UF12_VECOFS;
*(.vector.window_underflow_12)
+ }
#endif
#if XCHAL_NUM_INTLEVELS + XCHAL_HAVE_NMI >= 2
- . = XCHAL_INTLEVEL2_VECOFS;
+ .vector.level2 XCHAL_INTLEVEL2_VECTOR_VADDR :
+ {
*(.vector.level2)
+ }
#endif
#if XCHAL_NUM_INTLEVELS + XCHAL_HAVE_NMI >= 3
- . = XCHAL_INTLEVEL3_VECOFS;
+ .vector.level3 XCHAL_INTLEVEL3_VECTOR_VADDR :
+ {
*(.vector.level3)
+ }
#endif
#if XCHAL_NUM_INTLEVELS + XCHAL_HAVE_NMI >= 4
- . = XCHAL_INTLEVEL4_VECOFS;
+ .vector.level4 XCHAL_INTLEVEL4_VECTOR_VADDR :
+ {
*(.vector.level4)
+ }
#endif
#if XCHAL_NUM_INTLEVELS + XCHAL_HAVE_NMI >= 5
- . = XCHAL_INTLEVEL5_VECOFS;
+ .vector.level5 XCHAL_INTLEVEL5_VECTOR_VADDR :
+ {
*(.vector.level5)
+ }
#endif
#if XCHAL_NUM_INTLEVELS + XCHAL_HAVE_NMI >= 6
- . = XCHAL_INTLEVEL6_VECOFS;
+ .vector.level6 XCHAL_INTLEVEL6_VECTOR_VADDR :
+ {
*(.vector.level6)
+ }
#endif
#if XCHAL_NUM_INTLEVELS + XCHAL_HAVE_NMI >= 7
- . = XCHAL_INTLEVEL7_VECOFS;
+ .vector.level7 XCHAL_INTLEVEL7_VECTOR_VADDR :
+ {
*(.vector.level7)
+ }
#endif
-
- . = XCHAL_KERNEL_VECOFS;
+ .vector.kernel XCHAL_KERNEL_VECTOR_VADDR :
+ {
*(.vector.kernel)
- . = XCHAL_USER_VECOFS;
+ }
+ .vector.user XCHAL_USER_VECTOR_VADDR :
+ {
*(.vector.user)
- . = XCHAL_DOUBLEEXC_VECOFS;
+ }
+ .vector.double XCHAL_DOUBLEEXC_VECTOR_VADDR :
+ {
*(.vector.double)
- } > ram
+ }
- .vector.text :
+ .vector.text XCHAL_VECBASE_RESET_VADDR + VECTORS_RESERVED_SIZE :
{
*(.vector.window_overflow_4.*)
*(.vector.window_underflow_4.*)
diff --git a/tests/tcg/xtensa/macros.inc b/tests/tcg/xtensa/macros.inc
index 4ebd30a..aa8f95b 100644
--- a/tests/tcg/xtensa/macros.inc
+++ b/tests/tcg/xtensa/macros.inc
@@ -23,11 +23,14 @@
movi a0, result
sub a2, a2, a0
movi a3, 0
- loopnez a2, 1f
- l8ui a2, a0, 0
- or a3, a3, a2
- addi a0, a0, 1
+ beqz a2, 2f
1:
+ l8ui a1, a0, 0
+ or a3, a3, a1
+ addi a0, a0, 1
+ addi a2, a2, -1
+ bnez a2, 1b
+2:
exit
.endm
@@ -49,7 +52,9 @@
.endm
.macro test name
- //print test_\name
+#ifdef DEBUG
+ print test_\name
+#endif
test_init
test_\name:
.global test_\name
@@ -74,6 +79,9 @@
l32i a2, a2, 0
movi a3, 1
s8i a3, a2, 0
+#ifdef DEBUG
+ print failed
+#endif
j 99f
.endm
@@ -89,3 +97,26 @@
movi a3, \addr
s32i a3, a2, 0
.endm
+
+.macro dump r
+#ifdef DEBUG
+.data
+.align 4
+1: .word 0
+.text
+ movi a4, 1b
+ s32i a2, a4, 0
+ movi a2, 4
+ movi a3, 1
+ movi a5, 4
+ simcall
+ movi a4, 1b
+ l32i a2, a4, 0
+#endif
+.endm
+
+#define glue(a, b) _glue(a, b)
+#define _glue(a, b) a ## b
+
+#define glue3(a, b, c) _glue3(a, b, c)
+#define _glue3(a, b, c) a ## b ## c
diff --git a/tests/tcg/xtensa/test_b.S b/tests/tcg/xtensa/test_b.S
index 8e81f95..713a454 100644
--- a/tests/tcg/xtensa/test_b.S
+++ b/tests/tcg/xtensa/test_b.S
@@ -84,12 +84,24 @@
test bbc
movi a2, 0xfffffffd
- movi a3, 0xffffff01
+#undef BIT
+#if XCHAL_HAVE_BE
+#define BIT 0xfffffffe
+#else
+#define BIT 0xffffff01
+#endif
+ movi a3, BIT
bbc a2, a3, 1f
test_fail
1:
movi a2, 8
- movi a3, 0xffffff03
+#undef BIT
+#if XCHAL_HAVE_BE
+#define BIT 0xfffffffc
+#else
+#define BIT 0xffffff03
+#endif
+ movi a3, BIT
bbc a2, a3, 1f
j 2f
1:
@@ -99,11 +111,11 @@
test bbci
movi a2, 0xfffdffff
- bbci a2, 17, 1f
+ bbci.l a2, 17, 1f
test_fail
1:
movi a2, 0x00020000
- bbci a2, 17, 1f
+ bbci.l a2, 17, 1f
j 2f
1:
test_fail
@@ -192,12 +204,24 @@
test bbs
movi a2, 8
- movi a3, 0xffffff03
+#undef BIT
+#if XCHAL_HAVE_BE
+#define BIT 0xfffffffc
+#else
+#define BIT 0xffffff03
+#endif
+ movi a3, BIT
bbs a2, a3, 1f
test_fail
1:
movi a2, 0xfffffffd
- movi a3, 0xffffff01
+#undef BIT
+#if XCHAL_HAVE_BE
+#define BIT 0xfffffffe
+#else
+#define BIT 0xffffff01
+#endif
+ movi a3, BIT
bbs a2, a3, 1f
j 2f
1:
@@ -207,11 +231,11 @@
test bbsi
movi a2, 0x00020000
- bbsi a2, 17, 1f
+ bbsi.l a2, 17, 1f
test_fail
1:
movi a2, 0xfffdffff
- bbsi a2, 17, 1f
+ bbsi.l a2, 17, 1f
j 2f
1:
test_fail
diff --git a/tests/tcg/xtensa/test_boolean.S b/tests/tcg/xtensa/test_boolean.S
index eac40e0..5a850bf 100644
--- a/tests/tcg/xtensa/test_boolean.S
+++ b/tests/tcg/xtensa/test_boolean.S
@@ -2,6 +2,8 @@
test_suite boolean
+#if XCHAL_HAVE_BOOLEANS
+
test all4
movi a2, 0xfec0
wsr a2, br
@@ -20,4 +22,6 @@
assert eq, a2, a3
test_end
+#endif
+
test_suite_end
diff --git a/tests/tcg/xtensa/test_break.S b/tests/tcg/xtensa/test_break.S
index 775cd7c..3379a3f 100644
--- a/tests/tcg/xtensa/test_break.S
+++ b/tests/tcg/xtensa/test_break.S
@@ -1,10 +1,13 @@
#include "macros.inc"
-#define debug_level 6
-#define debug_vector level6
-
test_suite break
+#if XCHAL_HAVE_DEBUG
+
+#define debug_level XCHAL_DEBUGLEVEL
+#define debug_vector glue(level, XCHAL_DEBUGLEVEL)
+#define EPC_DEBUG glue(epc, XCHAL_DEBUGLEVEL)
+
test break
set_vector debug_vector, 0
rsil a2, debug_level
@@ -21,7 +24,7 @@
and a2, a2, a3
movi a3, 0x10 | debug_level
assert eq, a2, a3
- rsr a2, epc6
+ rsr a2, EPC_DEBUG
movi a3, 1b
assert eq, a2, a3
rsr a2, debugcause
@@ -45,7 +48,7 @@
and a2, a2, a3
movi a3, 0x10 | debug_level
assert eq, a2, a3
- rsr a2, epc6
+ rsr a2, EPC_DEBUG
movi a3, 1b
assert eq, a2, a3
rsr a2, debugcause
@@ -53,6 +56,7 @@
assert eq, a2, a3
test_end
+#if XCHAL_NUM_IBREAK
test ibreak
set_vector debug_vector, 0
rsil a2, debug_level
@@ -83,7 +87,7 @@
and a2, a2, a3
movi a3, 0x10 | debug_level
assert eq, a2, a3
- rsr a2, epc6
+ rsr a2, EPC_DEBUG
movi a3, 1b
assert eq, a2, a3
rsr a2, debugcause
@@ -110,7 +114,7 @@
and a2, a2, a3
movi a3, 0x10 | debug_level
assert eq, a2, a3
- rsr a2, epc6
+ rsr a2, EPC_DEBUG
movi a3, 2b
assert eq, a2, a3
rsr a2, debugcause
@@ -141,6 +145,7 @@
movi a3, 0x2
assert eq, a2, a3
test_end
+#endif
test icount
set_vector debug_vector, 2f
@@ -158,7 +163,7 @@
2:
movi a2, 0
wsr a2, icountlevel
- rsr a2, epc6
+ rsr a2, EPC_DEBUG
movi a3, 1b
assert eq, a2, a3
rsr a2, debugcause
@@ -167,7 +172,7 @@
test_end
.macro check_dbreak dr
- rsr a2, epc6
+ rsr a2, EPC_DEBUG
movi a3, 1b
assert eq, a2, a3
rsr a2, debugcause
@@ -194,6 +199,7 @@
reset_ps
.endm
+#if XCHAL_NUM_DBREAK
test dbreak_exact
dbreak_test 0, 0x4000003f, 0xd000007f, 0xd000007f, l8ui
dbreak_test 1, 0x4000003e, 0xd000007e, 0xd000007e, l16ui
@@ -253,5 +259,8 @@
dbreak_test 0, 0x40000030, 0xd0000071, 0xd0000070, l16ui
dbreak_test 1, 0x40000035, 0xd0000072, 0xd0000070, l32i
test_end
+#endif
+
+#endif
test_suite_end
diff --git a/tests/tcg/xtensa/test_cache.S b/tests/tcg/xtensa/test_cache.S
index 6b2df97..7e6ba4c 100644
--- a/tests/tcg/xtensa/test_cache.S
+++ b/tests/tcg/xtensa/test_cache.S
@@ -7,6 +7,8 @@
test_suite cache
+#if XCHAL_HAVE_PTP_MMU
+
.macro pf_op op
\op a2, 0
\op a3, 0
@@ -18,14 +20,23 @@
movi a3, 0xd8000000 /* non-cacheable */
movi a4, 0x00001235 /* unmapped */
+#if XCHAL_DCACHE_SIZE
pf_op dpfr
pf_op dpfro
pf_op dpfw
pf_op dpfwo
+#endif
+#ifdef XCHAL_ICACHE_SIZE
pf_op ipf
-
+#endif
+#if XCHAL_HAVE_PTP_MMU && !XCHAL_HAVE_SPANNING_WAY
+#if XCHAL_DCACHE_LINE_LOCKABLE
dpfl a2, 0
+#endif
+#if XCHAL_ICACHE_LINE_LOCKABLE
ipfl a2, 0
+#endif
+#endif
test_end
.macro cache_fault op, addr, exc_code
@@ -46,10 +57,16 @@
assert eq, a2, a3
.endm
+#if XCHAL_HAVE_PTP_MMU && !XCHAL_HAVE_SPANNING_WAY
+
+#if XCHAL_DCACHE_LINE_LOCKABLE
test dpfl_tlb_miss
cache_fault dpfl, 0x00002345, 24
test_end
+#endif
+#if XCHAL_DCACHE_SIZE
+#if XCHAL_DCACHE_IS_WRITEBACK
test dhwb_tlb_miss
cache_fault dhwb, 0x00002345, 24
test_end
@@ -57,16 +74,21 @@
test dhwbi_tlb_miss
cache_fault dhwbi, 0x00002345, 24
test_end
+#endif
test dhi_tlb_miss
cache_fault dhi, 0x00002345, 24
test_end
+#if XCHAL_DCACHE_LINE_LOCKABLE
test dhu_tlb_miss
cache_fault dhu, 0x00002345, 24
test_end
+#endif
+#endif
-
+#if XCHAL_ICACHE_SIZE
+#if XCHAL_ICACHE_LINE_LOCKABLE
test ipfl_tlb_miss
cache_fault ipfl, 0x00002345, 16
test_end
@@ -74,24 +96,40 @@
test ihu_tlb_miss
cache_fault ihu, 0x00002345, 16
test_end
+#endif
test ihi_tlb_miss
cache_fault ihi, 0x00002345, 16
test_end
+#endif
+
+#endif
+
+#endif
test_suite_end
-.macro cache_all op1, op2, size, linesize
- movi a2, 0
- movi a3, \size
-1:
- \op1 a2, 0
- \op2 a2, 0
- addi a2, a2, \linesize
- bltu a2, a3, 1b
-.endm
-
cache_unlock_invalidate:
- cache_all diu, dii, XCHAL_DCACHE_SIZE, XCHAL_DCACHE_LINESIZE
- cache_all iiu, iii, XCHAL_ICACHE_SIZE, XCHAL_ICACHE_LINESIZE
+#if XCHAL_DCACHE_SIZE
+ movi a2, 0
+ movi a3, XCHAL_DCACHE_SIZE
+1:
+#if XCHAL_DCACHE_LINE_LOCKABLE
+ diu a2, 0
+#endif
+ dii a2, 0
+ addi a2, a2, XCHAL_DCACHE_LINESIZE
+ bltu a2, a3, 1b
+#endif
+#if XCHAL_ICACHE_SIZE
+ movi a2, 0
+ movi a3, XCHAL_ICACHE_SIZE
+1:
+#if XCHAL_ICACHE_LINE_LOCKABLE
+ iiu a2, 0
+#endif
+ iii a2, 0
+ addi a2, a2, XCHAL_ICACHE_LINESIZE
+ bltu a2, a3, 1b
+#endif
ret
diff --git a/tests/tcg/xtensa/test_clamps.S b/tests/tcg/xtensa/test_clamps.S
index 3efabfd..d9b2c38 100644
--- a/tests/tcg/xtensa/test_clamps.S
+++ b/tests/tcg/xtensa/test_clamps.S
@@ -2,6 +2,8 @@
test_suite clamps
+#if XCHAL_HAVE_CLAMPS
+
test clamps
movi a2, 0
movi a3, 0
@@ -39,4 +41,6 @@
assert eq, a3, a2
test_end
+#endif
+
test_suite_end
diff --git a/tests/tcg/xtensa/test_flix.S b/tests/tcg/xtensa/test_flix.S
new file mode 100644
index 0000000..7c259e7
--- /dev/null
+++ b/tests/tcg/xtensa/test_flix.S
@@ -0,0 +1,60 @@
+#include "macros.inc"
+
+test_suite flix
+
+#if XCHAL_HAVE_FLIX3
+
+test misc
+ {
+ mov a3, a4
+ mov a2, a3
+ nop
+ }
+ {
+ nop
+ bne.w18 a2, a3, 1f
+ }
+ movi a2, 1f
+ {
+ mov a2, a3
+ mov a3, a2
+ nop
+ }
+ {
+ l32i a2, a3, 0
+ add a4, a4, a2
+ nop
+ }
+ {
+ mov a3, a4
+ jx a3
+ nop
+ }
+1:
+test_end
+
+test sum
+
+ movi a2, 0
+ movi a3, 2f
+ movi a4, 0
+ movi a5, 4
+
+ loop a5, 1f
+ {
+ l32i a2, a3, 0
+ addi a3, a3, 4
+ add a4, a4, a2
+ }
+1:
+ add a4, a4, a2
+ assert eqi, a4, 10
+ .data
+2:
+ .word 1, 2, 3, 4
+ .previous
+test_end
+
+#endif
+
+test_suite_end
diff --git a/tests/tcg/xtensa/test_fp0_arith.S b/tests/tcg/xtensa/test_fp0_arith.S
new file mode 100644
index 0000000..253d033
--- /dev/null
+++ b/tests/tcg/xtensa/test_fp0_arith.S
@@ -0,0 +1,173 @@
+#include "macros.inc"
+
+test_suite fp0_arith
+
+#if XCHAL_HAVE_FP
+
+.macro movfp fr, v
+ movi a2, \v
+ wfr \fr, a2
+.endm
+
+.macro check_res fr, r
+ rfr a2, \fr
+ dump a2
+ movi a3, \r
+ assert eq, a2, a3
+ rur a2, fsr
+ assert eqi, a2, 0
+.endm
+
+.macro test_op2_rm op, fr0, fr1, fr2, v0, v1, r
+ movi a2, 0
+ wur a2, fsr
+ movfp \fr0, \v0
+ movfp \fr1, \v1
+ \op \fr2, \fr0, \fr1
+ check_res \fr2, \r
+.endm
+
+.macro test_op3_rm op, fr0, fr1, fr2, fr3, v0, v1, v2, r
+ movi a2, 0
+ wur a2, fsr
+ movfp \fr0, \v0
+ movfp \fr1, \v1
+ movfp \fr2, \v2
+ \op \fr0, \fr1, \fr2
+ check_res \fr3, \r
+.endm
+
+.macro test_op2_ex op, fr0, fr1, fr2, v0, v1, rm, r
+ movi a2, \rm
+ wur a2, fcr
+ test_op2_rm \op, \fr0, \fr1, \fr2, \v0, \v1, \r
+ movi a2, (\rm) | 0x7c
+ wur a2, fcr
+ test_op2_rm \op, \fr0, \fr1, \fr2, \v0, \v1, \r
+.endm
+
+.macro test_op3_ex op, fr0, fr1, fr2, fr3, v0, v1, v2, rm, r
+ movi a2, \rm
+ wur a2, fcr
+ test_op3_rm \op, \fr0, \fr1, \fr2, \fr3, \v0, \v1, \v2, \r
+ movi a2, (\rm) | 0x7c
+ wur a2, fcr
+ test_op3_rm \op, \fr0, \fr1, \fr2, \fr3, \v0, \v1, \v2, \r
+.endm
+
+.macro test_op2 op, fr0, fr1, fr2, v0, v1, r0, r1, r2, r3
+ test_op2_ex \op, \fr0, \fr1, \fr2, \v0, \v1, 0, \r0
+ test_op2_ex \op, \fr0, \fr1, \fr2, \v0, \v1, 1, \r1
+ test_op2_ex \op, \fr0, \fr1, \fr2, \v0, \v1, 2, \r2
+ test_op2_ex \op, \fr0, \fr1, \fr2, \v0, \v1, 3, \r3
+.endm
+
+.macro test_op3 op, fr0, fr1, fr2, fr3, v0, v1, v2, r0, r1, r2, r3
+ test_op3_ex \op, \fr0, \fr1, \fr2, \fr3, \v0, \v1, \v2, 0, \r0
+ test_op3_ex \op, \fr0, \fr1, \fr2, \fr3, \v0, \v1, \v2, 1, \r1
+ test_op3_ex \op, \fr0, \fr1, \fr2, \fr3, \v0, \v1, \v2, 2, \r2
+ test_op3_ex \op, \fr0, \fr1, \fr2, \fr3, \v0, \v1, \v2, 3, \r3
+.endm
+
+.macro test_op2_cpe op
+ set_vector kernel, 2f
+ movi a2, 0
+ wsr a2, cpenable
+1:
+ \op f2, f0, f1
+ test_fail
+2:
+ rsr a2, excvaddr
+ movi a3, 1b
+ assert eq, a2, a3
+ rsr a2, exccause
+ movi a3, 32
+ assert eq, a2, a3
+
+ set_vector kernel, 0
+ movi a2, 1
+ wsr a2, cpenable
+.endm
+
+test add_s
+ movi a2, 1
+ wsr a2, cpenable
+
+ test_op2 add.s, f0, f1, f2, 0x3fc00000, 0x34400000, \
+ 0x3fc00002, 0x3fc00001, 0x3fc00002, 0x3fc00001
+ test_op2 add.s, f3, f4, f5, 0x3fc00000, 0x34a00000, \
+ 0x3fc00002, 0x3fc00002, 0x3fc00003, 0x3fc00002
+
+ /* MAX_FLOAT + MAX_FLOAT = +inf/MAX_FLOAT */
+ test_op2 add.s, f6, f7, f8, 0x7f7fffff, 0x7f7fffff, \
+ 0x7f800000, 0x7f7fffff, 0x7f800000, 0x7f7fffff
+test_end
+
+test add_s_inf
+ /* 1 + +inf = +inf */
+ test_op2 add.s, f6, f7, f8, 0x3fc00000, 0x7f800000, \
+ 0x7f800000, 0x7f800000, 0x7f800000, 0x7f800000
+
+ /* +inf + -inf = default NaN */
+ test_op2 add.s, f0, f1, f2, 0x7f800000, 0xff800000, \
+ 0x7fc00000, 0x7fc00000, 0x7fc00000, 0x7fc00000
+test_end
+
+test add_s_nan
+ /* 1 + NaN = NaN */
+ test_op2 add.s, f9, f10, f11, 0x3fc00000, 0x7fc00001, \
+ 0x7fc00001, 0x7fc00001, 0x7fc00001, 0x7fc00001
+ test_op2 add.s, f12, f13, f14, 0x3fc00000, 0x7f800001, \
+ 0x7f800001, 0x7f800001, 0x7f800001, 0x7f800001
+
+ /* NaN1 + NaN2 = NaN1 */
+ test_op2 add.s, f15, f0, f1, 0x7f800001, 0x7fbfffff, \
+ 0x7f800001, 0x7f800001, 0x7f800001, 0x7f800001
+ test_op2 add.s, f2, f3, f4, 0x7fbfffff, 0x7f800001, \
+ 0x7fbfffff, 0x7fbfffff, 0x7fbfffff, 0x7fbfffff
+ test_op2 add.s, f5, f6, f7, 0x7fc00001, 0x7fbfffff, \
+ 0x7fc00001, 0x7fc00001, 0x7fc00001, 0x7fc00001
+ test_op2 add.s, f8, f9, f10, 0x7fbfffff, 0x7fc00001, \
+ 0x7fbfffff, 0x7fbfffff, 0x7fbfffff, 0x7fbfffff
+test_end
+
+test sub_s
+ test_op2 sub.s, f0, f1, f0, 0x3f800001, 0x33800000, \
+ 0x3f800000, 0x3f800000, 0x3f800001, 0x3f800000
+ test_op2 sub.s, f0, f1, f1, 0x3f800002, 0x33800000, \
+ 0x3f800002, 0x3f800001, 0x3f800002, 0x3f800001
+
+ /* norm - norm = denorm */
+ test_op2 sub.s, f6, f7, f8, 0x00800001, 0x00800000, \
+ 0x00000001, 0x00000001, 0x00000001, 0x00000001
+test_end
+
+test mul_s
+ test_op2 mul.s, f0, f1, f2, 0x3f800001, 0x3f800001, \
+ 0x3f800002, 0x3f800002, 0x3f800003, 0x3f800002
+
+ /* MAX_FLOAT/2 * MAX_FLOAT/2 = +inf/MAX_FLOAT */
+ test_op2 mul.s, f6, f7, f8, 0x7f000000, 0x7f000000, \
+ 0x7f800000, 0x7f7fffff, 0x7f800000, 0x7f7fffff
+ /* min norm * min norm = 0/denorm */
+ test_op2 mul.s, f6, f7, f8, 0x00800001, 0x00800000, \
+ 0x00000000, 0x00000000, 0x00000001, 0x00000000
+
+ /* inf * 0 = default NaN */
+ test_op2 mul.s, f6, f7, f8, 0x7f800000, 0x00000000, \
+ 0x7fc00000, 0x7fc00000, 0x7fc00000, 0x7fc00000
+test_end
+
+test madd_s
+ test_op3 madd.s, f0, f1, f2, f0, 0, 0x3f800001, 0x3f800001, \
+ 0x3f800002, 0x3f800002, 0x3f800003, 0x3f800002
+test_end
+
+test msub_s
+ test_op3 msub.s, f0, f1, f2, f0, 0x3f800000, 0x3f800001, 0x3f800001, \
+ 0xb4800000, 0xb4800000, 0xb4800000, 0xb4800001
+test_end
+
+#endif
+
+test_suite_end
diff --git a/tests/tcg/xtensa/test_fp0_conv.S b/tests/tcg/xtensa/test_fp0_conv.S
new file mode 100644
index 0000000..147e3d5
--- /dev/null
+++ b/tests/tcg/xtensa/test_fp0_conv.S
@@ -0,0 +1,304 @@
+#include "macros.inc"
+
+test_suite fp0_conv
+
+#if XCHAL_HAVE_FP
+
+.macro movfp fr, v
+ movi a2, \v
+ wfr \fr, a2
+.endm
+
+.macro test_ftoi_ex op, r0, fr0, v, c, r
+ movi a2, 0
+ wur a2, fsr
+ movfp \fr0, \v
+ \op \r0, \fr0, \c
+ dump \r0
+ movi a3, \r
+ assert eq, \r0, a3
+ rur a2, fsr
+ assert eqi, a2, 0
+.endm
+
+.macro test_ftoi op, r0, fr0, v, c, r
+ movi a2, 0
+ wur a2, fcr
+ test_ftoi_ex \op, \r0, \fr0, \v, \c, \r
+ movi a2, 0x7c
+ wur a2, fcr
+ test_ftoi_ex \op, \r0, \fr0, \v, \c, \r
+.endm
+
+
+.macro test_itof_ex op, fr0, ar0, v, c, r
+ movi a2, 0
+ wur a2, fsr
+ movi \ar0, \v
+ \op \fr0, \ar0, \c
+
+ rfr a2, \fr0
+ dump a2
+ movi a3, \r
+ assert eq, a2, a3
+ rur a2, fsr
+ assert eqi, a2, 0
+.endm
+
+.macro test_itof_rm op, fr0, ar0, v, c, rm, r
+ movi a2, \rm
+ wur a2, fcr
+ test_itof_ex \op, \fr0, \ar0, \v, \c, \r
+ movi a2, (\rm) | 0x7c
+ wur a2, fcr
+ test_itof_ex \op, \fr0, \ar0, \v, \c, \r
+.endm
+
+.macro test_itof op, fr0, ar0, v, c, r0, r1, r2, r3
+ test_itof_rm \op, \fr0, \ar0, \v, \c, 0, \r0
+ test_itof_rm \op, \fr0, \ar0, \v, \c, 1, \r1
+ test_itof_rm \op, \fr0, \ar0, \v, \c, 2, \r2
+ test_itof_rm \op, \fr0, \ar0, \v, \c, 3, \r3
+.endm
+
+test round_s
+ movi a2, 1
+ wsr a2, cpenable
+
+ /* NaN */
+ test_ftoi round.s, a2, f0, 0xffc00001, 0, 0x7fffffff
+ test_ftoi round.s, a2, f0, 0xff800001, 0, 0x7fffffff
+
+ /* -inf */
+ test_ftoi round.s, a2, f0, 0xff800000, 0, 0x80000000
+
+ /* negative overflow */
+ test_ftoi round.s, a2, f0, 0xceffffff, 1, 0x80000000
+ test_ftoi round.s, a2, f0, 0xcf000000, 0, 0x80000000
+ test_ftoi round.s, a2, f0, 0xceffffff, 0, 0x80000080
+
+ /* negative */
+ test_ftoi round.s, a2, f0, 0xbfa00000, 1, -2 /* -1.25 * 2 */
+ test_ftoi round.s, a2, f0, 0xbfc00000, 0, -2 /* -1.5 */
+ test_ftoi round.s, a2, f0, 0xbf800000, 1, -2 /* -1 * 2 */
+ test_ftoi round.s, a2, f0, 0xbf800000, 0, -1 /* -1 */
+ test_ftoi round.s, a2, f0, 0xbf400000, 0, -1 /* -0.75 */
+ test_ftoi round.s, a2, f0, 0xbf000000, 0, 0 /* -0.5 */
+
+ /* positive */
+ test_ftoi round.s, a2, f0, 0x3f000000, 0, 0 /* 0.5 */
+ test_ftoi round.s, a2, f0, 0x3f400000, 0, 1 /* 0.75 */
+ test_ftoi round.s, a2, f0, 0x3f800000, 0, 1 /* 1 */
+ test_ftoi round.s, a2, f0, 0x3f800000, 1, 2 /* 1 * 2 */
+ test_ftoi round.s, a2, f0, 0x3fc00000, 0, 2 /* 1.5 */
+ test_ftoi round.s, a2, f0, 0x3fa00000, 1, 2 /* 1.25 * 2 */
+
+ /* positive overflow */
+ test_ftoi round.s, a2, f0, 0x4effffff, 0, 0x7fffff80
+ test_ftoi round.s, a2, f0, 0x4f000000, 0, 0x7fffffff
+ test_ftoi round.s, a2, f0, 0x4effffff, 1, 0x7fffffff
+
+ /* +inf */
+ test_ftoi round.s, a2, f0, 0x7f800000, 0, 0x7fffffff
+
+ /* NaN */
+ test_ftoi round.s, a2, f0, 0x7f800001, 0, 0x7fffffff
+ test_ftoi round.s, a2, f0, 0x7fc00000, 0, 0x7fffffff
+test_end
+
+test trunc_s
+ /* NaN */
+ test_ftoi trunc.s, a2, f0, 0xffc00001, 0, 0x7fffffff
+ test_ftoi trunc.s, a2, f0, 0xff800001, 0, 0x7fffffff
+
+ /* -inf */
+ test_ftoi trunc.s, a2, f0, 0xff800000, 0, 0x80000000
+
+ /* negative overflow */
+ test_ftoi trunc.s, a2, f0, 0xceffffff, 1, 0x80000000
+ test_ftoi trunc.s, a2, f0, 0xcf000000, 0, 0x80000000
+ test_ftoi trunc.s, a2, f0, 0xceffffff, 0, 0x80000080
+
+ /* negative */
+ test_ftoi trunc.s, a2, f0, 0xbfa00000, 1, -2 /* -1.25 * 2 */
+ test_ftoi trunc.s, a2, f0, 0xbfc00000, 0, -1 /* -1.5 */
+ test_ftoi trunc.s, a2, f0, 0xbf800000, 1, -2 /* -1 * 2 */
+ test_ftoi trunc.s, a2, f0, 0xbf800000, 0, -1 /* -1 */
+ test_ftoi trunc.s, a2, f0, 0xbf400000, 0, 0 /* -0.75 */
+ test_ftoi trunc.s, a2, f0, 0xbf000000, 0, 0 /* -0.5 */
+
+ /* positive */
+ test_ftoi trunc.s, a2, f0, 0x3f000000, 0, 0 /* 0.5 */
+ test_ftoi trunc.s, a2, f0, 0x3f400000, 0, 0 /* 0.75 */
+ test_ftoi trunc.s, a2, f0, 0x3f800000, 0, 1 /* 1 */
+ test_ftoi trunc.s, a2, f0, 0x3f800000, 1, 2 /* 1 * 2 */
+ test_ftoi trunc.s, a2, f0, 0x3fc00000, 0, 1 /* 1.5 */
+ test_ftoi trunc.s, a2, f0, 0x3fa00000, 1, 2 /* 1.25 * 2 */
+
+ /* positive overflow */
+ test_ftoi trunc.s, a2, f0, 0x4effffff, 0, 0x7fffff80
+ test_ftoi trunc.s, a2, f0, 0x4f000000, 0, 0x7fffffff
+ test_ftoi trunc.s, a2, f0, 0x4effffff, 1, 0x7fffffff
+
+ /* +inf */
+ test_ftoi trunc.s, a2, f0, 0x7f800000, 0, 0x7fffffff
+
+ /* NaN */
+ test_ftoi trunc.s, a2, f0, 0x7f800001, 0, 0x7fffffff
+ test_ftoi trunc.s, a2, f0, 0x7fc00000, 0, 0x7fffffff
+test_end
+
+test floor_s
+ /* NaN */
+ test_ftoi floor.s, a2, f0, 0xffc00001, 0, 0x7fffffff
+ test_ftoi floor.s, a2, f0, 0xff800001, 0, 0x7fffffff
+
+ /* -inf */
+ test_ftoi floor.s, a2, f0, 0xff800000, 0, 0x80000000
+
+ /* negative overflow */
+ test_ftoi floor.s, a2, f0, 0xceffffff, 1, 0x80000000
+ test_ftoi floor.s, a2, f0, 0xcf000000, 0, 0x80000000
+ test_ftoi floor.s, a2, f0, 0xceffffff, 0, 0x80000080
+
+ /* negative */
+ test_ftoi floor.s, a2, f0, 0xbfa00000, 1, -3 /* -1.25 * 2 */
+ test_ftoi floor.s, a2, f0, 0xbfc00000, 0, -2 /* -1.5 */
+ test_ftoi floor.s, a2, f0, 0xbf800000, 1, -2 /* -1 * 2 */
+ test_ftoi floor.s, a2, f0, 0xbf800000, 0, -1 /* -1 */
+ test_ftoi floor.s, a2, f0, 0xbf400000, 0, -1 /* -0.75 */
+ test_ftoi floor.s, a2, f0, 0xbf000000, 0, -1 /* -0.5 */
+
+ /* positive */
+ test_ftoi floor.s, a2, f0, 0x3f000000, 0, 0 /* 0.5 */
+ test_ftoi floor.s, a2, f0, 0x3f400000, 0, 0 /* 0.75 */
+ test_ftoi floor.s, a2, f0, 0x3f800000, 0, 1 /* 1 */
+ test_ftoi floor.s, a2, f0, 0x3f800000, 1, 2 /* 1 * 2 */
+ test_ftoi floor.s, a2, f0, 0x3fc00000, 0, 1 /* 1.5 */
+ test_ftoi floor.s, a2, f0, 0x3fa00000, 1, 2 /* 1.25 * 2 */
+
+ /* positive overflow */
+ test_ftoi floor.s, a2, f0, 0x4effffff, 0, 0x7fffff80
+ test_ftoi floor.s, a2, f0, 0x4f000000, 0, 0x7fffffff
+ test_ftoi floor.s, a2, f0, 0x4effffff, 1, 0x7fffffff
+
+ /* +inf */
+ test_ftoi floor.s, a2, f0, 0x7f800000, 0, 0x7fffffff
+
+ /* NaN */
+ test_ftoi floor.s, a2, f0, 0x7f800001, 0, 0x7fffffff
+ test_ftoi floor.s, a2, f0, 0x7fc00000, 0, 0x7fffffff
+test_end
+
+test ceil_s
+ /* NaN */
+ test_ftoi ceil.s, a2, f0, 0xffc00001, 0, 0x7fffffff
+ test_ftoi ceil.s, a2, f0, 0xff800001, 0, 0x7fffffff
+
+ /* -inf */
+ test_ftoi ceil.s, a2, f0, 0xff800000, 0, 0x80000000
+
+ /* negative overflow */
+ test_ftoi ceil.s, a2, f0, 0xceffffff, 1, 0x80000000
+ test_ftoi ceil.s, a2, f0, 0xcf000000, 0, 0x80000000
+ test_ftoi ceil.s, a2, f0, 0xceffffff, 0, 0x80000080
+
+ /* negative */
+ test_ftoi ceil.s, a2, f0, 0xbfa00000, 1, -2 /* -1.25 * 2 */
+ test_ftoi ceil.s, a2, f0, 0xbfc00000, 0, -1 /* -1.5 */
+ test_ftoi ceil.s, a2, f0, 0xbf800000, 1, -2 /* -1 * 2 */
+ test_ftoi ceil.s, a2, f0, 0xbf800000, 0, -1 /* -1 */
+ test_ftoi ceil.s, a2, f0, 0xbf400000, 0, 0 /* -0.75 */
+ test_ftoi ceil.s, a2, f0, 0xbf000000, 0, 0 /* -0.5 */
+
+ /* positive */
+ test_ftoi ceil.s, a2, f0, 0x3f000000, 0, 1 /* 0.5 */
+ test_ftoi ceil.s, a2, f0, 0x3f400000, 0, 1 /* 0.75 */
+ test_ftoi ceil.s, a2, f0, 0x3f800000, 0, 1 /* 1 */
+ test_ftoi ceil.s, a2, f0, 0x3f800000, 1, 2 /* 1 * 2 */
+ test_ftoi ceil.s, a2, f0, 0x3fc00000, 0, 2 /* 1.5 */
+ test_ftoi ceil.s, a2, f0, 0x3fa00000, 1, 3 /* 1.25 * 2 */
+
+ /* positive overflow */
+ test_ftoi ceil.s, a2, f0, 0x4effffff, 0, 0x7fffff80
+ test_ftoi ceil.s, a2, f0, 0x4f000000, 0, 0x7fffffff
+ test_ftoi ceil.s, a2, f0, 0x4effffff, 1, 0x7fffffff
+
+ /* +inf */
+ test_ftoi ceil.s, a2, f0, 0x7f800000, 0, 0x7fffffff
+
+ /* NaN */
+ test_ftoi ceil.s, a2, f0, 0x7f800001, 0, 0x7fffffff
+ test_ftoi ceil.s, a2, f0, 0x7fc00000, 0, 0x7fffffff
+test_end
+
+test utrunc_s
+ /* NaN */
+ test_ftoi utrunc.s, a2, f0, 0xffc00001, 0, 0xffffffff
+ test_ftoi utrunc.s, a2, f0, 0xff800001, 0, 0xffffffff
+
+ /* -inf */
+ test_ftoi utrunc.s, a2, f0, 0xff800000, 0, 0x80000000
+
+ /* negative overflow */
+ test_ftoi utrunc.s, a2, f0, 0xceffffff, 1, 0x80000000
+ test_ftoi utrunc.s, a2, f0, 0xcf000000, 0, 0x80000000
+ test_ftoi utrunc.s, a2, f0, 0xceffffff, 0, 0x80000080
+
+ /* negative */
+ test_ftoi utrunc.s, a2, f0, 0xbfa00000, 1, -2 /* -1.25 * 2 */
+ test_ftoi utrunc.s, a2, f0, 0xbfc00000, 0, -1 /* -1.5 */
+ test_ftoi utrunc.s, a2, f0, 0xbf800000, 1, -2 /* -1 * 2 */
+ test_ftoi utrunc.s, a2, f0, 0xbf800000, 0, -1 /* -1 */
+ test_ftoi utrunc.s, a2, f0, 0xbf400000, 0, 0 /* -0.75 */
+ test_ftoi utrunc.s, a2, f0, 0xbf000000, 0, 0 /* -0.5 */
+
+ /* positive */
+ test_ftoi utrunc.s, a2, f0, 0x3f000000, 0, 0 /* 0.5 */
+ test_ftoi utrunc.s, a2, f0, 0x3f400000, 0, 0 /* 0.75 */
+ test_ftoi utrunc.s, a2, f0, 0x3f800000, 0, 1 /* 1 */
+ test_ftoi utrunc.s, a2, f0, 0x3f800000, 1, 2 /* 1 * 2 */
+ test_ftoi utrunc.s, a2, f0, 0x3fc00000, 0, 1 /* 1.5 */
+ test_ftoi utrunc.s, a2, f0, 0x3fa00000, 1, 2 /* 1.25 * 2 */
+
+ /* positive overflow */
+ test_ftoi utrunc.s, a2, f0, 0x4effffff, 0, 0x7fffff80
+ test_ftoi utrunc.s, a2, f0, 0x4f000000, 0, 0x80000000
+ test_ftoi utrunc.s, a2, f0, 0x4effffff, 1, 0xffffff00
+ test_ftoi utrunc.s, a2, f0, 0x4f800000, 1, 0xffffffff
+
+ /* +inf */
+ test_ftoi utrunc.s, a2, f0, 0x7f800000, 0, 0xffffffff
+
+ /* NaN */
+ test_ftoi utrunc.s, a2, f0, 0x7f800001, 0, 0xffffffff
+ test_ftoi utrunc.s, a2, f0, 0x7fc00000, 0, 0xffffffff
+test_end
+
+test float_s
+ test_itof float.s, f0, a2, -1, 0, \
+ 0xbf800000, 0xbf800000, 0xbf800000, 0xbf800000
+ test_itof float.s, f0, a2, 0, 0, 0, 0, 0, 0
+ test_itof float.s, f0, a2, 1, 1, \
+ 0x3f000000, 0x3f000000, 0x3f000000, 0x3f000000
+ test_itof float.s, f0, a2, 1, 0, \
+ 0x3f800000, 0x3f800000, 0x3f800000, 0x3f800000
+ test_itof float.s, f0, a2, 0x7fffffff, 0, \
+ 0x4f000000, 0x4effffff, 0x4f000000, 0x4effffff
+test_end
+
+test ufloat_s
+ test_itof ufloat.s, f0, a2, 0, 0, 0, 0, 0, 0
+ test_itof ufloat.s, f0, a2, 1, 1, \
+ 0x3f000000, 0x3f000000, 0x3f000000, 0x3f000000
+ test_itof ufloat.s, f0, a2, 1, 0, \
+ 0x3f800000, 0x3f800000, 0x3f800000, 0x3f800000
+ test_itof ufloat.s, f0, a2, 0x7fffffff, 0, \
+ 0x4f000000, 0x4effffff, 0x4f000000, 0x4effffff
+ test_itof ufloat.s, f0, a2, 0xffffffff, 0, \
+ 0x4f800000, 0x4f7fffff, 0x4f800000, 0x4f7fffff
+test_end
+
+#endif
+
+test_suite_end
diff --git a/tests/tcg/xtensa/test_fp1.S b/tests/tcg/xtensa/test_fp1.S
new file mode 100644
index 0000000..6e182e5
--- /dev/null
+++ b/tests/tcg/xtensa/test_fp1.S
@@ -0,0 +1,141 @@
+#include "macros.inc"
+
+test_suite fp1
+
+#if XCHAL_HAVE_FP
+
+.macro movfp fr, v
+ movi a2, \v
+ wfr \fr, a2
+.endm
+
+.macro test_ord_ex op, br, fr0, fr1, v0, v1, r
+ movi a2, 0
+ wur a2, fsr
+ movfp \fr0, \v0
+ movfp \fr1, \v1
+ \op \br, \fr0, \fr1
+ movi a2, 0
+ movi a3, 1
+ movt a2, a3, \br
+ assert eqi, a2, \r
+ rur a2, fsr
+ assert eqi, a2, 0
+.endm
+
+.macro test_ord op, br, fr0, fr1, v0, v1, r
+ movi a2, 0
+ wur a2, fcr
+ test_ord_ex \op, \br, \fr0, \fr1, \v0, \v1, \r
+ movi a2, 0x7c
+ wur a2, fcr
+ test_ord_ex \op, \br, \fr0, \fr1, \v0, \v1, \r
+.endm
+
+.macro test_ord_all op, aa, ab, ba, aPI, PIa, aN, Na, II, IN, NI
+ test_ord \op b0, f0, f1, 0x3f800000, 0x3f800000, \aa
+ test_ord \op b1, f2, f3, 0x3f800000, 0x3fc00000, \ab
+ test_ord \op b2, f4, f5, 0x3fc00000, 0x3f800000, \ba
+ test_ord \op b3, f6, f7, 0x3f800000, 0x7f800000, \aPI
+ test_ord \op b4, f8, f9, 0x7f800000, 0x3f800000, \PIa
+ test_ord \op b5, f10, f11, 0x3f800000, 0xffc00001, \aN
+ test_ord \op b6, f12, f13, 0x3f800000, 0xff800001, \aN
+ test_ord \op b7, f14, f15, 0x3f800000, 0x7f800001, \aN
+ test_ord \op b8, f0, f1, 0x3f800000, 0x7fc00000, \aN
+ test_ord \op b9, f2, f3, 0xffc00001, 0x3f800000, \Na
+ test_ord \op b10, f4, f5, 0xff800001, 0x3f800000, \Na
+ test_ord \op b11, f6, f7, 0x7f800001, 0x3f800000, \Na
+ test_ord \op b12, f8, f9, 0x7fc00000, 0x3f800000, \Na
+ test_ord \op b13, f10, f11, 0x7f800000, 0x7f800000, \II
+ test_ord \op b14, f12, f13, 0x7f800000, 0x7fc00000, \IN
+ test_ord \op b15, f14, f15, 0x7fc00000, 0x7f800000, \NI
+.endm
+
+test un_s
+ movi a2, 1
+ wsr a2, cpenable
+ test_ord_all un.s, 0, 0, 0, 0, 0, 1, 1, 0, 1, 1
+test_end
+
+test oeq_s
+ test_ord_all oeq.s, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0
+test_end
+
+test ueq_s
+ test_ord_all ueq.s, 1, 0, 0, 0, 0, 1, 1, 1, 1, 1
+test_end
+
+test olt_s
+ test_ord_all olt.s, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0
+test_end
+
+test ult_s
+ test_ord_all ult.s, 0, 1, 0, 1, 0, 1, 1, 0, 1, 1
+test_end
+
+test ole_s
+ test_ord_all ole.s, 1, 1, 0, 1, 0, 0, 0, 1, 0, 0
+test_end
+
+test ule_s
+ test_ord_all ule.s, 1, 1, 0, 1, 0, 1, 1, 1, 1, 1
+test_end
+
+.macro test_cond op, fr0, fr1, cr, v0, v1, r
+ movfp \fr0, \v0
+ movfp \fr1, \v1
+ \op \fr0, \fr1, \cr
+ rfr a2, \fr0
+ movi a3, \r
+ assert eq, a2, a3
+.endm
+
+test moveqz_s
+ movi a3, 0
+ test_cond moveqz.s, f0, f1, a3, 0, 0x3f800000, 0x3f800000
+ movi a3, 1
+ test_cond moveqz.s, f0, f1, a3, 0, 0x3f800000, 0
+test_end
+
+test movnez_s
+ movi a3, 0
+ test_cond movnez.s, f0, f1, a3, 0, 0x3f800000, 0
+ movi a3, 1
+ test_cond movnez.s, f0, f1, a3, 0, 0x3f800000, 0x3f800000
+test_end
+
+test movltz_s
+ movi a3, -1
+ test_cond movltz.s, f0, f1, a3, 0, 0x3f800000, 0x3f800000
+ movi a3, 0
+ test_cond movltz.s, f0, f1, a3, 0, 0x3f800000, 0
+ movi a3, 1
+ test_cond movltz.s, f0, f1, a3, 0, 0x3f800000, 0
+test_end
+
+test movgez_s
+ movi a3, -1
+ test_cond movgez.s, f0, f1, a3, 0, 0x3f800000, 0
+ movi a3, 0
+ test_cond movgez.s, f0, f1, a3, 0, 0x3f800000, 0x3f800000
+ movi a3, 1
+ test_cond movgez.s, f0, f1, a3, 0, 0x3f800000, 0x3f800000
+test_end
+
+test movf_s
+ olt.s b0, f0, f0
+ test_cond movf.s, f0, f1, b0, 0, 0x3f800000, 0x3f800000
+ ueq.s b0, f0, f0
+ test_cond movf.s, f0, f1, b0, 0, 0x3f800000, 0
+test_end
+
+test movt_s
+ ueq.s b0, f0, f0
+ test_cond movt.s, f0, f1, b0, 0, 0x3f800000, 0x3f800000
+ olt.s b0, f0, f0
+ test_cond movt.s, f0, f1, b0, 0, 0x3f800000, 0
+test_end
+
+#endif
+
+test_suite_end
diff --git a/tests/tcg/xtensa/test_fp_cpenable.S b/tests/tcg/xtensa/test_fp_cpenable.S
new file mode 100644
index 0000000..882bb2f
--- /dev/null
+++ b/tests/tcg/xtensa/test_fp_cpenable.S
@@ -0,0 +1,27 @@
+#include "macros.inc"
+
+test_suite fp_cpenable
+
+#if XCHAL_HAVE_FP
+
+test rur
+ set_vector kernel, 2f
+ movi a2, 0
+ wsr a2, cpenable
+ isync
+1:
+ rur a2, fsr
+ //wfr f0, a2
+ test_fail
+2:
+ movi a2, 1b
+ rsr a3, epc1
+ assert eq, a2, a3
+ movi a2, 32
+ rsr a3, exccause
+ assert eq, a2, a3
+test_end
+
+#endif
+
+test_suite_end
diff --git a/tests/tcg/xtensa/test_interrupt.S b/tests/tcg/xtensa/test_interrupt.S
index 8766835..efedc43 100644
--- a/tests/tcg/xtensa/test_interrupt.S
+++ b/tests/tcg/xtensa/test_interrupt.S
@@ -1,15 +1,59 @@
#include "macros.inc"
-#define LSBIT(v) ((v) ^ ((v) & ((v) - 1)))
+#define LSBIT(v) ((v) & -(v))
+
+#define LEVEL_MASK(x) glue3(XCHAL_INTLEVEL, x, _MASK)
+#define LEVEL_SOFT_MASK(x) (LEVEL_MASK(x) & XCHAL_INTTYPE_MASK_SOFTWARE)
+
+#define L1_SOFT_MASK LEVEL_SOFT_MASK(1)
+#define L1_SOFT LSBIT(L1_SOFT_MASK)
+
+#if LEVEL_SOFT_MASK(2)
+#define HIGH_LEVEL_SOFT_MASK LEVEL_SOFT_MASK(2)
+#elif LEVEL_SOFT_MASK(3)
+#define HIGH_LEVEL_SOFT_MASK LEVEL_SOFT_MASK(3)
+#elif LEVEL_SOFT_MASK(4)
+#define HIGH_LEVEL_SOFT_MASK LEVEL_SOFT_MASK(4)
+#elif LEVEL_SOFT_MASK(5)
+#define HIGH_LEVEL_SOFT_MASK LEVEL_SOFT_MASK(5)
+#elif LEVEL_SOFT_MASK(6)
+#define HIGH_LEVEL_SOFT_MASK LEVEL_SOFT_MASK(6)
+#else
+#define HIGH_LEVEL_SOFT_MASK 0
+#endif
+
+#define HIGH_LEVEL_SOFT LSBIT(HIGH_LEVEL_SOFT_MASK)
+
+#if LEVEL_SOFT_MASK(2)
+#define HIGH_LEVEL_SOFT_LEVEL 2
+#elif LEVEL_SOFT_MASK(3)
+#define HIGH_LEVEL_SOFT_LEVEL 3
+#elif LEVEL_SOFT_MASK(4)
+#define HIGH_LEVEL_SOFT_LEVEL 4
+#elif LEVEL_SOFT_MASK(5)
+#define HIGH_LEVEL_SOFT_LEVEL 5
+#elif LEVEL_SOFT_MASK(6)
+#define HIGH_LEVEL_SOFT_LEVEL 6
+#else
+#define HIGH_LEVEL_SOFT_LEVEL 0
+#endif
test_suite interrupt
+#if XCHAL_HAVE_INTERRUPTS
+
.macro clear_interrupts
movi a2, 0
wsr a2, intenable
+#if XCHAL_NUM_TIMERS
wsr a2, ccompare0
+#endif
+#if XCHAL_NUM_TIMERS > 1
wsr a2, ccompare1
+#endif
+#if XCHAL_NUM_TIMERS > 2
wsr a2, ccompare2
+#endif
esync
rsr a2, interrupt
wsr a2, intclear
@@ -44,11 +88,12 @@
assert eqi, a2, 0
test_end
+#if L1_SOFT
test soft_disabled
set_vector kernel, 1f
clear_interrupts
- movi a2, LSBIT(XCHAL_INTTYPE_MASK_SOFTWARE)
+ movi a2, L1_SOFT
wsr a2, intset
esync
rsr a3, interrupt
@@ -70,7 +115,7 @@
set_vector kernel, 1f
clear_interrupts
- movi a2, LSBIT(XCHAL_INTTYPE_MASK_SOFTWARE)
+ movi a2, L1_SOFT
wsr a2, intset
esync
rsr a3, interrupt
@@ -89,7 +134,7 @@
set_vector kernel, 1f
clear_interrupts
- movi a2, LSBIT(XCHAL_INTTYPE_MASK_SOFTWARE)
+ movi a2, L1_SOFT
wsr a2, intset
esync
rsr a3, interrupt
@@ -108,7 +153,7 @@
set_vector kernel, 1f
clear_interrupts
- movi a2, LSBIT(XCHAL_INTTYPE_MASK_SOFTWARE)
+ movi a2, L1_SOFT
wsr a2, intset
esync
rsr a3, interrupt
@@ -127,7 +172,7 @@
set_vector user, 2f
clear_interrupts
- movi a2, LSBIT(XCHAL_INTTYPE_MASK_SOFTWARE)
+ movi a2, L1_SOFT
wsr a2, intset
esync
rsr a3, interrupt
@@ -147,12 +192,13 @@
check_l1
test_end
+#if HIGH_LEVEL_SOFT
test soft_priority
set_vector kernel, 1f
- set_vector level3, 2f
+ set_vector glue(level, HIGH_LEVEL_SOFT_LEVEL), 2f
clear_interrupts
- movi a2, XCHAL_INTTYPE_MASK_SOFTWARE
+ movi a2, L1_SOFT | HIGH_LEVEL_SOFT
wsr a2, intenable
rsil a3, 0
esync
@@ -164,17 +210,20 @@
rsr a2, ps
movi a3, 0x1f /* EXCM | INTMASK */
and a2, a2, a3
- movi a3, 0x13
+ movi a3, 0x10 | HIGH_LEVEL_SOFT_LEVEL
assert eq, a2, a3 /* EXCM and INTMASK are set
for high-priority interrupt */
test_end
+#endif
+#endif
+#if HIGH_LEVEL_SOFT
test eps_epc_rfi
- set_vector level3, 3f
+ set_vector glue(level, HIGH_LEVEL_SOFT_LEVEL), 3f
clear_interrupts
reset_ps
- movi a2, XCHAL_INTTYPE_MASK_SOFTWARE
+ movi a2, L1_SOFT_MASK | HIGH_LEVEL_SOFT_MASK
wsr a2, intenable
rsil a3, 0
rsr a3, ps
@@ -185,23 +234,26 @@
2:
test_fail
3:
- rsr a2, eps3
+ rsr a2, glue(eps, HIGH_LEVEL_SOFT_LEVEL)
assert eq, a2, a3
- rsr a2, epc3
+ rsr a2, glue(epc, HIGH_LEVEL_SOFT_LEVEL)
movi a3, 1b
assert ge, a2, a3
movi a3, 2b
assert ge, a3, a2
movi a2, 4f
- wsr a2, epc3
- movi a2, 0x40003
- wsr a2, eps3
- rfi 3
+ wsr a2, glue(epc, HIGH_LEVEL_SOFT_LEVEL)
+ movi a2, 0x40000 | HIGH_LEVEL_SOFT_LEVEL
+ wsr a2, glue(eps, HIGH_LEVEL_SOFT_LEVEL)
+ rfi HIGH_LEVEL_SOFT_LEVEL
test_fail
4:
rsr a2, ps
- movi a3, 0x40003
+ movi a3, 0x40000 | HIGH_LEVEL_SOFT_LEVEL
assert eq, a2, a3
test_end
+#endif
+
+#endif
test_suite_end
diff --git a/tests/tcg/xtensa/test_loop.S b/tests/tcg/xtensa/test_loop.S
index 5755578..0cfd866 100644
--- a/tests/tcg/xtensa/test_loop.S
+++ b/tests/tcg/xtensa/test_loop.S
@@ -2,6 +2,8 @@
test_suite loop
+#if XCHAL_HAVE_LOOPS
+
test loop
movi a2, 0
movi a3, 5
@@ -160,4 +162,6 @@
1:
test_end
+#endif
+
test_suite_end
diff --git a/tests/tcg/xtensa/test_lsc.S b/tests/tcg/xtensa/test_lsc.S
new file mode 100644
index 0000000..0578bf1
--- /dev/null
+++ b/tests/tcg/xtensa/test_lsc.S
@@ -0,0 +1,122 @@
+#include "macros.inc"
+
+test_suite lsc
+
+#if XCHAL_HAVE_FP
+
+test lsi
+ movi a2, 1
+ wsr a2, cpenable
+
+ movi a2, 1f
+ lsi f0, a2, 0
+ lsi f1, a2, 4
+ lsiu f2, a2, 8
+ movi a3, 1f + 8
+ assert eq, a2, a3
+ rfr a2, f0
+ movi a3, 0x3f800000
+ assert eq, a2, a3
+ rfr a2, f1
+ movi a3, 0x40000000
+ assert eq, a2, a3
+ rfr a2, f2
+ movi a3, 0x40400000
+ assert eq, a2, a3
+.data
+ .align 4
+1:
+.float 1, 2, 3
+.text
+test_end
+
+test ssi
+ movi a2, 1f
+ movi a3, 0x40800000
+ wfr f3, a3
+ ssi f3, a2, 0
+ movi a3, 0x40a00000
+ wfr f4, a3
+ ssi f4, a2, 4
+ movi a3, 0x40c00000
+ wfr f5, a3
+ ssiu f5, a2, 8
+ movi a3, 1f + 8
+ assert eq, a2, a3
+ l32i a4, a2, -8
+ movi a3, 0x40800000
+ assert eq, a4, a3
+ l32i a4, a2, -4
+ movi a3, 0x40a00000
+ assert eq, a4, a3
+ l32i a4, a2, 0
+ movi a3, 0x40c00000
+ assert eq, a4, a3
+.data
+ .align 4
+1:
+.float 0, 0, 0
+.text
+test_end
+
+test lsx
+ movi a2, 1f
+ movi a3, 0
+ lsx f6, a2, a3
+ movi a3, 4
+ lsx f7, a2, a3
+ movi a3, 8
+ lsxu f8, a2, a3
+ movi a3, 1f + 8
+ assert eq, a2, a3
+ rfr a2, f6
+ movi a3, 0x40e00000
+ assert eq, a2, a3
+ rfr a2, f7
+ movi a3, 0x41000000
+ assert eq, a2, a3
+ rfr a2, f8
+ movi a3, 0x41100000
+ assert eq, a2, a3
+.data
+ .align 4
+1:
+.float 7, 8, 9
+.text
+test_end
+
+test ssx
+ movi a2, 1f
+ movi a3, 0
+ movi a4, 0x41200000
+ wfr f9, a4
+ ssx f9, a2, a3
+ movi a3, 4
+ movi a4, 0x41300000
+ wfr f10, a4
+ ssx f10, a2, a3
+ movi a3, 8
+ movi a4, 0x41400000
+ wfr f11, a4
+ ssxu f11, a2, a3
+ movi a3, 1f + 8
+ assert eq, a2, a3
+ l32i a4, a2, -8
+ movi a3, 0x41200000
+ assert eq, a4, a3
+ l32i a4, a2, -4
+ movi a3, 0x41300000
+ assert eq, a4, a3
+ l32i a4, a2, 0
+ movi a3, 0x41400000
+ assert eq, a4, a3
+.data
+ .align 4
+1:
+.float 0, 0, 0
+.text
+test_end
+
+#endif
+
+test_suite_end
diff --git a/tests/tcg/xtensa/test_mac16.S b/tests/tcg/xtensa/test_mac16.S
index 512025d..ee0cedd 100644
--- a/tests/tcg/xtensa/test_mac16.S
+++ b/tests/tcg/xtensa/test_mac16.S
@@ -2,6 +2,8 @@
test_suite mac16
+#if XCHAL_HAVE_MAC16
+
#define ext16(v) (((v) & 0xffff) | (((v) & 0x8000) * 0x1ffffffe))
#define mul16(a, b) ((ext16(a) * ext16(b)))
@@ -240,4 +242,6 @@
.text
test_end
+#endif
+
test_suite_end
diff --git a/tests/tcg/xtensa/test_max.S b/tests/tcg/xtensa/test_max.S
index 3caa207..f349d57 100644
--- a/tests/tcg/xtensa/test_max.S
+++ b/tests/tcg/xtensa/test_max.S
@@ -2,6 +2,8 @@
test_suite max
+#if XCHAL_HAVE_MINMAX
+
test max
movi a2, 0xffffffff
movi a3, 1
@@ -78,4 +80,6 @@
assert eq, a3, a4
test_end
+#endif
+
test_suite_end
diff --git a/tests/tcg/xtensa/test_min.S b/tests/tcg/xtensa/test_min.S
index 551cf59..89ee103 100644
--- a/tests/tcg/xtensa/test_min.S
+++ b/tests/tcg/xtensa/test_min.S
@@ -2,6 +2,8 @@
test_suite min
+#if XCHAL_HAVE_MINMAX
+
test min
movi a2, 0xffffffff
movi a3, 1
@@ -78,4 +80,6 @@
assert eq, a3, a4
test_end
+#endif
+
test_suite_end
diff --git a/tests/tcg/xtensa/test_mmu.S b/tests/tcg/xtensa/test_mmu.S
index a15316f..4cbd6ef 100644
--- a/tests/tcg/xtensa/test_mmu.S
+++ b/tests/tcg/xtensa/test_mmu.S
@@ -2,6 +2,8 @@
test_suite mmu
+#if XCHAL_HAVE_PTP_MMU && !XCHAL_HAVE_SPANNING_WAY
+
.purgem test_init
.macro clean_tlb_way way, page_size, n_entries
@@ -740,4 +742,6 @@
assert eq, a2, a3
test_end
+#endif
+
test_suite_end
diff --git a/tests/tcg/xtensa/test_mul16.S b/tests/tcg/xtensa/test_mul16.S
index 98fa704..32507f7 100644
--- a/tests/tcg/xtensa/test_mul16.S
+++ b/tests/tcg/xtensa/test_mul16.S
@@ -2,6 +2,8 @@
test_suite mul16
+#if XCHAL_HAVE_MUL16
+
test mul16u_pp
movi a2, 0x137f5a5a
mov a3, a2
@@ -80,4 +82,6 @@
assert eq, a3, a6
test_end
+#endif
+
test_suite_end
diff --git a/tests/tcg/xtensa/test_mul32.S b/tests/tcg/xtensa/test_mul32.S
index b288ead..862d45a 100644
--- a/tests/tcg/xtensa/test_mul32.S
+++ b/tests/tcg/xtensa/test_mul32.S
@@ -2,6 +2,8 @@
test_suite mul32
+#if XCHAL_HAVE_MUL32
+
test mull
movi a2, 0x137f5a5a
mov a3, a2
@@ -15,6 +17,8 @@
assert eq, a3, a6
test_end
+#endif
+
/* unfortunately dc232b doesn't have muluh/mulsh*/
test_suite_end
diff --git a/tests/tcg/xtensa/test_nsa.S b/tests/tcg/xtensa/test_nsa.S
index 479b2e2..0af7d1f 100644
--- a/tests/tcg/xtensa/test_nsa.S
+++ b/tests/tcg/xtensa/test_nsa.S
@@ -2,6 +2,8 @@
test_suite nsa
+#if XCHAL_HAVE_NSA
+
test nsa
movi a2, 0
movi a3, 31
@@ -56,4 +58,6 @@
assert eq, a3, a2
test_end
+#endif
+
test_suite_end
diff --git a/tests/tcg/xtensa/test_phys_mem.S b/tests/tcg/xtensa/test_phys_mem.S
index aae0a79..9bb3ee3 100644
--- a/tests/tcg/xtensa/test_phys_mem.S
+++ b/tests/tcg/xtensa/test_phys_mem.S
@@ -2,6 +2,8 @@
test_suite phys_mem
+#if XCHAL_HAVE_PTP_MMU && !XCHAL_HAVE_SPANNING_WAY
+
.purgem test_init
.macro test_init
@@ -67,6 +69,8 @@
assert eq, a2, a3
test_end
+#endif
+
test inst_fetch_no_phys
set_vector kernel, 2f
diff --git a/tests/tcg/xtensa/test_quo.S b/tests/tcg/xtensa/test_quo.S
index 5b3ae38..32886b9 100644
--- a/tests/tcg/xtensa/test_quo.S
+++ b/tests/tcg/xtensa/test_quo.S
@@ -2,6 +2,8 @@
test_suite quo
+#if XCHAL_HAVE_DIV32
+
test quou_pp
movi a2, 0x5a5a137f
mov a3, a2
@@ -144,4 +146,6 @@
assert eq, a2, a3
test_end
+#endif
+
test_suite_end
diff --git a/tests/tcg/xtensa/test_rem.S b/tests/tcg/xtensa/test_rem.S
index 6357e52..0b96bb3 100644
--- a/tests/tcg/xtensa/test_rem.S
+++ b/tests/tcg/xtensa/test_rem.S
@@ -2,6 +2,8 @@
test_suite rem
+#if XCHAL_HAVE_DIV32
+
test remu_pp
movi a2, 0x5a5a137f
mov a3, a2
@@ -144,4 +146,6 @@
assert eq, a2, a3
test_end
+#endif
+
test_suite_end
diff --git a/tests/tcg/xtensa/test_rst0.S b/tests/tcg/xtensa/test_rst0.S
index a73366b..143e90b 100644
--- a/tests/tcg/xtensa/test_rst0.S
+++ b/tests/tcg/xtensa/test_rst0.S
@@ -54,6 +54,8 @@
assert eq, a4, a6
test_end
+#if XCHAL_HAVE_ADDX
+
test addx2
movi a2, 0x137fa5a5
mov a3, a2
@@ -93,6 +95,8 @@
assert eq, a4, a6
test_end
+#endif
+
test sub
movi a2, 0x137fa5a5
mov a3, a2
@@ -106,6 +110,8 @@
assert eq, a4, a6
test_end
+#if XCHAL_HAVE_ADDX
+
test subx2
movi a2, 0x137fa5a5
mov a3, a2
@@ -145,4 +151,6 @@
assert eq, a4, a6
test_end
+#endif
+
test_suite_end
diff --git a/tests/tcg/xtensa/test_s32c1i.S b/tests/tcg/xtensa/test_s32c1i.S
index 93b575d..2885d9d 100644
--- a/tests/tcg/xtensa/test_s32c1i.S
+++ b/tests/tcg/xtensa/test_s32c1i.S
@@ -2,7 +2,13 @@
test_suite s32c1i
+#if XCHAL_HAVE_S32C1I
+
test s32c1i_nowrite
+#if XCHAL_HW_VERSION >= 230000
+ movi a2, 0x29
+ wsr a2, atomctl
+#endif
movi a2, 1f
movi a3, 1
wsr a3, scompare1
@@ -20,6 +26,10 @@
test_end
test s32c1i_write
+#if XCHAL_HW_VERSION >= 230000
+ movi a2, 0x29
+ wsr a2, atomctl
+#endif
movi a2, 1f
movi a3, 3
wsr a3, scompare1
@@ -36,4 +46,6 @@
.text
test_end
+#endif
+
test_suite_end
diff --git a/tests/tcg/xtensa/test_sext.S b/tests/tcg/xtensa/test_sext.S
index 087a633..483d217 100644
--- a/tests/tcg/xtensa/test_sext.S
+++ b/tests/tcg/xtensa/test_sext.S
@@ -2,6 +2,8 @@
test_suite sext
+#if XCHAL_HAVE_SEXT
+
test sext
movi a2, 0xffffff5a
movi a3, 0x0000005a
@@ -66,4 +68,6 @@
assert eq, a3, a2
test_end
+#endif
+
test_suite_end
diff --git a/tests/tcg/xtensa/test_sr.S b/tests/tcg/xtensa/test_sr.S
index 052f1e0..b1a91a0 100644
--- a/tests/tcg/xtensa/test_sr.S
+++ b/tests/tcg/xtensa/test_sr.S
@@ -2,11 +2,23 @@
test_suite sr
+#if XCHAL_HAVE_BE
+#define LOW__SR 0x04
+#define HI_RSR 0x30
+#define HI_WSR 0x31
+#define HI_XSR 0x16
+#else
+#define LOW__SR 0x40
+#define HI_RSR 0x03
+#define HI_WSR 0x13
+#define HI_XSR 0x61
+#endif
+
.macro sr_op sym, op_sym, op_byte, sr
.if \sym
\op_sym a4, \sr
.else
- .byte 0x40, \sr, \op_byte
+ .byte LOW__SR, \sr, \op_byte
.endif
.endm
@@ -32,9 +44,9 @@
.macro test_sr_mask sr, sym, mask
test \sr
- test_sr_op \sym, \mask & 1, rsr, 0x03, \sr
- test_sr_op \sym, \mask & 2, wsr, 0x13, \sr
- test_sr_op \sym, \mask & 4, xsr, 0x61, \sr
+ test_sr_op \sym, \mask & 1, rsr, HI_RSR, \sr
+ test_sr_op \sym, \mask & 2, wsr, HI_WSR, \sr
+ test_sr_op \sym, \mask & 4, xsr, HI_XSR, \sr
test_end
.endm
@@ -42,50 +54,183 @@
test_sr_mask \sr, \conf, 7
.endm
+#if XCHAL_HAVE_MAC16
test_sr acchi, 1
test_sr acclo, 1
+#else
+test_sr_mask /*acchi*/17, 0, 0
+test_sr_mask /*acclo*/16, 0, 0
+#endif
+
+#if XCHAL_HAVE_S32C1I && XCHAL_HW_VERSION >= 230000
+test_sr atomctl, 1
+#else
test_sr_mask /*atomctl*/99, 0, 0
+#endif
+
+#if XCHAL_HAVE_BOOLEANS
+test_sr br, 1
+#else
test_sr_mask /*br*/4, 0, 0
+#endif
+
test_sr_mask /*cacheattr*/98, 0, 0
+
+#if XCHAL_HAVE_CCOUNT
test_sr ccompare0, 1
test_sr ccount, 1
+#else
+test_sr_mask /*ccompare0*/240, 0, 0
+test_sr_mask /*ccount*/234, 0, 0
+#endif
+
+#if XCHAL_HAVE_CP
test_sr cpenable, 1
+#else
+test_sr_mask /*cpenable*/224, 0, 0
+#endif
+
+#if XCHAL_HAVE_DEBUG
+#if XCHAL_NUM_DBREAK
test_sr dbreaka0, 1
test_sr dbreakc0, 1
+#endif
test_sr_mask debugcause, 1, 1
+#else
+test_sr_mask /*dbreaka0*/144, 0, 0
+test_sr_mask /*dbreakc0*/160, 0, 0
+test_sr_mask /*debugcause*/233, 0, 0
+#endif
+
test_sr depc, 1
+
+#if XCHAL_HAVE_PTP_MMU
test_sr dtlbcfg, 1
+#else
+test_sr_mask /*dtlbcfg*/92, 0, 0
+#endif
+
test_sr epc1, 1
+
+#if XCHAL_NUM_INTLEVELS > 1
test_sr epc2, 1
test_sr eps2, 1
+#else
+test_sr_mask /*epc2*/178, 0, 0
+test_sr_mask /*eps2*/194, 0, 0
+#endif
+
test_sr exccause, 1
test_sr excsave1, 1
+
+#if XCHAL_NUM_INTLEVELS > 1
test_sr excsave2, 1
+#else
+test_sr_mask /*excsave2*/210, 0, 0
+#endif
+
test_sr excvaddr, 1
+
+#if XCHAL_HAVE_DEBUG
+#if XCHAL_NUM_IBREAK
test_sr ibreaka0, 1
test_sr ibreakenable, 1
+#endif
test_sr icount, 1
test_sr icountlevel, 1
+#else
+test_sr_mask /*ibreaka0*/128, 0, 0
+test_sr_mask /*ibreakenable*/96, 0, 0
+test_sr_mask /*icount*/236, 0, 0
+test_sr_mask /*icountlevel*/237, 0, 0
+#endif
+
test_sr_mask /*intclear*/227, 0, 2
test_sr_mask /*interrupt*/226, 0, 3
test_sr intenable, 1
+
+#if XCHAL_HAVE_PTP_MMU
test_sr itlbcfg, 1
+#else
+test_sr_mask /*itlbcfg*/91, 0, 0
+#endif
+
+#if XCHAL_HAVE_LOOPS
test_sr lbeg, 1
test_sr lcount, 1
test_sr lend, 1
+#else
+test_sr_mask /*lbeg*/0, 0, 0
+test_sr_mask /*lcount*/2, 0, 0
+test_sr_mask /*lend*/1, 0, 0
+#endif
+
+#if XCHAL_HAVE_ABSOLUTE_LITERALS
test_sr litbase, 1
+#else
+test_sr_mask /*litbase*/5, 0, 0
+#endif
+
+#if XCHAL_HAVE_MAC16
test_sr m0, 1
+#else
+test_sr_mask /*m0*/32, 0, 0
+#endif
+
+#if XCHAL_HW_VERSION >= 250000
+test_sr_mask /*memctl*/97, 0, 7
+#else
test_sr_mask /*memctl*/97, 0, 0
+#endif
+
+#if XCHAL_NUM_MISC_REGS
test_sr misc0, 1
+#else
+test_sr_mask /*misc0*/244, 0, 0
+#endif
+
+#if XCHAL_HAVE_PREFETCH
+test_sr prefctl, 1
+#else
test_sr_mask /*prefctl*/40, 0, 0
+#endif
+
+#if XCHAL_HAVE_PRID
test_sr_mask /*prid*/235, 0, 1
+#else
+test_sr_mask /*prid*/235, 0, 0
+#endif
+
test_sr ps, 1
+
+#if XCHAL_HAVE_PTP_MMU
test_sr ptevaddr, 1
test_sr rasid, 1
+#else
+test_sr_mask /*ptevaddr*/83, 0, 0
+test_sr_mask /*rasid*/90, 0, 0
+#endif
+
test_sr sar, 1
+
+#if XCHAL_HAVE_S32C1I
test_sr scompare1, 1
+#else
+test_sr_mask /*scompare1*/12, 0, 0
+#endif
+
+#if XCHAL_HAVE_VECBASE
test_sr vecbase, 1
+#else
+test_sr_mask /*vecbase*/231, 0, 0
+#endif
+
+#if XCHAL_HAVE_WINDOWED
test_sr windowbase, 1
test_sr windowstart, 1
+#else
+test_sr_mask /*windowbase*/72, 0, 0
+test_sr_mask /*windowstart*/73, 0, 0
+#endif
test_suite_end
diff --git a/tests/tcg/xtensa/test_timer.S b/tests/tcg/xtensa/test_timer.S
index 6cda71a..1ec8e20 100644
--- a/tests/tcg/xtensa/test_timer.S
+++ b/tests/tcg/xtensa/test_timer.S
@@ -2,6 +2,8 @@
#define CCOUNT_SHIFT 4
#define WAIT_LOOPS 20
+#define level1 kernel
+#define INTERRUPT_LEVEL(n) glue3(XCHAL_INT, n, _LEVEL)
.macro make_ccount_delta target, delta
rsr \delta, ccount
@@ -13,6 +15,8 @@
test_suite timer
+#if XCHAL_HAVE_CCOUNT
+
test ccount
rsr a3, ccount
rsr a4, ccount
@@ -32,14 +36,20 @@
assert ltu, a3, a4
test_end
+#if XCHAL_NUM_TIMERS
+
test ccount_update_deadline
movi a2, 0
wsr a2, intenable
rsr a2, interrupt
wsr a2, intclear
movi a2, 0
+#if XCHAL_NUM_TIMERS > 1
wsr a2, ccompare1
+#endif
+#if XCHAL_NUM_TIMERS > 2
wsr a2, ccompare2
+#endif
movi a2, 0x12345678
wsr a2, ccompare0
rsr a3, interrupt
@@ -59,8 +69,12 @@
rsr a2, interrupt
wsr a2, intclear
movi a2, 0
+#if XCHAL_NUM_TIMERS > 1
wsr a2, ccompare1
+#endif
+#if XCHAL_NUM_TIMERS > 2
wsr a2, ccompare2
+#endif
make_ccount_delta a2, a15
wsr a2, ccompare0
@@ -76,6 +90,7 @@
assert nei, a5, 0
test_end
+#if INTERRUPT_LEVEL(XCHAL_TIMER0_INTERRUPT) == 1
test ccompare0_interrupt
set_vector kernel, 2f
movi a2, 0
@@ -83,8 +98,12 @@
rsr a2, interrupt
wsr a2, intclear
movi a2, 0
+#if XCHAL_NUM_TIMERS > 1
wsr a2, ccompare1
+#endif
+#if XCHAL_NUM_TIMERS > 2
wsr a2, ccompare2
+#endif
movi a3, WAIT_LOOPS
make_ccount_delta a2, a15
@@ -104,16 +123,21 @@
rsr a2, exccause
assert eqi, a2, 4 /* LEVEL1_INTERRUPT_CAUSE */
test_end
+#endif
+
+#if XCHAL_NUM_TIMERS > 1
test ccompare1_interrupt
- set_vector level3, 2f
+ set_vector glue(level, INTERRUPT_LEVEL(XCHAL_TIMER1_INTERRUPT)), 2f
movi a2, 0
wsr a2, intenable
rsr a2, interrupt
wsr a2, intclear
movi a2, 0
wsr a2, ccompare0
+#if XCHAL_NUM_TIMERS > 2
wsr a2, ccompare2
+#endif
movi a3, WAIT_LOOPS
make_ccount_delta a2, a15
@@ -123,7 +147,7 @@
assert eqi, a2, 0
movi a2, 1 << XCHAL_TIMER1_INTERRUPT
wsr a2, intenable
- rsil a2, 2
+ rsil a2, INTERRUPT_LEVEL(XCHAL_TIMER1_INTERRUPT) - 1
loop a3, 1f
nop
1:
@@ -131,8 +155,11 @@
2:
test_end
+#endif
+#if XCHAL_NUM_TIMERS > 2
+
test ccompare2_interrupt
- set_vector level5, 2f
+ set_vector glue(level, INTERRUPT_LEVEL(XCHAL_TIMER2_INTERRUPT)), 2f
movi a2, 0
wsr a2, intenable
rsr a2, interrupt
@@ -149,7 +176,7 @@
assert eqi, a2, 0
movi a2, 1 << XCHAL_TIMER2_INTERRUPT
wsr a2, intenable
- rsil a2, 4
+ rsil a2, INTERRUPT_LEVEL(XCHAL_TIMER2_INTERRUPT) - 1
loop a3, 1f
nop
1:
@@ -157,6 +184,8 @@
2:
test_end
+#endif
+
test ccompare_interrupt_masked
set_vector kernel, 2f
movi a2, 0
@@ -164,11 +193,15 @@
rsr a2, interrupt
wsr a2, intclear
movi a2, 0
+#if XCHAL_NUM_TIMERS > 2
wsr a2, ccompare2
+#endif
movi a3, 2 * WAIT_LOOPS
make_ccount_delta a2, a15
+#if XCHAL_NUM_TIMERS > 1
wsr a2, ccompare1
+#endif
add a2, a2, a15
wsr a2, ccompare0
rsync
@@ -194,11 +227,15 @@
rsr a2, interrupt
wsr a2, intclear
movi a2, 0
+#if XCHAL_NUM_TIMERS > 2
wsr a2, ccompare2
+#endif
movi a3, 2 * WAIT_LOOPS
make_ccount_delta a2, a15
+#if XCHAL_NUM_TIMERS > 1
wsr a2, ccompare1
+#endif
add a2, a2, a15
wsr a2, ccompare0
rsync
@@ -214,4 +251,7 @@
assert eqi, a2, 4 /* LEVEL1_INTERRUPT_CAUSE */
test_end
+#endif
+#endif
+
test_suite_end
diff --git a/tests/tcg/xtensa/test_windowed.S b/tests/tcg/xtensa/test_windowed.S
index d851e8f..5ead90a 100644
--- a/tests/tcg/xtensa/test_windowed.S
+++ b/tests/tcg/xtensa/test_windowed.S
@@ -2,10 +2,12 @@
test_suite windowed
+#if XCHAL_HAVE_WINDOWED
+
.altmacro
.macro reset_window start
- movi a2, 0xff
+ movi a2, 0xffff
wsr a2, windowstart
rsync
movi a2, 0
@@ -105,7 +107,8 @@
movi a3, 0x4001f
assert eq, a2, a3
rsr a2, windowbase
- assert eqi, a2, 8 - ((\window) / 4)
+ movi a3, (XCHAL_NUM_AREGS - (\window)) / 4
+ assert eq, a2, a3
rsr a2, windowstart
assert eqi, a2, 1
rfwu
@@ -116,8 +119,8 @@
rsr a2, windowbase
assert eqi, a2, 0
rsr a2, windowstart
- assert bsi, a2, 0
- assert bsi, a2, 8 - ((\window) / 4)
+ assert bsi.l, a2, 0
+ assert bsi.l, a2, (XCHAL_NUM_AREGS - (\window)) / 4
.endm
test underflow
@@ -132,7 +135,7 @@
.macro retw_test window
- reset_window %(1 | (1 << (8 - (\window) / 4)))
+ reset_window %(1 | (1 << ((XCHAL_NUM_AREGS - \window) / 4)))
reset_ps
ssai 2
@@ -147,10 +150,11 @@
movi a3, 0x4000f
assert eq, a2, a3
rsr a2, windowbase
- assert eqi, a2, 8 - ((\window) / 4)
+ movi a3, (XCHAL_NUM_AREGS - (\window)) / 4
+ assert eq, a2, a3
rsr a2, windowstart
- assert bci, a2, 0
- assert bsi, a2, 8 - ((\window) / 4)
+ assert bci.l, a2, 0
+ assert bsi.l, a2, (XCHAL_NUM_AREGS - (\window)) / 4
.endm
test retw
@@ -180,7 +184,7 @@
set_vector kernel, 0
- reset_window 0x81
+ reset_window %(0x1 | (1 << ((XCHAL_NUM_AREGS / 4) - 1)))
reset_ps
movsp a2, a3
@@ -211,8 +215,16 @@
movi a3, 0x16
movi a7, 0x17
+#if XCHAL_NUM_AREGS == 32
movi a2, 0x44
wsr a2, windowstart
+#elif XCHAL_NUM_AREGS == 64
+ movi a2, 0x4004
+ wsr a2, windowstart
+ rotw -8
+#else
+#error XCHAL_NUM_AREGS unsupported
+#endif
rsync
movi a2, 0x10
@@ -350,4 +362,6 @@
all_entry_overflow_tests
test_end
+#endif
+
test_suite_end
diff --git a/tests/tcg/xtensa/vectors.S b/tests/tcg/xtensa/vectors.S
index 6a9cb3c..cd48cfb 100644
--- a/tests/tcg/xtensa/vectors.S
+++ b/tests/tcg/xtensa/vectors.S
@@ -2,10 +2,20 @@
.macro vector name
-.section .vector.\name
+.section .vector.\name, "ax"
+.global vector_\name
+vector_\name\():
j 1f
-.section .vector.\name\().text
+ .literal_position
1:
+ wsr a0, excsave1
+ movi a0, 1f
+ ret.n
+
+.section .vector.\name\().text, "ax"
+ .literal_position
+1:
+ rsr a0, excsave1
wsr a2, excsave1
movi a2, handler_\name
l32i a2, a2, 0
diff --git a/tests/test-announce-self.c b/tests/test-announce-self.c
new file mode 100644
index 0000000..1644d34
--- /dev/null
+++ b/tests/test-announce-self.c
@@ -0,0 +1,82 @@
+/*
+ * QTest testcase for qemu_announce_self
+ *
+ * Copyright (c) 2017 Red hat, Inc.
+ * Copyright (c) 2014 SUSE LINUX Products GmbH
+ *
+ * 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 "libqtest.h"
+#include "qapi/qmp/qdict.h"
+#include "qemu-common.h"
+#include "qemu/sockets.h"
+#include "qemu/iov.h"
+#include "libqos/libqos-pc.h"
+#include "libqos/libqos-spapr.h"
+
+#ifndef ETH_P_RARP
+#define ETH_P_RARP 0x8035
+#endif
+
+static QTestState *test_init(int socket)
+{
+ char *args;
+
+ args = g_strdup_printf("-netdev socket,fd=%d,id=hs0 -device "
+ "virtio-net-pci,netdev=hs0", socket);
+
+ return qtest_start(args);
+}
+
+
+static void test_announce(int socket)
+{
+ char buffer[60];
+ int len;
+ QDict *rsp;
+ int ret;
+ uint16_t *proto = (uint16_t *)&buffer[12];
+
+ rsp = qmp("{ 'execute' : 'announce-self', "
+ " 'arguments': {"
+ " 'initial': 50, 'max': 550,"
+ " 'rounds': 10, 'step': 50 } }");
+ assert(!qdict_haskey(rsp, "error"));
+ qobject_unref(rsp);
+
+ /* Catch the packet and make sure it's a RARP */
+ ret = qemu_recv(socket, &len, sizeof(len), 0);
+ g_assert_cmpint(ret, ==, sizeof(len));
+ len = ntohl(len);
+
+ ret = qemu_recv(socket, buffer, len, 0);
+ g_assert_cmpint(*proto, ==, htons(ETH_P_RARP));
+}
+
+static void setup(gconstpointer data)
+{
+ QTestState *qs;
+ void (*func) (int socket) = data;
+ int sv[2], ret;
+
+ ret = socketpair(PF_UNIX, SOCK_STREAM, 0, sv);
+ g_assert_cmpint(ret, !=, -1);
+
+ qs = test_init(sv[1]);
+ func(sv[0]);
+
+ /* End test */
+ close(sv[0]);
+ qtest_quit(qs);
+}
+
+int main(int argc, char **argv)
+{
+ g_test_init(&argc, &argv, NULL);
+ qtest_add_data_func("/virtio/net/test_announce_self", test_announce, setup);
+
+ return g_test_run();
+}
diff --git a/tests/test-authz-list.c b/tests/test-authz-list.c
new file mode 100644
index 0000000..24347a6
--- /dev/null
+++ b/tests/test-authz-list.c
@@ -0,0 +1,159 @@
+/*
+ * QEMU list file authorization object tests
+ *
+ * Copyright (c) 2018 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * 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 "authz/list.h"
+
+static void test_authz_default_deny(void)
+{
+ QAuthZList *auth = qauthz_list_new("auth0",
+ QAUTHZ_LIST_POLICY_DENY,
+ &error_abort);
+
+ g_assert(!qauthz_is_allowed(QAUTHZ(auth), "fred", &error_abort));
+
+ object_unparent(OBJECT(auth));
+}
+
+static void test_authz_default_allow(void)
+{
+ QAuthZList *auth = qauthz_list_new("auth0",
+ QAUTHZ_LIST_POLICY_ALLOW,
+ &error_abort);
+
+ g_assert(qauthz_is_allowed(QAUTHZ(auth), "fred", &error_abort));
+
+ object_unparent(OBJECT(auth));
+}
+
+static void test_authz_explicit_deny(void)
+{
+ QAuthZList *auth = qauthz_list_new("auth0",
+ QAUTHZ_LIST_POLICY_ALLOW,
+ &error_abort);
+
+ qauthz_list_append_rule(auth, "fred", QAUTHZ_LIST_POLICY_DENY,
+ QAUTHZ_LIST_FORMAT_EXACT, &error_abort);
+
+ g_assert(!qauthz_is_allowed(QAUTHZ(auth), "fred", &error_abort));
+
+ object_unparent(OBJECT(auth));
+}
+
+static void test_authz_explicit_allow(void)
+{
+ QAuthZList *auth = qauthz_list_new("auth0",
+ QAUTHZ_LIST_POLICY_DENY,
+ &error_abort);
+
+ qauthz_list_append_rule(auth, "fred", QAUTHZ_LIST_POLICY_ALLOW,
+ QAUTHZ_LIST_FORMAT_EXACT, &error_abort);
+
+ g_assert(qauthz_is_allowed(QAUTHZ(auth), "fred", &error_abort));
+
+ object_unparent(OBJECT(auth));
+}
+
+
+static void test_authz_complex(void)
+{
+ QAuthZList *auth = qauthz_list_new("auth0",
+ QAUTHZ_LIST_POLICY_DENY,
+ &error_abort);
+
+ qauthz_list_append_rule(auth, "fred", QAUTHZ_LIST_POLICY_ALLOW,
+ QAUTHZ_LIST_FORMAT_EXACT, &error_abort);
+ qauthz_list_append_rule(auth, "bob", QAUTHZ_LIST_POLICY_ALLOW,
+ QAUTHZ_LIST_FORMAT_EXACT, &error_abort);
+ qauthz_list_append_rule(auth, "dan", QAUTHZ_LIST_POLICY_DENY,
+ QAUTHZ_LIST_FORMAT_EXACT, &error_abort);
+ qauthz_list_append_rule(auth, "dan*", QAUTHZ_LIST_POLICY_ALLOW,
+ QAUTHZ_LIST_FORMAT_GLOB, &error_abort);
+
+ g_assert(qauthz_is_allowed(QAUTHZ(auth), "fred", &error_abort));
+ g_assert(qauthz_is_allowed(QAUTHZ(auth), "bob", &error_abort));
+ g_assert(!qauthz_is_allowed(QAUTHZ(auth), "dan", &error_abort));
+ g_assert(qauthz_is_allowed(QAUTHZ(auth), "danb", &error_abort));
+
+ object_unparent(OBJECT(auth));
+}
+
+static void test_authz_add_remove(void)
+{
+ QAuthZList *auth = qauthz_list_new("auth0",
+ QAUTHZ_LIST_POLICY_ALLOW,
+ &error_abort);
+
+ g_assert_cmpint(qauthz_list_append_rule(auth, "fred",
+ QAUTHZ_LIST_POLICY_ALLOW,
+ QAUTHZ_LIST_FORMAT_EXACT,
+ &error_abort),
+ ==, 0);
+ g_assert_cmpint(qauthz_list_append_rule(auth, "bob",
+ QAUTHZ_LIST_POLICY_ALLOW,
+ QAUTHZ_LIST_FORMAT_EXACT,
+ &error_abort),
+ ==, 1);
+ g_assert_cmpint(qauthz_list_append_rule(auth, "dan",
+ QAUTHZ_LIST_POLICY_DENY,
+ QAUTHZ_LIST_FORMAT_EXACT,
+ &error_abort),
+ ==, 2);
+ g_assert_cmpint(qauthz_list_append_rule(auth, "frank",
+ QAUTHZ_LIST_POLICY_DENY,
+ QAUTHZ_LIST_FORMAT_EXACT,
+ &error_abort),
+ ==, 3);
+
+ g_assert(!qauthz_is_allowed(QAUTHZ(auth), "dan", &error_abort));
+
+ g_assert_cmpint(qauthz_list_delete_rule(auth, "dan"),
+ ==, 2);
+
+ g_assert(qauthz_is_allowed(QAUTHZ(auth), "dan", &error_abort));
+
+ g_assert_cmpint(qauthz_list_insert_rule(auth, "dan",
+ QAUTHZ_LIST_POLICY_DENY,
+ QAUTHZ_LIST_FORMAT_EXACT,
+ 2,
+ &error_abort),
+ ==, 2);
+
+ g_assert(!qauthz_is_allowed(QAUTHZ(auth), "dan", &error_abort));
+
+ object_unparent(OBJECT(auth));
+}
+
+int main(int argc, char **argv)
+{
+ g_test_init(&argc, &argv, NULL);
+
+ module_call_init(MODULE_INIT_QOM);
+
+ g_test_add_func("/auth/list/default/deny", test_authz_default_deny);
+ g_test_add_func("/auth/list/default/allow", test_authz_default_allow);
+ g_test_add_func("/auth/list/explicit/deny", test_authz_explicit_deny);
+ g_test_add_func("/auth/list/explicit/allow", test_authz_explicit_allow);
+ g_test_add_func("/auth/list/complex", test_authz_complex);
+ g_test_add_func("/auth/list/add-remove", test_authz_add_remove);
+
+ return g_test_run();
+}
diff --git a/tests/test-authz-listfile.c b/tests/test-authz-listfile.c
new file mode 100644
index 0000000..1e452fe
--- /dev/null
+++ b/tests/test-authz-listfile.c
@@ -0,0 +1,195 @@
+/*
+ * QEMU list authorization object tests
+ *
+ * Copyright (c) 2018 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * 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 "qemu/main-loop.h"
+#include "authz/listfile.h"
+
+static char *workdir;
+
+static gchar *qemu_authz_listfile_test_save(const gchar *name,
+ const gchar *cfg)
+{
+ gchar *path = g_strdup_printf("%s/default-deny.cfg", workdir);
+ GError *gerr = NULL;
+
+ if (!g_file_set_contents(path, cfg, -1, &gerr)) {
+ g_printerr("Unable to save config %s: %s\n",
+ path, gerr->message);
+ g_error_free(gerr);
+ g_free(path);
+ rmdir(workdir);
+ abort();
+ }
+
+ return path;
+}
+
+static void test_authz_default_deny(void)
+{
+ gchar *file = qemu_authz_listfile_test_save(
+ "default-deny.cfg",
+ "{ \"policy\": \"deny\" }");
+ Error *local_err = NULL;
+
+ QAuthZListFile *auth = qauthz_list_file_new("auth0",
+ file, false,
+ &local_err);
+ unlink(file);
+ g_free(file);
+ g_assert(local_err == NULL);
+ g_assert(!qauthz_is_allowed(QAUTHZ(auth), "fred", &error_abort));
+
+ object_unparent(OBJECT(auth));
+}
+
+static void test_authz_default_allow(void)
+{
+ gchar *file = qemu_authz_listfile_test_save(
+ "default-allow.cfg",
+ "{ \"policy\": \"allow\" }");
+ Error *local_err = NULL;
+
+ QAuthZListFile *auth = qauthz_list_file_new("auth0",
+ file, false,
+ &local_err);
+ unlink(file);
+ g_free(file);
+ g_assert(local_err == NULL);
+ g_assert(qauthz_is_allowed(QAUTHZ(auth), "fred", &error_abort));
+
+ object_unparent(OBJECT(auth));
+}
+
+static void test_authz_explicit_deny(void)
+{
+ gchar *file = qemu_authz_listfile_test_save(
+ "explicit-deny.cfg",
+ "{ \"rules\": [ "
+ " { \"match\": \"fred\","
+ " \"policy\": \"deny\","
+ " \"format\": \"exact\" } ],"
+ " \"policy\": \"allow\" }");
+ Error *local_err = NULL;
+
+ QAuthZListFile *auth = qauthz_list_file_new("auth0",
+ file, false,
+ &local_err);
+ unlink(file);
+ g_free(file);
+ g_assert(local_err == NULL);
+
+ g_assert(!qauthz_is_allowed(QAUTHZ(auth), "fred", &error_abort));
+
+ object_unparent(OBJECT(auth));
+}
+
+static void test_authz_explicit_allow(void)
+{
+ gchar *file = qemu_authz_listfile_test_save(
+ "explicit-allow.cfg",
+ "{ \"rules\": [ "
+ " { \"match\": \"fred\","
+ " \"policy\": \"allow\","
+ " \"format\": \"exact\" } ],"
+ " \"policy\": \"deny\" }");
+ Error *local_err = NULL;
+
+ QAuthZListFile *auth = qauthz_list_file_new("auth0",
+ file, false,
+ &local_err);
+ unlink(file);
+ g_free(file);
+ g_assert(local_err == NULL);
+
+ g_assert(qauthz_is_allowed(QAUTHZ(auth), "fred", &error_abort));
+
+ object_unparent(OBJECT(auth));
+}
+
+
+static void test_authz_complex(void)
+{
+ gchar *file = qemu_authz_listfile_test_save(
+ "complex.cfg",
+ "{ \"rules\": [ "
+ " { \"match\": \"fred\","
+ " \"policy\": \"allow\","
+ " \"format\": \"exact\" },"
+ " { \"match\": \"bob\","
+ " \"policy\": \"allow\","
+ " \"format\": \"exact\" },"
+ " { \"match\": \"dan\","
+ " \"policy\": \"deny\","
+ " \"format\": \"exact\" },"
+ " { \"match\": \"dan*\","
+ " \"policy\": \"allow\","
+ " \"format\": \"glob\" } ],"
+ " \"policy\": \"deny\" }");
+
+ Error *local_err = NULL;
+
+ QAuthZListFile *auth = qauthz_list_file_new("auth0",
+ file, false,
+ &local_err);
+ unlink(file);
+ g_free(file);
+ g_assert(local_err == NULL);
+
+ g_assert(qauthz_is_allowed(QAUTHZ(auth), "fred", &error_abort));
+ g_assert(qauthz_is_allowed(QAUTHZ(auth), "bob", &error_abort));
+ g_assert(!qauthz_is_allowed(QAUTHZ(auth), "dan", &error_abort));
+ g_assert(qauthz_is_allowed(QAUTHZ(auth), "danb", &error_abort));
+
+ object_unparent(OBJECT(auth));
+}
+
+
+int main(int argc, char **argv)
+{
+ int ret;
+ GError *gerr = NULL;
+
+ g_test_init(&argc, &argv, NULL);
+
+ module_call_init(MODULE_INIT_QOM);
+
+ workdir = g_dir_make_tmp("qemu-test-authz-listfile-XXXXXX",
+ &gerr);
+ if (!workdir) {
+ g_printerr("Unable to create temporary dir: %s\n",
+ gerr->message);
+ g_error_free(gerr);
+ abort();
+ }
+
+ g_test_add_func("/auth/list/default/deny", test_authz_default_deny);
+ g_test_add_func("/auth/list/default/allow", test_authz_default_allow);
+ g_test_add_func("/auth/list/explicit/deny", test_authz_explicit_deny);
+ g_test_add_func("/auth/list/explicit/allow", test_authz_explicit_allow);
+ g_test_add_func("/auth/list/complex", test_authz_complex);
+
+ ret = g_test_run();
+
+ rmdir(workdir);
+ g_free(workdir);
+
+ return ret;
+}
diff --git a/tests/test-authz-pam.c b/tests/test-authz-pam.c
new file mode 100644
index 0000000..93d5ac8
--- /dev/null
+++ b/tests/test-authz-pam.c
@@ -0,0 +1,124 @@
+/*
+ * QEMU PAM authorization object tests
+ *
+ * Copyright (c) 2018 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * 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 "qapi/error.h"
+#include "authz/pamacct.h"
+
+#include <security/pam_appl.h>
+
+static bool failauth;
+
+/*
+ * These two functions are exported by libpam.so.
+ *
+ * By defining them again here, our impls are resolved
+ * by the linker instead of those in libpam.so
+ *
+ * The test suite is thus isolated from the host system
+ * PAM setup, so we can do predictable test scenarios
+ */
+int
+pam_start(const char *service_name, const char *user,
+ const struct pam_conv *pam_conversation,
+ pam_handle_t **pamh)
+{
+ failauth = true;
+ if (!g_str_equal(service_name, "qemu-vnc")) {
+ return PAM_AUTH_ERR;
+ }
+
+ if (g_str_equal(user, "fred")) {
+ failauth = false;
+ }
+
+ return PAM_SUCCESS;
+}
+
+
+int
+pam_acct_mgmt(pam_handle_t *pamh, int flags)
+{
+ if (failauth) {
+ return PAM_AUTH_ERR;
+ }
+
+ return PAM_SUCCESS;
+}
+
+
+static void test_authz_unknown_service(void)
+{
+ Error *local_err = NULL;
+ QAuthZPAM *auth = qauthz_pam_new("auth0",
+ "qemu-does-not-exist",
+ &error_abort);
+
+ g_assert_nonnull(auth);
+
+ g_assert_false(qauthz_is_allowed(QAUTHZ(auth), "fred", &local_err));
+
+ error_free_or_abort(&local_err);
+ object_unparent(OBJECT(auth));
+}
+
+
+static void test_authz_good_user(void)
+{
+ QAuthZPAM *auth = qauthz_pam_new("auth0",
+ "qemu-vnc",
+ &error_abort);
+
+ g_assert_nonnull(auth);
+
+ g_assert_true(qauthz_is_allowed(QAUTHZ(auth), "fred", &error_abort));
+
+ object_unparent(OBJECT(auth));
+}
+
+
+static void test_authz_bad_user(void)
+{
+ Error *local_err = NULL;
+ QAuthZPAM *auth = qauthz_pam_new("auth0",
+ "qemu-vnc",
+ &error_abort);
+
+ g_assert_nonnull(auth);
+
+ g_assert_false(qauthz_is_allowed(QAUTHZ(auth), "bob", &local_err));
+
+ error_free_or_abort(&local_err);
+ object_unparent(OBJECT(auth));
+}
+
+
+int main(int argc, char **argv)
+{
+ g_test_init(&argc, &argv, NULL);
+
+ module_call_init(MODULE_INIT_QOM);
+
+ g_test_add_func("/auth/pam/unknown-service", test_authz_unknown_service);
+ g_test_add_func("/auth/pam/good-user", test_authz_good_user);
+ g_test_add_func("/auth/pam/bad-user", test_authz_bad_user);
+
+ return g_test_run();
+}
diff --git a/tests/test-authz-simple.c b/tests/test-authz-simple.c
new file mode 100644
index 0000000..2cf14fb
--- /dev/null
+++ b/tests/test-authz-simple.c
@@ -0,0 +1,50 @@
+/*
+ * QEMU simple authorization object testing
+ *
+ * Copyright (c) 2018 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * 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 "qapi/error.h"
+
+#include "authz/simple.h"
+
+
+static void test_authz_simple(void)
+{
+ QAuthZSimple *authz = qauthz_simple_new("authz0",
+ "cthulu",
+ &error_abort);
+
+ g_assert(!qauthz_is_allowed(QAUTHZ(authz), "cthul", &error_abort));
+ g_assert(qauthz_is_allowed(QAUTHZ(authz), "cthulu", &error_abort));
+ g_assert(!qauthz_is_allowed(QAUTHZ(authz), "cthuluu", &error_abort));
+ g_assert(!qauthz_is_allowed(QAUTHZ(authz), "fred", &error_abort));
+
+ object_unparent(OBJECT(authz));
+}
+
+
+int main(int argc, char **argv)
+{
+ g_test_init(&argc, &argv, NULL);
+ module_call_init(MODULE_INIT_QOM);
+
+ g_test_add_func("/authz/simple", test_authz_simple);
+
+ return g_test_run();
+}
diff --git a/tests/test-bdrv-drain.c b/tests/test-bdrv-drain.c
index ee1740f..eda9075 100644
--- a/tests/test-bdrv-drain.c
+++ b/tests/test-bdrv-drain.c
@@ -204,12 +204,7 @@
BlockAIOCB *acb;
int aio_ret;
- QEMUIOVector qiov;
- struct iovec iov = {
- .iov_base = NULL,
- .iov_len = 0,
- };
- qemu_iovec_init_external(&qiov, &iov, 1);
+ QEMUIOVector qiov = QEMU_IOVEC_INIT_BUF(qiov, NULL, 0);
blk = blk_new(BLK_PERM_ALL, BLK_PERM_ALL);
bs = bdrv_new_open_driver(&bdrv_test, "test-node", BDRV_O_RDWR,
@@ -670,12 +665,7 @@
AioContext *ctx_a = iothread_get_aio_context(a);
AioContext *ctx_b = iothread_get_aio_context(b);
- QEMUIOVector qiov;
- struct iovec iov = {
- .iov_base = NULL,
- .iov_len = 0,
- };
- qemu_iovec_init_external(&qiov, &iov, 1);
+ QEMUIOVector qiov = QEMU_IOVEC_INIT_BUF(qiov, NULL, 0);
/* bdrv_drain_all() may only be called from the main loop thread */
if (drain_type == BDRV_DRAIN_ALL && drain_thread != 0) {
@@ -1148,13 +1138,7 @@
BlockDriverState *bs = blk_bs(blk);
BDRVTestTopState *tts = bs->opaque;
void *buffer = g_malloc(65536);
- QEMUIOVector qiov;
- struct iovec iov = {
- .iov_base = buffer,
- .iov_len = 65536,
- };
-
- qemu_iovec_init_external(&qiov, &iov, 1);
+ QEMUIOVector qiov = QEMU_IOVEC_INIT_BUF(qiov, buffer, 65536);
/* Pretend some internal write operation from parent to child.
* Important: We have to read from the child, not from the parent!
@@ -1365,12 +1349,7 @@
BdrvChild *child_a, *child_b;
BlockAIOCB *acb;
- QEMUIOVector qiov;
- struct iovec iov = {
- .iov_base = NULL,
- .iov_len = 0,
- };
- qemu_iovec_init_external(&qiov, &iov, 1);
+ QEMUIOVector qiov = QEMU_IOVEC_INIT_BUF(qiov, NULL, 0);
if (!by_parent_cb) {
detach_by_driver_cb_role = child_file;
@@ -1522,6 +1501,36 @@
blk_unref(blk);
}
+static void test_set_aio_context(void)
+{
+ BlockDriverState *bs;
+ IOThread *a = iothread_new();
+ IOThread *b = iothread_new();
+ AioContext *ctx_a = iothread_get_aio_context(a);
+ AioContext *ctx_b = iothread_get_aio_context(b);
+
+ bs = bdrv_new_open_driver(&bdrv_test, "test-node", BDRV_O_RDWR,
+ &error_abort);
+
+ bdrv_drained_begin(bs);
+ bdrv_set_aio_context(bs, ctx_a);
+
+ aio_context_acquire(ctx_a);
+ bdrv_drained_end(bs);
+
+ bdrv_drained_begin(bs);
+ bdrv_set_aio_context(bs, ctx_b);
+ aio_context_release(ctx_a);
+ aio_context_acquire(ctx_b);
+ bdrv_set_aio_context(bs, qemu_get_aio_context());
+ aio_context_release(ctx_b);
+ bdrv_drained_end(bs);
+
+ bdrv_unref(bs);
+ iothread_join(a);
+ iothread_join(b);
+}
+
int main(int argc, char **argv)
{
int ret;
@@ -1603,6 +1612,8 @@
g_test_add_func("/bdrv-drain/attach/drain", test_append_to_drained);
+ g_test_add_func("/bdrv-drain/set_aio_context", test_set_aio_context);
+
ret = g_test_run();
qemu_event_destroy(&done_event);
return ret;
diff --git a/tests/test-bdrv-graph-mod.c b/tests/test-bdrv-graph-mod.c
new file mode 100644
index 0000000..458dfa6
--- /dev/null
+++ b/tests/test-bdrv-graph-mod.c
@@ -0,0 +1,198 @@
+/*
+ * Block node graph modifications tests
+ *
+ * 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/>.
+ *
+ */
+
+#include "qemu/osdep.h"
+#include "qapi/error.h"
+#include "block/block_int.h"
+#include "sysemu/block-backend.h"
+
+static BlockDriver bdrv_pass_through = {
+ .format_name = "pass-through",
+ .bdrv_child_perm = bdrv_filter_default_perms,
+};
+
+static void no_perm_default_perms(BlockDriverState *bs, BdrvChild *c,
+ const BdrvChildRole *role,
+ BlockReopenQueue *reopen_queue,
+ uint64_t perm, uint64_t shared,
+ uint64_t *nperm, uint64_t *nshared)
+{
+ *nperm = 0;
+ *nshared = BLK_PERM_ALL;
+}
+
+static BlockDriver bdrv_no_perm = {
+ .format_name = "no-perm",
+ .bdrv_child_perm = no_perm_default_perms,
+};
+
+static BlockDriverState *no_perm_node(const char *name)
+{
+ return bdrv_new_open_driver(&bdrv_no_perm, name, BDRV_O_RDWR, &error_abort);
+}
+
+static BlockDriverState *pass_through_node(const char *name)
+{
+ return bdrv_new_open_driver(&bdrv_pass_through, name,
+ BDRV_O_RDWR, &error_abort);
+}
+
+/*
+ * test_update_perm_tree
+ *
+ * When checking node for a possibility to update permissions, it's subtree
+ * should be correctly checked too. New permissions for each node should be
+ * calculated and checked in context of permissions of other nodes. If we
+ * check new permissions of the node only in context of old permissions of
+ * its neighbors, we can finish up with wrong permission graph.
+ *
+ * This test firstly create the following graph:
+ * +--------+
+ * | root |
+ * +--------+
+ * |
+ * | perm: write, read
+ * | shared: except write
+ * v
+ * +-------------------+ +----------------+
+ * | passtrough filter |---------->| null-co node |
+ * +-------------------+ +----------------+
+ *
+ *
+ * and then, tries to append filter under node. Expected behavior: fail.
+ * Otherwise we'll get the following picture, with two BdrvChild'ren, having
+ * write permission to one node, without actually sharing it.
+ *
+ * +--------+
+ * | root |
+ * +--------+
+ * |
+ * | perm: write, read
+ * | shared: except write
+ * v
+ * +-------------------+
+ * | passtrough filter |
+ * +-------------------+
+ * | |
+ * perm: write, read | | perm: write, read
+ * shared: except write | | shared: except write
+ * v v
+ * +----------------+
+ * | null co node |
+ * +----------------+
+ */
+static void test_update_perm_tree(void)
+{
+ Error *local_err = NULL;
+
+ BlockBackend *root = blk_new(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");
+
+ blk_insert_bs(root, bs, &error_abort);
+
+ bdrv_attach_child(filter, bs, "child", &child_file, &error_abort);
+
+ bdrv_append(filter, bs, &local_err);
+
+ g_assert_nonnull(local_err);
+
+ bdrv_unref(bs);
+ blk_unref(root);
+}
+
+/*
+ * test_should_update_child
+ *
+ * Test that bdrv_replace_node, and concretely should_update_child
+ * do the right thing, i.e. not creating loops on the graph.
+ *
+ * The test does the following:
+ * 1. initial graph:
+ *
+ * +------+ +--------+
+ * | root | | filter |
+ * +------+ +--------+
+ * | |
+ * root| target|
+ * v v
+ * +------+ +--------+
+ * | node |<---------| target |
+ * +------+ backing +--------+
+ *
+ * 2. Append @filter above @node. If should_update_child works correctly,
+ * it understands, that backing child of @target should not be updated,
+ * as it will create a loop on node graph. Resulting picture should
+ * be the left one, not the right:
+ *
+ * +------+ +------+
+ * | root | | root |
+ * +------+ +------+
+ * | |
+ * root| root|
+ * v v
+ * +--------+ target +--------+ target
+ * | filter |--------------+ | filter |--------------+
+ * +--------+ | +--------+ |
+ * | | | ^ v
+ * backing| | backing| | +--------+
+ * v v | +-----------| target |
+ * +------+ +--------+ v backing +--------+
+ * | node |<---------| target | +------+
+ * +------+ backing +--------+ | node |
+ * +------+
+ *
+ * (good picture) (bad picture)
+ *
+ */
+static void test_should_update_child(void)
+{
+ BlockBackend *root = blk_new(0, BLK_PERM_ALL);
+ BlockDriverState *bs = no_perm_node("node");
+ BlockDriverState *filter = no_perm_node("filter");
+ BlockDriverState *target = no_perm_node("target");
+
+ blk_insert_bs(root, bs, &error_abort);
+
+ bdrv_set_backing_hd(target, bs, &error_abort);
+
+ g_assert(target->backing->bs == bs);
+ bdrv_attach_child(filter, target, "target", &child_file, &error_abort);
+ bdrv_append(filter, bs, &error_abort);
+ g_assert(target->backing->bs == bs);
+
+ bdrv_unref(bs);
+ blk_unref(root);
+}
+
+int main(int argc, char *argv[])
+{
+ bdrv_init();
+ qemu_init_main_loop(&error_abort);
+
+ g_test_init(&argc, &argv, NULL);
+
+ g_test_add_func("/bdrv-graph-mod/update-perm-tree", test_update_perm_tree);
+ g_test_add_func("/bdrv-graph-mod/should-update-child",
+ test_should_update_child);
+
+ return g_test_run();
+}
diff --git a/tests/test-clone-visitor.c b/tests/test-clone-visitor.c
index 9aeaf86..5e1e8b2 100644
--- a/tests/test-clone-visitor.c
+++ b/tests/test-clone-visitor.c
@@ -63,7 +63,7 @@
qapi_free_AltEnumBool(s_dst);
}
-static void test_clone_native_list(void)
+static void test_clone_list_union(void)
{
uint8List *src, *dst;
uint8List *tmp = NULL;
@@ -102,18 +102,18 @@
static void test_clone_complex1(void)
{
- UserDefNativeListUnion *src, *dst;
+ UserDefListUnion *src, *dst;
- src = g_new0(UserDefNativeListUnion, 1);
- src->type = USER_DEF_NATIVE_LIST_UNION_KIND_STRING;
+ src = g_new0(UserDefListUnion, 1);
+ src->type = USER_DEF_LIST_UNION_KIND_STRING;
- dst = QAPI_CLONE(UserDefNativeListUnion, src);
+ dst = QAPI_CLONE(UserDefListUnion, src);
g_assert(dst);
g_assert_cmpint(dst->type, ==, src->type);
g_assert(!dst->u.string.data);
- qapi_free_UserDefNativeListUnion(src);
- qapi_free_UserDefNativeListUnion(dst);
+ qapi_free_UserDefListUnion(src);
+ qapi_free_UserDefListUnion(dst);
}
static void test_clone_complex2(void)
@@ -192,7 +192,7 @@
g_test_add_func("/visitor/clone/struct", test_clone_struct);
g_test_add_func("/visitor/clone/alternate", test_clone_alternate);
- g_test_add_func("/visitor/clone/native_list", test_clone_native_list);
+ g_test_add_func("/visitor/clone/list_union", test_clone_list_union);
g_test_add_func("/visitor/clone/empty", test_clone_empty);
g_test_add_func("/visitor/clone/complex1", test_clone_complex1);
g_test_add_func("/visitor/clone/complex2", test_clone_complex2);
diff --git a/tests/test-crypto-tlssession.c b/tests/test-crypto-tlssession.c
index 6fa9950..15212ec 100644
--- a/tests/test-crypto-tlssession.c
+++ b/tests/test-crypto-tlssession.c
@@ -28,7 +28,7 @@
#include "qom/object_interfaces.h"
#include "qapi/error.h"
#include "qemu/sockets.h"
-#include "qemu/acl.h"
+#include "authz/list.h"
#ifdef QCRYPTO_HAVE_TLS_TEST_SUPPORT
@@ -229,7 +229,7 @@
QCryptoTLSCreds *serverCreds;
QCryptoTLSSession *clientSess = NULL;
QCryptoTLSSession *serverSess = NULL;
- qemu_acl *acl;
+ QAuthZList *auth;
const char * const *wildcards;
int channel[2];
bool clientShake = false;
@@ -285,11 +285,15 @@
SERVER_CERT_DIR);
g_assert(serverCreds != NULL);
- acl = qemu_acl_init("tlssessionacl");
- qemu_acl_reset(acl);
+ auth = qauthz_list_new("tlssessionacl",
+ QAUTHZ_LIST_POLICY_DENY,
+ &error_abort);
wildcards = data->wildcards;
while (wildcards && *wildcards) {
- qemu_acl_append(acl, 0, *wildcards);
+ qauthz_list_append_rule(auth, *wildcards,
+ QAUTHZ_LIST_POLICY_ALLOW,
+ QAUTHZ_LIST_FORMAT_GLOB,
+ &error_abort);
wildcards++;
}
@@ -377,6 +381,7 @@
object_unparent(OBJECT(serverCreds));
object_unparent(OBJECT(clientCreds));
+ object_unparent(OBJECT(auth));
qcrypto_tls_session_free(serverSess);
qcrypto_tls_session_free(clientSess);
diff --git a/tests/test-hmp.c b/tests/test-hmp.c
index 1a3a9c5..8c49d2f 100644
--- a/tests/test-hmp.c
+++ b/tests/test-hmp.c
@@ -20,6 +20,7 @@
static int verbose;
static const char *hmp_cmds[] = {
+ "announce_self",
"boot_set ndc",
"chardev-add null,id=testchardev1",
"chardev-send-break testchardev1",
diff --git a/tests/test-io-channel-tls.c b/tests/test-io-channel-tls.c
index 4900c6d..43b707e 100644
--- a/tests/test-io-channel-tls.c
+++ b/tests/test-io-channel-tls.c
@@ -29,8 +29,8 @@
#include "io-channel-helpers.h"
#include "crypto/init.h"
#include "crypto/tlscredsx509.h"
-#include "qemu/acl.h"
#include "qapi/error.h"
+#include "authz/list.h"
#include "qom/object_interfaces.h"
#ifdef QCRYPTO_HAVE_TLS_TEST_SUPPORT
@@ -113,7 +113,7 @@
QIOChannelTLS *serverChanTLS;
QIOChannelSocket *clientChanSock;
QIOChannelSocket *serverChanSock;
- qemu_acl *acl;
+ QAuthZList *auth;
const char * const *wildcards;
int channel[2];
struct QIOChannelTLSHandshakeData clientHandshake = { false, false };
@@ -161,11 +161,15 @@
SERVER_CERT_DIR);
g_assert(serverCreds != NULL);
- acl = qemu_acl_init("channeltlsacl");
- qemu_acl_reset(acl);
+ auth = qauthz_list_new("channeltlsacl",
+ QAUTHZ_LIST_POLICY_DENY,
+ &error_abort);
wildcards = data->wildcards;
while (wildcards && *wildcards) {
- qemu_acl_append(acl, 0, *wildcards);
+ qauthz_list_append_rule(auth, *wildcards,
+ QAUTHZ_LIST_POLICY_ALLOW,
+ QAUTHZ_LIST_FORMAT_GLOB,
+ &error_abort);
wildcards++;
}
@@ -253,6 +257,8 @@
object_unref(OBJECT(serverChanSock));
object_unref(OBJECT(clientChanSock));
+ object_unparent(OBJECT(auth));
+
close(channel[0]);
close(channel[1]);
}
diff --git a/tests/test-qmp-cmds.c b/tests/test-qmp-cmds.c
index 481cb06..630b1b9 100644
--- a/tests/test-qmp-cmds.c
+++ b/tests/test-qmp-cmds.c
@@ -87,7 +87,7 @@
{
}
-void qmp_boxed_union(UserDefNativeListUnion *arg, Error **errp)
+void qmp_boxed_union(UserDefListUnion *arg, Error **errp)
{
}
diff --git a/tests/test-qobject-input-visitor.c b/tests/test-qobject-input-visitor.c
index 609334a..6bacabf 100644
--- a/tests/test-qobject-input-visitor.c
+++ b/tests/test-qobject-input-visitor.c
@@ -686,11 +686,11 @@
qapi_free_AltEnumInt(asi);
}
-static void test_native_list_integer_helper(TestInputVisitorData *data,
- const void *unused,
- UserDefNativeListUnionKind kind)
+static void test_list_union_integer_helper(TestInputVisitorData *data,
+ const void *unused,
+ UserDefListUnionKind kind)
{
- UserDefNativeListUnion *cvalue = NULL;
+ UserDefListUnion *cvalue = NULL;
Visitor *v;
GString *gstr_list = g_string_new("");
GString *gstr_union = g_string_new("");
@@ -703,16 +703,16 @@
}
}
g_string_append_printf(gstr_union, "{ 'type': '%s', 'data': [ %s ] }",
- UserDefNativeListUnionKind_str(kind),
+ UserDefListUnionKind_str(kind),
gstr_list->str);
v = visitor_input_test_init_raw(data, gstr_union->str);
- visit_type_UserDefNativeListUnion(v, NULL, &cvalue, &error_abort);
+ visit_type_UserDefListUnion(v, NULL, &cvalue, &error_abort);
g_assert(cvalue != NULL);
g_assert_cmpint(cvalue->type, ==, kind);
switch (kind) {
- case USER_DEF_NATIVE_LIST_UNION_KIND_INTEGER: {
+ case USER_DEF_LIST_UNION_KIND_INTEGER: {
intList *elem = NULL;
for (i = 0, elem = cvalue->u.integer.data;
elem; elem = elem->next, i++) {
@@ -720,56 +720,56 @@
}
break;
}
- case USER_DEF_NATIVE_LIST_UNION_KIND_S8: {
+ case USER_DEF_LIST_UNION_KIND_S8: {
int8List *elem = NULL;
for (i = 0, elem = cvalue->u.s8.data; elem; elem = elem->next, i++) {
g_assert_cmpint(elem->value, ==, i);
}
break;
}
- case USER_DEF_NATIVE_LIST_UNION_KIND_S16: {
+ case USER_DEF_LIST_UNION_KIND_S16: {
int16List *elem = NULL;
for (i = 0, elem = cvalue->u.s16.data; elem; elem = elem->next, i++) {
g_assert_cmpint(elem->value, ==, i);
}
break;
}
- case USER_DEF_NATIVE_LIST_UNION_KIND_S32: {
+ case USER_DEF_LIST_UNION_KIND_S32: {
int32List *elem = NULL;
for (i = 0, elem = cvalue->u.s32.data; elem; elem = elem->next, i++) {
g_assert_cmpint(elem->value, ==, i);
}
break;
}
- case USER_DEF_NATIVE_LIST_UNION_KIND_S64: {
+ case USER_DEF_LIST_UNION_KIND_S64: {
int64List *elem = NULL;
for (i = 0, elem = cvalue->u.s64.data; elem; elem = elem->next, i++) {
g_assert_cmpint(elem->value, ==, i);
}
break;
}
- case USER_DEF_NATIVE_LIST_UNION_KIND_U8: {
+ case USER_DEF_LIST_UNION_KIND_U8: {
uint8List *elem = NULL;
for (i = 0, elem = cvalue->u.u8.data; elem; elem = elem->next, i++) {
g_assert_cmpint(elem->value, ==, i);
}
break;
}
- case USER_DEF_NATIVE_LIST_UNION_KIND_U16: {
+ case USER_DEF_LIST_UNION_KIND_U16: {
uint16List *elem = NULL;
for (i = 0, elem = cvalue->u.u16.data; elem; elem = elem->next, i++) {
g_assert_cmpint(elem->value, ==, i);
}
break;
}
- case USER_DEF_NATIVE_LIST_UNION_KIND_U32: {
+ case USER_DEF_LIST_UNION_KIND_U32: {
uint32List *elem = NULL;
for (i = 0, elem = cvalue->u.u32.data; elem; elem = elem->next, i++) {
g_assert_cmpint(elem->value, ==, i);
}
break;
}
- case USER_DEF_NATIVE_LIST_UNION_KIND_U64: {
+ case USER_DEF_LIST_UNION_KIND_U64: {
uint64List *elem = NULL;
for (i = 0, elem = cvalue->u.u64.data; elem; elem = elem->next, i++) {
g_assert_cmpint(elem->value, ==, i);
@@ -782,76 +782,76 @@
g_string_free(gstr_union, true);
g_string_free(gstr_list, true);
- qapi_free_UserDefNativeListUnion(cvalue);
+ qapi_free_UserDefListUnion(cvalue);
}
-static void test_visitor_in_native_list_int(TestInputVisitorData *data,
+static void test_visitor_in_list_union_int(TestInputVisitorData *data,
+ const void *unused)
+{
+ test_list_union_integer_helper(data, unused,
+ USER_DEF_LIST_UNION_KIND_INTEGER);
+}
+
+static void test_visitor_in_list_union_int8(TestInputVisitorData *data,
const void *unused)
{
- test_native_list_integer_helper(data, unused,
- USER_DEF_NATIVE_LIST_UNION_KIND_INTEGER);
+ test_list_union_integer_helper(data, unused,
+ USER_DEF_LIST_UNION_KIND_S8);
}
-static void test_visitor_in_native_list_int8(TestInputVisitorData *data,
+static void test_visitor_in_list_union_int16(TestInputVisitorData *data,
const void *unused)
{
- test_native_list_integer_helper(data, unused,
- USER_DEF_NATIVE_LIST_UNION_KIND_S8);
+ test_list_union_integer_helper(data, unused,
+ USER_DEF_LIST_UNION_KIND_S16);
}
-static void test_visitor_in_native_list_int16(TestInputVisitorData *data,
- const void *unused)
-{
- test_native_list_integer_helper(data, unused,
- USER_DEF_NATIVE_LIST_UNION_KIND_S16);
-}
-
-static void test_visitor_in_native_list_int32(TestInputVisitorData *data,
- const void *unused)
-{
- test_native_list_integer_helper(data, unused,
- USER_DEF_NATIVE_LIST_UNION_KIND_S32);
-}
-
-static void test_visitor_in_native_list_int64(TestInputVisitorData *data,
- const void *unused)
-{
- test_native_list_integer_helper(data, unused,
- USER_DEF_NATIVE_LIST_UNION_KIND_S64);
-}
-
-static void test_visitor_in_native_list_uint8(TestInputVisitorData *data,
+static void test_visitor_in_list_union_int32(TestInputVisitorData *data,
const void *unused)
{
- test_native_list_integer_helper(data, unused,
- USER_DEF_NATIVE_LIST_UNION_KIND_U8);
+ test_list_union_integer_helper(data, unused,
+ USER_DEF_LIST_UNION_KIND_S32);
}
-static void test_visitor_in_native_list_uint16(TestInputVisitorData *data,
- const void *unused)
+static void test_visitor_in_list_union_int64(TestInputVisitorData *data,
+ const void *unused)
{
- test_native_list_integer_helper(data, unused,
- USER_DEF_NATIVE_LIST_UNION_KIND_U16);
+ test_list_union_integer_helper(data, unused,
+ USER_DEF_LIST_UNION_KIND_S64);
}
-static void test_visitor_in_native_list_uint32(TestInputVisitorData *data,
- const void *unused)
+static void test_visitor_in_list_union_uint8(TestInputVisitorData *data,
+ const void *unused)
{
- test_native_list_integer_helper(data, unused,
- USER_DEF_NATIVE_LIST_UNION_KIND_U32);
+ test_list_union_integer_helper(data, unused,
+ USER_DEF_LIST_UNION_KIND_U8);
}
-static void test_visitor_in_native_list_uint64(TestInputVisitorData *data,
- const void *unused)
+static void test_visitor_in_list_union_uint16(TestInputVisitorData *data,
+ const void *unused)
{
- test_native_list_integer_helper(data, unused,
- USER_DEF_NATIVE_LIST_UNION_KIND_U64);
+ test_list_union_integer_helper(data, unused,
+ USER_DEF_LIST_UNION_KIND_U16);
}
-static void test_visitor_in_native_list_bool(TestInputVisitorData *data,
+static void test_visitor_in_list_union_uint32(TestInputVisitorData *data,
+ const void *unused)
+{
+ test_list_union_integer_helper(data, unused,
+ USER_DEF_LIST_UNION_KIND_U32);
+}
+
+static void test_visitor_in_list_union_uint64(TestInputVisitorData *data,
+ const void *unused)
+{
+ test_list_union_integer_helper(data, unused,
+ USER_DEF_LIST_UNION_KIND_U64);
+}
+
+static void test_visitor_in_list_union_bool(TestInputVisitorData *data,
const void *unused)
{
- UserDefNativeListUnion *cvalue = NULL;
+ UserDefListUnion *cvalue = NULL;
boolList *elem = NULL;
Visitor *v;
GString *gstr_list = g_string_new("");
@@ -869,9 +869,9 @@
gstr_list->str);
v = visitor_input_test_init_raw(data, gstr_union->str);
- visit_type_UserDefNativeListUnion(v, NULL, &cvalue, &error_abort);
+ visit_type_UserDefListUnion(v, NULL, &cvalue, &error_abort);
g_assert(cvalue != NULL);
- g_assert_cmpint(cvalue->type, ==, USER_DEF_NATIVE_LIST_UNION_KIND_BOOLEAN);
+ g_assert_cmpint(cvalue->type, ==, USER_DEF_LIST_UNION_KIND_BOOLEAN);
for (i = 0, elem = cvalue->u.boolean.data; elem; elem = elem->next, i++) {
g_assert_cmpint(elem->value, ==, (i % 3 == 0) ? 1 : 0);
@@ -879,13 +879,13 @@
g_string_free(gstr_union, true);
g_string_free(gstr_list, true);
- qapi_free_UserDefNativeListUnion(cvalue);
+ qapi_free_UserDefListUnion(cvalue);
}
-static void test_visitor_in_native_list_string(TestInputVisitorData *data,
- const void *unused)
+static void test_visitor_in_list_union_string(TestInputVisitorData *data,
+ const void *unused)
{
- UserDefNativeListUnion *cvalue = NULL;
+ UserDefListUnion *cvalue = NULL;
strList *elem = NULL;
Visitor *v;
GString *gstr_list = g_string_new("");
@@ -902,9 +902,9 @@
gstr_list->str);
v = visitor_input_test_init_raw(data, gstr_union->str);
- visit_type_UserDefNativeListUnion(v, NULL, &cvalue, &error_abort);
+ visit_type_UserDefListUnion(v, NULL, &cvalue, &error_abort);
g_assert(cvalue != NULL);
- g_assert_cmpint(cvalue->type, ==, USER_DEF_NATIVE_LIST_UNION_KIND_STRING);
+ g_assert_cmpint(cvalue->type, ==, USER_DEF_LIST_UNION_KIND_STRING);
for (i = 0, elem = cvalue->u.string.data; elem; elem = elem->next, i++) {
gchar str[8];
@@ -914,15 +914,15 @@
g_string_free(gstr_union, true);
g_string_free(gstr_list, true);
- qapi_free_UserDefNativeListUnion(cvalue);
+ qapi_free_UserDefListUnion(cvalue);
}
#define DOUBLE_STR_MAX 16
-static void test_visitor_in_native_list_number(TestInputVisitorData *data,
- const void *unused)
+static void test_visitor_in_list_union_number(TestInputVisitorData *data,
+ const void *unused)
{
- UserDefNativeListUnion *cvalue = NULL;
+ UserDefListUnion *cvalue = NULL;
numberList *elem = NULL;
Visitor *v;
GString *gstr_list = g_string_new("");
@@ -939,9 +939,9 @@
gstr_list->str);
v = visitor_input_test_init_raw(data, gstr_union->str);
- visit_type_UserDefNativeListUnion(v, NULL, &cvalue, &error_abort);
+ visit_type_UserDefListUnion(v, NULL, &cvalue, &error_abort);
g_assert(cvalue != NULL);
- g_assert_cmpint(cvalue->type, ==, USER_DEF_NATIVE_LIST_UNION_KIND_NUMBER);
+ g_assert_cmpint(cvalue->type, ==, USER_DEF_LIST_UNION_KIND_NUMBER);
for (i = 0, elem = cvalue->u.number.data; elem; elem = elem->next, i++) {
GString *double_expected = g_string_new("");
@@ -957,7 +957,7 @@
g_string_free(gstr_union, true);
g_string_free(gstr_list, true);
- qapi_free_UserDefNativeListUnion(cvalue);
+ qapi_free_UserDefListUnion(cvalue);
}
static void input_visitor_test_add(const char *testpath,
@@ -1192,17 +1192,17 @@
visit_end_list(v, NULL);
}
-static void test_visitor_in_fail_union_native_list(TestInputVisitorData *data,
- const void *unused)
+static void test_visitor_in_fail_union_list(TestInputVisitorData *data,
+ const void *unused)
{
- UserDefNativeListUnion *tmp = NULL;
+ UserDefListUnion *tmp = NULL;
Error *err = NULL;
Visitor *v;
v = visitor_input_test_init(data,
"{ 'type': 'integer', 'data' : [ 'string' ] }");
- visit_type_UserDefNativeListUnion(v, NULL, &tmp, &err);
+ visit_type_UserDefListUnion(v, NULL, &tmp, &err);
error_free_or_abort(&err);
g_assert(!tmp);
}
@@ -1335,30 +1335,30 @@
NULL, test_visitor_in_wrong_type);
input_visitor_test_add("/visitor/input/alternate-number",
NULL, test_visitor_in_alternate_number);
- input_visitor_test_add("/visitor/input/native_list/int",
- NULL, test_visitor_in_native_list_int);
- input_visitor_test_add("/visitor/input/native_list/int8",
- NULL, test_visitor_in_native_list_int8);
- input_visitor_test_add("/visitor/input/native_list/int16",
- NULL, test_visitor_in_native_list_int16);
- input_visitor_test_add("/visitor/input/native_list/int32",
- NULL, test_visitor_in_native_list_int32);
- input_visitor_test_add("/visitor/input/native_list/int64",
- NULL, test_visitor_in_native_list_int64);
- input_visitor_test_add("/visitor/input/native_list/uint8",
- NULL, test_visitor_in_native_list_uint8);
- input_visitor_test_add("/visitor/input/native_list/uint16",
- NULL, test_visitor_in_native_list_uint16);
- input_visitor_test_add("/visitor/input/native_list/uint32",
- NULL, test_visitor_in_native_list_uint32);
- input_visitor_test_add("/visitor/input/native_list/uint64",
- NULL, test_visitor_in_native_list_uint64);
- input_visitor_test_add("/visitor/input/native_list/bool",
- NULL, test_visitor_in_native_list_bool);
- input_visitor_test_add("/visitor/input/native_list/str",
- NULL, test_visitor_in_native_list_string);
- input_visitor_test_add("/visitor/input/native_list/number",
- NULL, test_visitor_in_native_list_number);
+ input_visitor_test_add("/visitor/input/list_union/int",
+ NULL, test_visitor_in_list_union_int);
+ input_visitor_test_add("/visitor/input/list_union/int8",
+ NULL, test_visitor_in_list_union_int8);
+ input_visitor_test_add("/visitor/input/list_union/int16",
+ NULL, test_visitor_in_list_union_int16);
+ input_visitor_test_add("/visitor/input/list_union/int32",
+ NULL, test_visitor_in_list_union_int32);
+ input_visitor_test_add("/visitor/input/list_union/int64",
+ NULL, test_visitor_in_list_union_int64);
+ input_visitor_test_add("/visitor/input/list_union/uint8",
+ NULL, test_visitor_in_list_union_uint8);
+ input_visitor_test_add("/visitor/input/list_union/uint16",
+ NULL, test_visitor_in_list_union_uint16);
+ input_visitor_test_add("/visitor/input/list_union/uint32",
+ NULL, test_visitor_in_list_union_uint32);
+ input_visitor_test_add("/visitor/input/list_union/uint64",
+ NULL, test_visitor_in_list_union_uint64);
+ input_visitor_test_add("/visitor/input/list_union/bool",
+ NULL, test_visitor_in_list_union_bool);
+ input_visitor_test_add("/visitor/input/list_union/str",
+ NULL, test_visitor_in_list_union_string);
+ input_visitor_test_add("/visitor/input/list_union/number",
+ NULL, test_visitor_in_list_union_number);
input_visitor_test_add("/visitor/input/fail/struct",
NULL, test_visitor_in_fail_struct);
input_visitor_test_add("/visitor/input/fail/struct-nested",
@@ -1377,8 +1377,8 @@
NULL, test_visitor_in_fail_union_flat_no_discrim);
input_visitor_test_add("/visitor/input/fail/alternate",
NULL, test_visitor_in_fail_alternate);
- input_visitor_test_add("/visitor/input/fail/union-native-list",
- NULL, test_visitor_in_fail_union_native_list);
+ input_visitor_test_add("/visitor/input/fail/union-list",
+ NULL, test_visitor_in_fail_union_list);
input_visitor_test_add("/visitor/input/qapi-introspect",
NULL, test_visitor_in_qmp_introspect);
diff --git a/tests/test-qobject-output-visitor.c b/tests/test-qobject-output-visitor.c
index be63585..3e993e5 100644
--- a/tests/test-qobject-output-visitor.c
+++ b/tests/test-qobject-output-visitor.c
@@ -474,11 +474,11 @@
g_assert(qobject_type(nil) == QTYPE_QNULL);
}
-static void init_native_list(UserDefNativeListUnion *cvalue)
+static void init_list_union(UserDefListUnion *cvalue)
{
int i;
switch (cvalue->type) {
- case USER_DEF_NATIVE_LIST_UNION_KIND_INTEGER: {
+ case USER_DEF_LIST_UNION_KIND_INTEGER: {
intList **list = &cvalue->u.integer.data;
for (i = 0; i < 32; i++) {
*list = g_new0(intList, 1);
@@ -488,7 +488,7 @@
}
break;
}
- case USER_DEF_NATIVE_LIST_UNION_KIND_S8: {
+ case USER_DEF_LIST_UNION_KIND_S8: {
int8List **list = &cvalue->u.s8.data;
for (i = 0; i < 32; i++) {
*list = g_new0(int8List, 1);
@@ -498,7 +498,7 @@
}
break;
}
- case USER_DEF_NATIVE_LIST_UNION_KIND_S16: {
+ case USER_DEF_LIST_UNION_KIND_S16: {
int16List **list = &cvalue->u.s16.data;
for (i = 0; i < 32; i++) {
*list = g_new0(int16List, 1);
@@ -508,7 +508,7 @@
}
break;
}
- case USER_DEF_NATIVE_LIST_UNION_KIND_S32: {
+ case USER_DEF_LIST_UNION_KIND_S32: {
int32List **list = &cvalue->u.s32.data;
for (i = 0; i < 32; i++) {
*list = g_new0(int32List, 1);
@@ -518,7 +518,7 @@
}
break;
}
- case USER_DEF_NATIVE_LIST_UNION_KIND_S64: {
+ case USER_DEF_LIST_UNION_KIND_S64: {
int64List **list = &cvalue->u.s64.data;
for (i = 0; i < 32; i++) {
*list = g_new0(int64List, 1);
@@ -528,7 +528,7 @@
}
break;
}
- case USER_DEF_NATIVE_LIST_UNION_KIND_U8: {
+ case USER_DEF_LIST_UNION_KIND_U8: {
uint8List **list = &cvalue->u.u8.data;
for (i = 0; i < 32; i++) {
*list = g_new0(uint8List, 1);
@@ -538,7 +538,7 @@
}
break;
}
- case USER_DEF_NATIVE_LIST_UNION_KIND_U16: {
+ case USER_DEF_LIST_UNION_KIND_U16: {
uint16List **list = &cvalue->u.u16.data;
for (i = 0; i < 32; i++) {
*list = g_new0(uint16List, 1);
@@ -548,7 +548,7 @@
}
break;
}
- case USER_DEF_NATIVE_LIST_UNION_KIND_U32: {
+ case USER_DEF_LIST_UNION_KIND_U32: {
uint32List **list = &cvalue->u.u32.data;
for (i = 0; i < 32; i++) {
*list = g_new0(uint32List, 1);
@@ -558,7 +558,7 @@
}
break;
}
- case USER_DEF_NATIVE_LIST_UNION_KIND_U64: {
+ case USER_DEF_LIST_UNION_KIND_U64: {
uint64List **list = &cvalue->u.u64.data;
for (i = 0; i < 32; i++) {
*list = g_new0(uint64List, 1);
@@ -568,7 +568,7 @@
}
break;
}
- case USER_DEF_NATIVE_LIST_UNION_KIND_BOOLEAN: {
+ case USER_DEF_LIST_UNION_KIND_BOOLEAN: {
boolList **list = &cvalue->u.boolean.data;
for (i = 0; i < 32; i++) {
*list = g_new0(boolList, 1);
@@ -578,7 +578,7 @@
}
break;
}
- case USER_DEF_NATIVE_LIST_UNION_KIND_STRING: {
+ case USER_DEF_LIST_UNION_KIND_STRING: {
strList **list = &cvalue->u.string.data;
for (i = 0; i < 32; i++) {
*list = g_new0(strList, 1);
@@ -588,7 +588,7 @@
}
break;
}
- case USER_DEF_NATIVE_LIST_UNION_KIND_NUMBER: {
+ case USER_DEF_LIST_UNION_KIND_NUMBER: {
numberList **list = &cvalue->u.number.data;
for (i = 0; i < 32; i++) {
*list = g_new0(numberList, 1);
@@ -603,8 +603,8 @@
}
}
-static void check_native_list(QObject *qobj,
- UserDefNativeListUnionKind kind)
+static void check_list_union(QObject *qobj,
+ UserDefListUnionKind kind)
{
QDict *qdict;
QList *qlist;
@@ -616,10 +616,10 @@
qlist = qlist_copy(qobject_to(QList, qdict_get(qdict, "data")));
switch (kind) {
- case USER_DEF_NATIVE_LIST_UNION_KIND_U8:
- case USER_DEF_NATIVE_LIST_UNION_KIND_U16:
- case USER_DEF_NATIVE_LIST_UNION_KIND_U32:
- case USER_DEF_NATIVE_LIST_UNION_KIND_U64:
+ case USER_DEF_LIST_UNION_KIND_U8:
+ case USER_DEF_LIST_UNION_KIND_U16:
+ case USER_DEF_LIST_UNION_KIND_U32:
+ case USER_DEF_LIST_UNION_KIND_U64:
for (i = 0; i < 32; i++) {
QObject *tmp;
QNum *qvalue;
@@ -634,16 +634,16 @@
}
break;
- case USER_DEF_NATIVE_LIST_UNION_KIND_S8:
- case USER_DEF_NATIVE_LIST_UNION_KIND_S16:
- case USER_DEF_NATIVE_LIST_UNION_KIND_S32:
- case USER_DEF_NATIVE_LIST_UNION_KIND_S64:
+ case USER_DEF_LIST_UNION_KIND_S8:
+ case USER_DEF_LIST_UNION_KIND_S16:
+ case USER_DEF_LIST_UNION_KIND_S32:
+ case USER_DEF_LIST_UNION_KIND_S64:
/*
* All integer elements in JSON arrays get stored into QNums
* when we convert to QObjects, so we can check them all in
* the same fashion, so simply fall through here.
*/
- case USER_DEF_NATIVE_LIST_UNION_KIND_INTEGER:
+ case USER_DEF_LIST_UNION_KIND_INTEGER:
for (i = 0; i < 32; i++) {
QObject *tmp;
QNum *qvalue;
@@ -657,7 +657,7 @@
qobject_unref(qlist_pop(qlist));
}
break;
- case USER_DEF_NATIVE_LIST_UNION_KIND_BOOLEAN:
+ case USER_DEF_LIST_UNION_KIND_BOOLEAN:
for (i = 0; i < 32; i++) {
QObject *tmp;
QBool *qvalue;
@@ -668,7 +668,7 @@
qobject_unref(qlist_pop(qlist));
}
break;
- case USER_DEF_NATIVE_LIST_UNION_KIND_STRING:
+ case USER_DEF_LIST_UNION_KIND_STRING:
for (i = 0; i < 32; i++) {
QObject *tmp;
QString *qvalue;
@@ -681,7 +681,7 @@
qobject_unref(qlist_pop(qlist));
}
break;
- case USER_DEF_NATIVE_LIST_UNION_KIND_NUMBER:
+ case USER_DEF_LIST_UNION_KIND_NUMBER:
for (i = 0; i < 32; i++) {
QObject *tmp;
QNum *qvalue;
@@ -706,93 +706,93 @@
qobject_unref(qlist);
}
-static void test_native_list(TestOutputVisitorData *data,
- const void *unused,
- UserDefNativeListUnionKind kind)
+static void test_list_union(TestOutputVisitorData *data,
+ const void *unused,
+ UserDefListUnionKind kind)
{
- UserDefNativeListUnion *cvalue = g_new0(UserDefNativeListUnion, 1);
+ UserDefListUnion *cvalue = g_new0(UserDefListUnion, 1);
QObject *obj;
cvalue->type = kind;
- init_native_list(cvalue);
+ init_list_union(cvalue);
- visit_type_UserDefNativeListUnion(data->ov, NULL, &cvalue, &error_abort);
+ visit_type_UserDefListUnion(data->ov, NULL, &cvalue, &error_abort);
obj = visitor_get(data);
- check_native_list(obj, cvalue->type);
- qapi_free_UserDefNativeListUnion(cvalue);
+ check_list_union(obj, cvalue->type);
+ qapi_free_UserDefListUnion(cvalue);
}
-static void test_visitor_out_native_list_int(TestOutputVisitorData *data,
+static void test_visitor_out_list_union_int(TestOutputVisitorData *data,
+ const void *unused)
+{
+ test_list_union(data, unused, USER_DEF_LIST_UNION_KIND_INTEGER);
+}
+
+static void test_visitor_out_list_union_int8(TestOutputVisitorData *data,
const void *unused)
{
- test_native_list(data, unused, USER_DEF_NATIVE_LIST_UNION_KIND_INTEGER);
+ test_list_union(data, unused, USER_DEF_LIST_UNION_KIND_S8);
}
-static void test_visitor_out_native_list_int8(TestOutputVisitorData *data,
+static void test_visitor_out_list_union_int16(TestOutputVisitorData *data,
const void *unused)
{
- test_native_list(data, unused, USER_DEF_NATIVE_LIST_UNION_KIND_S8);
+ test_list_union(data, unused, USER_DEF_LIST_UNION_KIND_S16);
}
-static void test_visitor_out_native_list_int16(TestOutputVisitorData *data,
- const void *unused)
-{
- test_native_list(data, unused, USER_DEF_NATIVE_LIST_UNION_KIND_S16);
-}
-
-static void test_visitor_out_native_list_int32(TestOutputVisitorData *data,
- const void *unused)
-{
- test_native_list(data, unused, USER_DEF_NATIVE_LIST_UNION_KIND_S32);
-}
-
-static void test_visitor_out_native_list_int64(TestOutputVisitorData *data,
- const void *unused)
-{
- test_native_list(data, unused, USER_DEF_NATIVE_LIST_UNION_KIND_S64);
-}
-
-static void test_visitor_out_native_list_uint8(TestOutputVisitorData *data,
- const void *unused)
-{
- test_native_list(data, unused, USER_DEF_NATIVE_LIST_UNION_KIND_U8);
-}
-
-static void test_visitor_out_native_list_uint16(TestOutputVisitorData *data,
- const void *unused)
-{
- test_native_list(data, unused, USER_DEF_NATIVE_LIST_UNION_KIND_U16);
-}
-
-static void test_visitor_out_native_list_uint32(TestOutputVisitorData *data,
- const void *unused)
-{
- test_native_list(data, unused, USER_DEF_NATIVE_LIST_UNION_KIND_U32);
-}
-
-static void test_visitor_out_native_list_uint64(TestOutputVisitorData *data,
- const void *unused)
-{
- test_native_list(data, unused, USER_DEF_NATIVE_LIST_UNION_KIND_U64);
-}
-
-static void test_visitor_out_native_list_bool(TestOutputVisitorData *data,
+static void test_visitor_out_list_union_int32(TestOutputVisitorData *data,
const void *unused)
{
- test_native_list(data, unused, USER_DEF_NATIVE_LIST_UNION_KIND_BOOLEAN);
+ test_list_union(data, unused, USER_DEF_LIST_UNION_KIND_S32);
}
-static void test_visitor_out_native_list_str(TestOutputVisitorData *data,
+static void test_visitor_out_list_union_int64(TestOutputVisitorData *data,
const void *unused)
{
- test_native_list(data, unused, USER_DEF_NATIVE_LIST_UNION_KIND_STRING);
+ test_list_union(data, unused, USER_DEF_LIST_UNION_KIND_S64);
}
-static void test_visitor_out_native_list_number(TestOutputVisitorData *data,
- const void *unused)
+static void test_visitor_out_list_union_uint8(TestOutputVisitorData *data,
+ const void *unused)
{
- test_native_list(data, unused, USER_DEF_NATIVE_LIST_UNION_KIND_NUMBER);
+ test_list_union(data, unused, USER_DEF_LIST_UNION_KIND_U8);
+}
+
+static void test_visitor_out_list_union_uint16(TestOutputVisitorData *data,
+ const void *unused)
+{
+ test_list_union(data, unused, USER_DEF_LIST_UNION_KIND_U16);
+}
+
+static void test_visitor_out_list_union_uint32(TestOutputVisitorData *data,
+ const void *unused)
+{
+ test_list_union(data, unused, USER_DEF_LIST_UNION_KIND_U32);
+}
+
+static void test_visitor_out_list_union_uint64(TestOutputVisitorData *data,
+ const void *unused)
+{
+ test_list_union(data, unused, USER_DEF_LIST_UNION_KIND_U64);
+}
+
+static void test_visitor_out_list_union_bool(TestOutputVisitorData *data,
+ const void *unused)
+{
+ test_list_union(data, unused, USER_DEF_LIST_UNION_KIND_BOOLEAN);
+}
+
+static void test_visitor_out_list_union_str(TestOutputVisitorData *data,
+ const void *unused)
+{
+ test_list_union(data, unused, USER_DEF_LIST_UNION_KIND_STRING);
+}
+
+static void test_visitor_out_list_union_number(TestOutputVisitorData *data,
+ const void *unused)
+{
+ test_list_union(data, unused, USER_DEF_LIST_UNION_KIND_NUMBER);
}
static void output_visitor_test_add(const char *testpath,
@@ -841,42 +841,42 @@
&out_visitor_data, test_visitor_out_alternate);
output_visitor_test_add("/visitor/output/null",
&out_visitor_data, test_visitor_out_null);
- output_visitor_test_add("/visitor/output/native_list/int",
+ output_visitor_test_add("/visitor/output/list_union/int",
&out_visitor_data,
- test_visitor_out_native_list_int);
- output_visitor_test_add("/visitor/output/native_list/int8",
+ test_visitor_out_list_union_int);
+ output_visitor_test_add("/visitor/output/list_union/int8",
&out_visitor_data,
- test_visitor_out_native_list_int8);
- output_visitor_test_add("/visitor/output/native_list/int16",
+ test_visitor_out_list_union_int8);
+ output_visitor_test_add("/visitor/output/list_union/int16",
&out_visitor_data,
- test_visitor_out_native_list_int16);
- output_visitor_test_add("/visitor/output/native_list/int32",
+ test_visitor_out_list_union_int16);
+ output_visitor_test_add("/visitor/output/list_union/int32",
&out_visitor_data,
- test_visitor_out_native_list_int32);
- output_visitor_test_add("/visitor/output/native_list/int64",
+ test_visitor_out_list_union_int32);
+ output_visitor_test_add("/visitor/output/list_union/int64",
&out_visitor_data,
- test_visitor_out_native_list_int64);
- output_visitor_test_add("/visitor/output/native_list/uint8",
+ test_visitor_out_list_union_int64);
+ output_visitor_test_add("/visitor/output/list_union/uint8",
&out_visitor_data,
- test_visitor_out_native_list_uint8);
- output_visitor_test_add("/visitor/output/native_list/uint16",
+ test_visitor_out_list_union_uint8);
+ output_visitor_test_add("/visitor/output/list_union/uint16",
&out_visitor_data,
- test_visitor_out_native_list_uint16);
- output_visitor_test_add("/visitor/output/native_list/uint32",
+ test_visitor_out_list_union_uint16);
+ output_visitor_test_add("/visitor/output/list_union/uint32",
&out_visitor_data,
- test_visitor_out_native_list_uint32);
- output_visitor_test_add("/visitor/output/native_list/uint64",
+ test_visitor_out_list_union_uint32);
+ output_visitor_test_add("/visitor/output/list_union/uint64",
&out_visitor_data,
- test_visitor_out_native_list_uint64);
- output_visitor_test_add("/visitor/output/native_list/bool",
+ test_visitor_out_list_union_uint64);
+ output_visitor_test_add("/visitor/output/list_union/bool",
&out_visitor_data,
- test_visitor_out_native_list_bool);
- output_visitor_test_add("/visitor/output/native_list/string",
+ test_visitor_out_list_union_bool);
+ output_visitor_test_add("/visitor/output/list_union/string",
&out_visitor_data,
- test_visitor_out_native_list_str);
- output_visitor_test_add("/visitor/output/native_list/number",
+ test_visitor_out_list_union_str);
+ output_visitor_test_add("/visitor/output/list_union/number",
&out_visitor_data,
- test_visitor_out_native_list_number);
+ test_visitor_out_list_union_number);
g_test_run();
diff --git a/tests/test-util-filemonitor.c b/tests/test-util-filemonitor.c
new file mode 100644
index 0000000..5d95cea
--- /dev/null
+++ b/tests/test-util-filemonitor.c
@@ -0,0 +1,685 @@
+/*
+ * Tests for util/filemonitor-*.c
+ *
+ * Copyright 2018 Red Hat, Inc.
+ *
+ * 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 library; if not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include "qemu/osdep.h"
+#include "qemu/main-loop.h"
+#include "qapi/error.h"
+#include "qemu/filemonitor.h"
+
+#include <utime.h>
+
+enum {
+ QFILE_MONITOR_TEST_OP_CREATE,
+ QFILE_MONITOR_TEST_OP_APPEND,
+ QFILE_MONITOR_TEST_OP_TRUNC,
+ QFILE_MONITOR_TEST_OP_RENAME,
+ QFILE_MONITOR_TEST_OP_TOUCH,
+ QFILE_MONITOR_TEST_OP_UNLINK,
+};
+
+typedef struct {
+ int type;
+ const char *filesrc;
+ const char *filedst;
+} QFileMonitorTestOp;
+
+typedef struct {
+ const char *file;
+} QFileMonitorTestWatch;
+
+typedef struct {
+ gsize nwatches;
+ const QFileMonitorTestWatch *watches;
+
+ gsize nops;
+ const QFileMonitorTestOp *ops;
+} QFileMonitorTestPlan;
+
+typedef struct {
+ int id;
+ QFileMonitorEvent event;
+ char *filename;
+} QFileMonitorTestRecord;
+
+
+typedef struct {
+ QemuMutex lock;
+ GList *records;
+} QFileMonitorTestData;
+
+static QemuMutex evlock;
+static bool evstopping;
+static bool evrunning;
+
+/*
+ * Main function for a background thread that is
+ * running the event loop during the test
+ */
+static void *
+qemu_file_monitor_test_event_loop(void *opaque G_GNUC_UNUSED)
+{
+ qemu_mutex_lock(&evlock);
+
+ while (!evstopping) {
+ qemu_mutex_unlock(&evlock);
+ main_loop_wait(true);
+ qemu_mutex_lock(&evlock);
+ }
+
+ evrunning = false;
+ qemu_mutex_unlock(&evlock);
+ return NULL;
+}
+
+
+/*
+ * File monitor event handler which simply maintains
+ * an ordered list of all events that it receives
+ */
+static void
+qemu_file_monitor_test_handler(int id,
+ QFileMonitorEvent event,
+ const char *filename,
+ void *opaque)
+{
+ QFileMonitorTestData *data = opaque;
+ QFileMonitorTestRecord *rec = g_new0(QFileMonitorTestRecord, 1);
+
+ rec->id = id;
+ rec->event = event;
+ rec->filename = g_strdup(filename);
+
+ qemu_mutex_lock(&data->lock);
+ data->records = g_list_append(data->records, rec);
+ qemu_mutex_unlock(&data->lock);
+}
+
+
+static void
+qemu_file_monitor_test_record_free(QFileMonitorTestRecord *rec)
+{
+ g_free(rec->filename);
+ g_free(rec);
+}
+
+
+/*
+ * Get the next event record that has been received by
+ * the file monitor event handler. Since events are
+ * emitted in the background thread running the event
+ * loop, we can't assume there is a record available
+ * immediately. Thus we will sleep for upto 5 seconds
+ * to wait for the event to be queued for us.
+ */
+static QFileMonitorTestRecord *
+qemu_file_monitor_test_next_record(QFileMonitorTestData *data)
+{
+ GTimer *timer = g_timer_new();
+ QFileMonitorTestRecord *record = NULL;
+ GList *tmp;
+
+ qemu_mutex_lock(&data->lock);
+ while (!data->records && g_timer_elapsed(timer, NULL) < 5) {
+ qemu_mutex_unlock(&data->lock);
+ usleep(10 * 1000);
+ qemu_mutex_lock(&data->lock);
+ }
+ if (data->records) {
+ record = data->records->data;
+ tmp = data->records;
+ data->records = g_list_remove_link(data->records, tmp);
+ g_list_free(tmp);
+ }
+ qemu_mutex_unlock(&data->lock);
+
+ g_timer_destroy(timer);
+ return record;
+}
+
+
+/*
+ * Check whether the event record we retrieved matches
+ * data we were expecting to see for the event
+ */
+static bool
+qemu_file_monitor_test_expect(QFileMonitorTestData *data,
+ int id,
+ QFileMonitorEvent event,
+ const char *filename)
+{
+ QFileMonitorTestRecord *rec;
+ bool ret = false;
+
+ rec = qemu_file_monitor_test_next_record(data);
+
+ if (!rec) {
+ g_printerr("Missing event watch id %d event %d file %s\n",
+ id, event, filename);
+ return false;
+ }
+
+ if (id != rec->id) {
+ g_printerr("Expected watch id %d but got %d\n", id, rec->id);
+ goto cleanup;
+ }
+
+ if (event != rec->event) {
+ g_printerr("Expected event %d but got %d\n", event, rec->event);
+ goto cleanup;
+ }
+
+ if (!g_str_equal(filename, rec->filename)) {
+ g_printerr("Expected filename %s but got %s\n",
+ filename, rec->filename);
+ goto cleanup;
+ }
+
+ ret = true;
+
+ cleanup:
+ qemu_file_monitor_test_record_free(rec);
+ return ret;
+}
+
+
+static void
+test_file_monitor_events(const void *opaque)
+{
+ const QFileMonitorTestPlan *plan = opaque;
+ Error *local_err = NULL;
+ GError *gerr = NULL;
+ QFileMonitor *mon = qemu_file_monitor_new(&local_err);
+ QemuThread th;
+ GTimer *timer;
+ gchar *dir = NULL;
+ int err = -1;
+ gsize i, j;
+ char *pathsrc = NULL;
+ char *pathdst = NULL;
+ QFileMonitorTestData data;
+
+ qemu_mutex_init(&data.lock);
+ data.records = NULL;
+
+ /*
+ * The file monitor needs the main loop running in
+ * order to receive events from inotify. We must
+ * thus spawn a background thread to run an event
+ * loop impl, while this thread triggers the
+ * actual file operations we're testing
+ */
+ evrunning = 1;
+ evstopping = 0;
+ qemu_thread_create(&th, "event-loop",
+ qemu_file_monitor_test_event_loop, NULL,
+ QEMU_THREAD_JOINABLE);
+
+ if (local_err) {
+ g_printerr("File monitoring not available: %s",
+ error_get_pretty(local_err));
+ error_free(local_err);
+ return;
+ }
+
+ dir = g_dir_make_tmp("test-util-filemonitor-XXXXXX",
+ &gerr);
+ if (!dir) {
+ g_printerr("Unable to create tmp dir %s",
+ gerr->message);
+ g_error_free(gerr);
+ abort();
+ }
+
+ /*
+ * First register all the directory / file watches
+ * we're interested in seeing events against
+ */
+ for (i = 0; i < plan->nwatches; i++) {
+ int watchid;
+ watchid = qemu_file_monitor_add_watch(mon,
+ dir,
+ plan->watches[i].file,
+ qemu_file_monitor_test_handler,
+ &data,
+ &local_err);
+ if (watchid < 0) {
+ g_printerr("Unable to add watch %s",
+ error_get_pretty(local_err));
+ goto cleanup;
+ }
+ }
+
+
+ /*
+ * Now invoke all the file operations (create,
+ * delete, rename, chmod, etc). These operations
+ * will trigger the various file monitor events
+ */
+ for (i = 0; i < plan->nops; i++) {
+ const QFileMonitorTestOp *op = &(plan->ops[i]);
+ int fd;
+ struct utimbuf ubuf;
+
+ pathsrc = g_strdup_printf("%s/%s", dir, op->filesrc);
+ if (op->filedst) {
+ pathdst = g_strdup_printf("%s/%s", dir, op->filedst);
+ }
+
+ switch (op->type) {
+ case QFILE_MONITOR_TEST_OP_CREATE:
+ fd = open(pathsrc, O_WRONLY | O_CREAT, 0700);
+ if (fd < 0) {
+ g_printerr("Unable to create %s: %s",
+ pathsrc, strerror(errno));
+ goto cleanup;
+ }
+ close(fd);
+ break;
+
+ case QFILE_MONITOR_TEST_OP_APPEND:
+ fd = open(pathsrc, O_WRONLY | O_APPEND, 0700);
+ if (fd < 0) {
+ g_printerr("Unable to open %s: %s",
+ pathsrc, strerror(errno));
+ goto cleanup;
+ }
+
+ if (write(fd, "Hello World", 10) != 10) {
+ g_printerr("Unable to write %s: %s",
+ pathsrc, strerror(errno));
+ close(fd);
+ goto cleanup;
+ }
+ close(fd);
+ break;
+
+ case QFILE_MONITOR_TEST_OP_TRUNC:
+ if (truncate(pathsrc, 4) < 0) {
+ g_printerr("Unable to truncate %s: %s",
+ pathsrc, strerror(errno));
+ goto cleanup;
+ }
+ break;
+
+ case QFILE_MONITOR_TEST_OP_RENAME:
+ if (rename(pathsrc, pathdst) < 0) {
+ g_printerr("Unable to rename %s to %s: %s",
+ pathsrc, pathdst, strerror(errno));
+ goto cleanup;
+ }
+ break;
+
+ case QFILE_MONITOR_TEST_OP_UNLINK:
+ if (unlink(pathsrc) < 0) {
+ g_printerr("Unable to unlink %s: %s",
+ pathsrc, strerror(errno));
+ goto cleanup;
+ }
+ break;
+
+ case QFILE_MONITOR_TEST_OP_TOUCH:
+ ubuf.actime = 1024;
+ ubuf.modtime = 1025;
+ if (utime(pathsrc, &ubuf) < 0) {
+ g_printerr("Unable to touch %s: %s",
+ pathsrc, strerror(errno));
+ goto cleanup;
+ }
+ break;
+
+ default:
+ g_assert_not_reached();
+ }
+
+ g_free(pathsrc);
+ g_free(pathdst);
+ pathsrc = pathdst = NULL;
+ }
+
+
+ /*
+ * Finally validate that we have received all the events
+ * we expect to see for the combination of watches and
+ * file operations
+ */
+ for (i = 0; i < plan->nops; i++) {
+ const QFileMonitorTestOp *op = &(plan->ops[i]);
+
+ switch (op->type) {
+ case QFILE_MONITOR_TEST_OP_CREATE:
+ for (j = 0; j < plan->nwatches; j++) {
+ if (plan->watches[j].file &&
+ !g_str_equal(plan->watches[j].file, op->filesrc))
+ continue;
+
+ if (!qemu_file_monitor_test_expect(
+ &data, j, QFILE_MONITOR_EVENT_CREATED, op->filesrc))
+ goto cleanup;
+ }
+ break;
+
+ case QFILE_MONITOR_TEST_OP_APPEND:
+ case QFILE_MONITOR_TEST_OP_TRUNC:
+ for (j = 0; j < plan->nwatches; j++) {
+ if (plan->watches[j].file &&
+ !g_str_equal(plan->watches[j].file, op->filesrc))
+ continue;
+
+ if (!qemu_file_monitor_test_expect(
+ &data, j, QFILE_MONITOR_EVENT_MODIFIED, op->filesrc))
+ goto cleanup;
+ }
+ break;
+
+ case QFILE_MONITOR_TEST_OP_RENAME:
+ for (j = 0; j < plan->nwatches; j++) {
+ if (plan->watches[j].file &&
+ !g_str_equal(plan->watches[j].file, op->filesrc))
+ continue;
+
+ if (!qemu_file_monitor_test_expect(
+ &data, j, QFILE_MONITOR_EVENT_DELETED, op->filesrc))
+ goto cleanup;
+ }
+
+ for (j = 0; j < plan->nwatches; j++) {
+ if (plan->watches[j].file &&
+ !g_str_equal(plan->watches[j].file, op->filedst))
+ continue;
+
+ if (!qemu_file_monitor_test_expect(
+ &data, j, QFILE_MONITOR_EVENT_CREATED, op->filedst))
+ goto cleanup;
+ }
+ break;
+
+ case QFILE_MONITOR_TEST_OP_TOUCH:
+ for (j = 0; j < plan->nwatches; j++) {
+ if (plan->watches[j].file &&
+ !g_str_equal(plan->watches[j].file, op->filesrc))
+ continue;
+
+ if (!qemu_file_monitor_test_expect(
+ &data, j, QFILE_MONITOR_EVENT_ATTRIBUTES, op->filesrc))
+ goto cleanup;
+ }
+ break;
+
+ case QFILE_MONITOR_TEST_OP_UNLINK:
+ for (j = 0; j < plan->nwatches; j++) {
+ if (plan->watches[j].file &&
+ !g_str_equal(plan->watches[j].file, op->filesrc))
+ continue;
+
+ if (!qemu_file_monitor_test_expect(
+ &data, j, QFILE_MONITOR_EVENT_DELETED, op->filesrc))
+ goto cleanup;
+ }
+ break;
+
+ default:
+ g_assert_not_reached();
+ }
+ }
+
+ err = 0;
+
+ cleanup:
+ g_free(pathsrc);
+ g_free(pathdst);
+
+ qemu_mutex_lock(&evlock);
+ evstopping = 1;
+ timer = g_timer_new();
+ while (evrunning && g_timer_elapsed(timer, NULL) < 5) {
+ qemu_mutex_unlock(&evlock);
+ usleep(10 * 1000);
+ qemu_mutex_lock(&evlock);
+ }
+ qemu_mutex_unlock(&evlock);
+
+ if (g_timer_elapsed(timer, NULL) >= 5) {
+ g_printerr("Event loop failed to quit after 5 seconds\n");
+ }
+ g_timer_destroy(timer);
+
+ for (i = 0; i < plan->nops; i++) {
+ const QFileMonitorTestOp *op = &(plan->ops[i]);
+ pathsrc = g_strdup_printf("%s/%s", dir, op->filesrc);
+ unlink(pathsrc);
+ g_free(pathsrc);
+ if (op->filedst) {
+ pathdst = g_strdup_printf("%s/%s", dir, op->filedst);
+ unlink(pathdst);
+ g_free(pathdst);
+ }
+ }
+
+ qemu_file_monitor_free(mon);
+ g_list_foreach(data.records,
+ (GFunc)qemu_file_monitor_test_record_free, NULL);
+ g_list_free(data.records);
+ qemu_mutex_destroy(&data.lock);
+ if (dir) {
+ rmdir(dir);
+ }
+ g_free(dir);
+ g_assert(err == 0);
+}
+
+
+/*
+ * Set of structs which define which file name patterns
+ * we're trying to watch against. NULL, means all files
+ * in the directory
+ */
+static const QFileMonitorTestWatch watches_any[] = {
+ { NULL },
+};
+
+static const QFileMonitorTestWatch watches_one[] = {
+ { "one.txt" },
+};
+
+static const QFileMonitorTestWatch watches_two[] = {
+ { "two.txt" },
+};
+
+static const QFileMonitorTestWatch watches_many[] = {
+ { NULL },
+ { "one.txt" },
+ { "two.txt" },
+};
+
+
+/*
+ * Various sets of file operations we're going to
+ * trigger and validate events for
+ */
+static const QFileMonitorTestOp ops_create_one[] = {
+ { .type = QFILE_MONITOR_TEST_OP_CREATE,
+ .filesrc = "one.txt", }
+};
+
+static const QFileMonitorTestOp ops_delete_one[] = {
+ { .type = QFILE_MONITOR_TEST_OP_CREATE,
+ .filesrc = "one.txt", },
+ { .type = QFILE_MONITOR_TEST_OP_UNLINK,
+ .filesrc = "one.txt", }
+};
+
+static const QFileMonitorTestOp ops_create_many[] = {
+ { .type = QFILE_MONITOR_TEST_OP_CREATE,
+ .filesrc = "one.txt", },
+ { .type = QFILE_MONITOR_TEST_OP_CREATE,
+ .filesrc = "two.txt", },
+ { .type = QFILE_MONITOR_TEST_OP_CREATE,
+ .filesrc = "three.txt", }
+};
+
+static const QFileMonitorTestOp ops_rename_one[] = {
+ { .type = QFILE_MONITOR_TEST_OP_CREATE,
+ .filesrc = "one.txt", },
+ { .type = QFILE_MONITOR_TEST_OP_RENAME,
+ .filesrc = "one.txt", .filedst = "two.txt" }
+};
+
+static const QFileMonitorTestOp ops_rename_many[] = {
+ { .type = QFILE_MONITOR_TEST_OP_CREATE,
+ .filesrc = "one.txt", },
+ { .type = QFILE_MONITOR_TEST_OP_CREATE,
+ .filesrc = "two.txt", },
+ { .type = QFILE_MONITOR_TEST_OP_RENAME,
+ .filesrc = "one.txt", .filedst = "two.txt" }
+};
+
+static const QFileMonitorTestOp ops_append_one[] = {
+ { .type = QFILE_MONITOR_TEST_OP_CREATE,
+ .filesrc = "one.txt", },
+ { .type = QFILE_MONITOR_TEST_OP_APPEND,
+ .filesrc = "one.txt", },
+};
+
+static const QFileMonitorTestOp ops_trunc_one[] = {
+ { .type = QFILE_MONITOR_TEST_OP_CREATE,
+ .filesrc = "one.txt", },
+ { .type = QFILE_MONITOR_TEST_OP_TRUNC,
+ .filesrc = "one.txt", },
+};
+
+static const QFileMonitorTestOp ops_touch_one[] = {
+ { .type = QFILE_MONITOR_TEST_OP_CREATE,
+ .filesrc = "one.txt", },
+ { .type = QFILE_MONITOR_TEST_OP_TOUCH,
+ .filesrc = "one.txt", },
+};
+
+
+/*
+ * No we define data sets for the combinatorial
+ * expansion of file watches and operation sets
+ */
+#define PLAN_DATA(o, w) \
+ static const QFileMonitorTestPlan plan_ ## o ## _ ## w = { \
+ .nops = G_N_ELEMENTS(ops_ ##o), \
+ .ops = ops_ ##o, \
+ .nwatches = G_N_ELEMENTS(watches_ ##w), \
+ .watches = watches_ ## w, \
+ }
+
+PLAN_DATA(create_one, any);
+PLAN_DATA(create_one, one);
+PLAN_DATA(create_one, two);
+PLAN_DATA(create_one, many);
+
+PLAN_DATA(delete_one, any);
+PLAN_DATA(delete_one, one);
+PLAN_DATA(delete_one, two);
+PLAN_DATA(delete_one, many);
+
+PLAN_DATA(create_many, any);
+PLAN_DATA(create_many, one);
+PLAN_DATA(create_many, two);
+PLAN_DATA(create_many, many);
+
+PLAN_DATA(rename_one, any);
+PLAN_DATA(rename_one, one);
+PLAN_DATA(rename_one, two);
+PLAN_DATA(rename_one, many);
+
+PLAN_DATA(rename_many, any);
+PLAN_DATA(rename_many, one);
+PLAN_DATA(rename_many, two);
+PLAN_DATA(rename_many, many);
+
+PLAN_DATA(append_one, any);
+PLAN_DATA(append_one, one);
+PLAN_DATA(append_one, two);
+PLAN_DATA(append_one, many);
+
+PLAN_DATA(trunc_one, any);
+PLAN_DATA(trunc_one, one);
+PLAN_DATA(trunc_one, two);
+PLAN_DATA(trunc_one, many);
+
+PLAN_DATA(touch_one, any);
+PLAN_DATA(touch_one, one);
+PLAN_DATA(touch_one, two);
+PLAN_DATA(touch_one, many);
+
+
+int main(int argc, char **argv)
+{
+ g_test_init(&argc, &argv, NULL);
+
+ qemu_init_main_loop(&error_abort);
+
+ qemu_mutex_init(&evlock);
+
+ /*
+ * Register test cases for the combinatorial
+ * expansion of file watches and operation sets
+ */
+ #define PLAN_REGISTER(o, w) \
+ g_test_add_data_func("/util/filemonitor/" # o "/" # w, \
+ &plan_ ## o ## _ ## w, test_file_monitor_events)
+
+ PLAN_REGISTER(create_one, any);
+ PLAN_REGISTER(create_one, one);
+ PLAN_REGISTER(create_one, two);
+ PLAN_REGISTER(create_one, many);
+
+ PLAN_REGISTER(delete_one, any);
+ PLAN_REGISTER(delete_one, one);
+ PLAN_REGISTER(delete_one, two);
+ PLAN_REGISTER(delete_one, many);
+
+ PLAN_REGISTER(create_many, any);
+ PLAN_REGISTER(create_many, one);
+ PLAN_REGISTER(create_many, two);
+ PLAN_REGISTER(create_many, many);
+
+ PLAN_REGISTER(rename_one, any);
+ PLAN_REGISTER(rename_one, one);
+ PLAN_REGISTER(rename_one, two);
+ PLAN_REGISTER(rename_one, many);
+
+ PLAN_REGISTER(rename_many, any);
+ PLAN_REGISTER(rename_many, one);
+ PLAN_REGISTER(rename_many, two);
+ PLAN_REGISTER(rename_many, many);
+
+ PLAN_REGISTER(append_one, any);
+ PLAN_REGISTER(append_one, one);
+ PLAN_REGISTER(append_one, two);
+ PLAN_REGISTER(append_one, many);
+
+ PLAN_REGISTER(trunc_one, any);
+ PLAN_REGISTER(trunc_one, one);
+ PLAN_REGISTER(trunc_one, two);
+ PLAN_REGISTER(trunc_one, many);
+
+ PLAN_REGISTER(touch_one, any);
+ PLAN_REGISTER(touch_one, one);
+ PLAN_REGISTER(touch_one, two);
+ PLAN_REGISTER(touch_one, many);
+
+ return g_test_run();
+}
diff --git a/tests/uefi-test-tools/.gitignore b/tests/uefi-test-tools/.gitignore
new file mode 100644
index 0000000..9f24670
--- /dev/null
+++ b/tests/uefi-test-tools/.gitignore
@@ -0,0 +1,3 @@
+Build
+Conf
+log
diff --git a/tests/uefi-test-tools/LICENSE b/tests/uefi-test-tools/LICENSE
new file mode 100644
index 0000000..38b78ae
--- /dev/null
+++ b/tests/uefi-test-tools/LICENSE
@@ -0,0 +1,25 @@
+All the files in this directory and subdirectories are released under the
+2-Clause BSD License (see header in each file).
+
+Copyright (C) 2019, Red Hat, Inc.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+1. Redistributions of source code must retain the above copyright notice, this
+ list of conditions and the following disclaimer.
+
+2. Redistributions in binary form must reproduce the above copyright notice,
+ this list of conditions and the following disclaimer in the documentation
+ and/or other materials provided with the distribution.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
diff --git a/tests/uefi-test-tools/Makefile b/tests/uefi-test-tools/Makefile
new file mode 100644
index 0000000..1d78bc1
--- /dev/null
+++ b/tests/uefi-test-tools/Makefile
@@ -0,0 +1,106 @@
+# Makefile for the test helper UEFI applications that run in guests.
+#
+# Copyright (C) 2019, Red Hat, Inc.
+#
+# This program and the accompanying materials are licensed and made available
+# under the terms and conditions of the BSD License that accompanies this
+# distribution. The full text of the license may be found at
+# <http://opensource.org/licenses/bsd-license.php>.
+#
+# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, WITHOUT
+# WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+edk2_dir := ../../roms/edk2
+images_dir := ../data/uefi-boot-images
+emulation_targets := arm aarch64 i386 x86_64
+uefi_binaries := bios-tables-test
+intermediate_suffixes := .efi .fat .iso.raw
+
+images: $(foreach binary,$(uefi_binaries), \
+ $(foreach target,$(emulation_targets), \
+ $(images_dir)/$(binary).$(target).iso.qcow2))
+
+# Preserve all intermediate targets if the build succeeds.
+# - Intermediate targets help with development & debugging.
+# - Preserving intermediate targets also keeps spurious changes out of the
+# final build products, in case the user re-runs "make" without any changes
+# to the UEFI source code. Normally, the intermediate files would have been
+# removed by the last "make" invocation, hence the re-run would rebuild them
+# from the unchanged UEFI sources. Unfortunately, the "mkdosfs" and
+# "genisoimage" utilities embed timestamp-based information in their outputs,
+# which causes git to report differences for the tracked qcow2 ISO images.
+.SECONDARY: $(foreach binary,$(uefi_binaries), \
+ $(foreach target,$(emulation_targets), \
+ $(foreach suffix,$(intermediate_suffixes), \
+ Build/$(binary).$(target)$(suffix))))
+
+# In the pattern rules below, the stem (%, $*) stands for
+# "$(binary).$(target)".
+
+# Convert the raw ISO image to a qcow2 one, enabling compression, and using a
+# small cluster size. This allows for small binary files under git control,
+# hence for small binary patches.
+$(images_dir)/%.iso.qcow2: Build/%.iso.raw
+ mkdir -p -- $(images_dir)
+ $${QTEST_QEMU_IMG:-qemu-img} convert -f raw -O qcow2 -c \
+ -o cluster_size=512 -- $< $@
+
+# Embed the "UEFI system partition" into an ISO9660 file system as an ElTorito
+# boot image.
+Build/%.iso.raw: Build/%.fat
+ genisoimage -input-charset ASCII -efi-boot $(notdir $<) -no-emul-boot \
+ -quiet -o $@ -- $<
+
+# Define chained macros in order to map QEMU system emulation targets to
+# *short* UEFI architecture identifiers. Periods are allowed in, and ultimately
+# stripped from, the argument.
+map_arm_to_uefi = $(subst arm,ARM,$(1))
+map_aarch64_to_uefi = $(subst aarch64,AA64,$(call map_arm_to_uefi,$(1)))
+map_i386_to_uefi = $(subst i386,IA32,$(call map_aarch64_to_uefi,$(1)))
+map_x86_64_to_uefi = $(subst x86_64,X64,$(call map_i386_to_uefi,$(1)))
+map_to_uefi = $(subst .,,$(call map_x86_64_to_uefi,$(1)))
+
+# Format a "UEFI system partition", using the UEFI binary as the default boot
+# loader. Add 10% size for filesystem metadata, round up to the next KB, and
+# make sure the size is large enough for a FAT filesystem. Name the filesystem
+# after the UEFI binary. (Excess characters are automatically dropped from the
+# filesystem label.)
+Build/%.fat: Build/%.efi
+ rm -f -- $@
+ uefi_bin_b=$$(stat --format=%s -- $<) && \
+ uefi_fat_kb=$$(( (uefi_bin_b * 11 / 10 + 1023) / 1024 )) && \
+ uefi_fat_kb=$$(( uefi_fat_kb >= 64 ? uefi_fat_kb : 64 )) && \
+ mkdosfs -C $@ -n $(basename $(@F)) -- $$uefi_fat_kb
+ MTOOLS_SKIP_CHECK=1 mmd -i $@ ::EFI
+ MTOOLS_SKIP_CHECK=1 mmd -i $@ ::EFI/BOOT
+ MTOOLS_SKIP_CHECK=1 mcopy -i $@ -- $< \
+ ::EFI/BOOT/BOOT$(call map_to_uefi,$(suffix $*)).EFI
+
+# In the pattern rules below, the stem (%, $*) stands for "$(target)" only. The
+# association between the UEFI binary (such as "bios-tables-test") and the
+# component name from the edk2 platform DSC file (such as "BiosTablesTest") is
+# explicit in each rule.
+
+# "build.sh" invokes the "build" utility of edk2 BaseTools. In any given edk2
+# workspace, at most one "build" instance may be operating at a time. Therefore
+# we must serialize the rebuilding of targets in this Makefile.
+.NOTPARALLEL:
+
+# In turn, the "build" utility of edk2 BaseTools invokes another "make".
+# Although the outer "make" process advertizes its job server to all child
+# processes via MAKEFLAGS in the environment, the outer "make" closes the job
+# server file descriptors (exposed in MAKEFLAGS) before executing a recipe --
+# unless the recipe is recognized as a recursive "make" recipe. Recipes that
+# call $(MAKE) are classified automatically as recursive; for "build.sh" below,
+# we must mark the recipe manually as recursive, by using the "+" indicator.
+# This way, when the inner "make" starts a parallel build of the target edk2
+# module, it can communicate with the outer "make"'s job server.
+Build/bios-tables-test.%.efi: build-edk2-tools
+ +./build.sh $(edk2_dir) BiosTablesTest $* $@
+
+build-edk2-tools:
+ $(MAKE) -C $(edk2_dir)/BaseTools
+
+clean:
+ rm -rf Build Conf log
+ $(MAKE) -C $(edk2_dir)/BaseTools clean
diff --git a/tests/uefi-test-tools/UefiTestToolsPkg/BiosTablesTest/BiosTablesTest.c b/tests/uefi-test-tools/UefiTestToolsPkg/BiosTablesTest/BiosTablesTest.c
new file mode 100644
index 0000000..b208e17
--- /dev/null
+++ b/tests/uefi-test-tools/UefiTestToolsPkg/BiosTablesTest/BiosTablesTest.c
@@ -0,0 +1,130 @@
+/** @file
+ Populate the BIOS_TABLES_TEST structure.
+
+ Copyright (C) 2019, Red Hat, Inc.
+
+ This program and the accompanying materials are licensed and made available
+ under the terms and conditions of the BSD License that accompanies this
+ distribution. The full text of the license may be found at
+ <http://opensource.org/licenses/bsd-license.php>.
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, WITHOUT
+ WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+**/
+
+#include <Guid/Acpi.h>
+#include <Guid/BiosTablesTest.h>
+#include <Library/BaseLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/UefiLib.h>
+
+/**
+ Wait for a keypress with a message that the application is about to exit.
+**/
+STATIC
+VOID
+WaitForExitKeyPress (
+ VOID
+ )
+{
+ EFI_STATUS Status;
+ UINTN Idx;
+ EFI_INPUT_KEY Key;
+
+ if (gST->ConIn == NULL) {
+ return;
+ }
+ AsciiPrint ("%a: press any key to exit\n", gEfiCallerBaseName);
+ Status = gBS->WaitForEvent (1, &gST->ConIn->WaitForKey, &Idx);
+ if (EFI_ERROR (Status)) {
+ return;
+ }
+ gST->ConIn->ReadKeyStroke (gST->ConIn, &Key);
+}
+
+EFI_STATUS
+EFIAPI
+BiosTablesTestMain (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+{
+ VOID *Pages;
+ volatile BIOS_TABLES_TEST *BiosTablesTest;
+ CONST VOID *Rsdp10;
+ CONST VOID *Rsdp20;
+ CONST EFI_CONFIGURATION_TABLE *ConfigTable;
+ CONST EFI_CONFIGURATION_TABLE *ConfigTablesEnd;
+ volatile EFI_GUID *InverseSignature;
+ UINTN Idx;
+
+ Pages = AllocateAlignedPages (EFI_SIZE_TO_PAGES (sizeof *BiosTablesTest),
+ SIZE_1MB);
+ if (Pages == NULL) {
+ AsciiErrorPrint ("%a: AllocateAlignedPages() failed\n",
+ gEfiCallerBaseName);
+ //
+ // Assuming the application was launched by the boot manager as a boot
+ // loader, exiting with error will cause the boot manager to proceed with
+ // the remaining boot options. If there are no other boot options, the boot
+ // manager menu will be pulled up. Give the user a chance to read the error
+ // message.
+ //
+ WaitForExitKeyPress ();
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ //
+ // Locate both gEfiAcpi10TableGuid and gEfiAcpi20TableGuid config tables in
+ // one go.
+ //
+ Rsdp10 = NULL;
+ Rsdp20 = NULL;
+ ConfigTable = gST->ConfigurationTable;
+ ConfigTablesEnd = gST->ConfigurationTable + gST->NumberOfTableEntries;
+ while ((Rsdp10 == NULL || Rsdp20 == NULL) && ConfigTable < ConfigTablesEnd) {
+ if (CompareGuid (&ConfigTable->VendorGuid, &gEfiAcpi10TableGuid)) {
+ Rsdp10 = ConfigTable->VendorTable;
+ } else if (CompareGuid (&ConfigTable->VendorGuid, &gEfiAcpi20TableGuid)) {
+ Rsdp20 = ConfigTable->VendorTable;
+ }
+ ++ConfigTable;
+ }
+
+ AsciiPrint ("%a: BiosTablesTest=%p Rsdp10=%p Rsdp20=%p\n",
+ gEfiCallerBaseName, Pages, Rsdp10, Rsdp20);
+
+ //
+ // Store the RSD PTR address(es) first, then the signature second.
+ //
+ BiosTablesTest = Pages;
+ BiosTablesTest->Rsdp10 = (UINTN)Rsdp10;
+ BiosTablesTest->Rsdp20 = (UINTN)Rsdp20;
+
+ MemoryFence();
+
+ InverseSignature = &BiosTablesTest->InverseSignatureGuid;
+ InverseSignature->Data1 = gBiosTablesTestGuid.Data1;
+ InverseSignature->Data1 ^= MAX_UINT32;
+ InverseSignature->Data2 = gBiosTablesTestGuid.Data2;
+ InverseSignature->Data2 ^= MAX_UINT16;
+ InverseSignature->Data3 = gBiosTablesTestGuid.Data3;
+ InverseSignature->Data3 ^= MAX_UINT16;
+ for (Idx = 0; Idx < sizeof InverseSignature->Data4; ++Idx) {
+ InverseSignature->Data4[Idx] = gBiosTablesTestGuid.Data4[Idx];
+ InverseSignature->Data4[Idx] ^= MAX_UINT8;
+ }
+
+ //
+ // The wait below has dual purpose. First, it blocks the application without
+ // wasting VCPU cycles while the hypervisor is scanning guest RAM. Second,
+ // assuming the application was launched by the boot manager as a boot
+ // loader, exiting the app with success causes the boot manager to pull up
+ // the boot manager menu at once (regardless of other boot options); the wait
+ // gives the user a chance to read the info printed above.
+ //
+ WaitForExitKeyPress ();
+ return EFI_SUCCESS;
+}
diff --git a/tests/uefi-test-tools/UefiTestToolsPkg/BiosTablesTest/BiosTablesTest.inf b/tests/uefi-test-tools/UefiTestToolsPkg/BiosTablesTest/BiosTablesTest.inf
new file mode 100644
index 0000000..924d8a8
--- /dev/null
+++ b/tests/uefi-test-tools/UefiTestToolsPkg/BiosTablesTest/BiosTablesTest.inf
@@ -0,0 +1,41 @@
+## @file
+# Populate the BIOS_TABLES_TEST structure.
+#
+# Copyright (C) 2019, Red Hat, Inc.
+#
+# This program and the accompanying materials are licensed and made available
+# under the terms and conditions of the BSD License that accompanies this
+# distribution. The full text of the license may be found at
+# <http://opensource.org/licenses/bsd-license.php>.
+#
+# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, WITHOUT
+# WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+##
+
+[Defines]
+ INF_VERSION = 1.27
+ BASE_NAME = BiosTablesTest
+ UEFI_SPECIFICATION_VERSION = 2.31
+ FILE_GUID = 87f00433-3b7c-45c3-ae78-a56495bd4e62
+ MODULE_TYPE = UEFI_APPLICATION
+ ENTRY_POINT = BiosTablesTestMain
+
+[Sources]
+ BiosTablesTest.c
+
+[LibraryClasses]
+ BaseLib
+ BaseMemoryLib
+ MemoryAllocationLib
+ UefiApplicationEntryPoint
+ UefiBootServicesTableLib
+ UefiLib
+
+[Guids]
+ gBiosTablesTestGuid
+ gEfiAcpi10TableGuid
+ gEfiAcpi20TableGuid
+
+[Packages]
+ MdePkg/MdePkg.dec
+ UefiTestToolsPkg/UefiTestToolsPkg.dec
diff --git a/tests/uefi-test-tools/UefiTestToolsPkg/Include/Guid/BiosTablesTest.h b/tests/uefi-test-tools/UefiTestToolsPkg/Include/Guid/BiosTablesTest.h
new file mode 100644
index 0000000..0b72c61
--- /dev/null
+++ b/tests/uefi-test-tools/UefiTestToolsPkg/Include/Guid/BiosTablesTest.h
@@ -0,0 +1,67 @@
+/** @file
+ Expose the address(es) of the ACPI RSD PTR table(s) in a MB-aligned structure
+ to the hypervisor.
+
+ The hypervisor locates the MB-aligned structure based on the signature GUID
+ that is at offset 0 in the structure. Once the RSD PTR address(es) are
+ retrieved, the hypervisor may perform various ACPI checks.
+
+ This feature is a development aid, for supporting ACPI table unit tests in
+ hypervisors. Do not enable in production builds.
+
+ Copyright (C) 2019, Red Hat, Inc.
+
+ This program and the accompanying materials are licensed and made available
+ under the terms and conditions of the BSD License that accompanies this
+ distribution. The full text of the license may be found at
+ <http://opensource.org/licenses/bsd-license.php>.
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, WITHOUT
+ WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+**/
+
+#ifndef __BIOS_TABLES_TEST_H__
+#define __BIOS_TABLES_TEST_H__
+
+#include <Uefi/UefiBaseType.h>
+
+#define BIOS_TABLES_TEST_GUID \
+ { \
+ 0x5478594e, \
+ 0xdfcb, \
+ 0x425f, \
+ { 0x8e, 0x42, 0xc8, 0xaf, 0xf8, 0x8a, 0x88, 0x7a } \
+ }
+
+extern EFI_GUID gBiosTablesTestGuid;
+
+//
+// The following structure must be allocated in Boot Services Data type memory,
+// aligned at a 1MB boundary.
+//
+#pragma pack (1)
+typedef struct {
+ //
+ // The signature GUID is written to the MB-aligned structure from
+ // gBiosTablesTestGuid, but with all bits inverted. That's the actual GUID
+ // value that the hypervisor should look for at each MB boundary, looping
+ // over all guest RAM pages with that alignment, until a match is found. The
+ // bit-flipping occurs in order not to store the actual GUID in any UEFI
+ // executable, which might confuse guest memory analysis. Note that EFI_GUID
+ // has little endian representation.
+ //
+ EFI_GUID InverseSignatureGuid;
+ //
+ // The Rsdp10 and Rsdp20 fields may be read when the signature GUID matches.
+ // Rsdp10 is the guest-physical address of the ACPI 1.0 specification RSD PTR
+ // table, in 8-byte little endian representation. Rsdp20 is the same, for the
+ // ACPI 2.0 or later specification RSD PTR table. Each of these fields may be
+ // zero (independently of the other) if the UEFI System Table does not
+ // provide the corresponding UEFI Configuration Table.
+ //
+ EFI_PHYSICAL_ADDRESS Rsdp10;
+ EFI_PHYSICAL_ADDRESS Rsdp20;
+} BIOS_TABLES_TEST;
+#pragma pack ()
+
+#endif // __BIOS_TABLES_TEST_H__
diff --git a/tests/uefi-test-tools/UefiTestToolsPkg/UefiTestToolsPkg.dec b/tests/uefi-test-tools/UefiTestToolsPkg/UefiTestToolsPkg.dec
new file mode 100644
index 0000000..ed3a2fe
--- /dev/null
+++ b/tests/uefi-test-tools/UefiTestToolsPkg/UefiTestToolsPkg.dec
@@ -0,0 +1,27 @@
+## @file
+# edk2 package declaration for the test helper UEFI applications that run in
+# guests.
+#
+# Copyright (C) 2019, Red Hat, Inc.
+#
+# This program and the accompanying materials are licensed and made available
+# under the terms and conditions of the BSD License that accompanies this
+# distribution. The full text of the license may be found at
+# <http://opensource.org/licenses/bsd-license.php>.
+#
+# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, WITHOUT
+# WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+##
+
+[Defines]
+ DEC_SPECIFICATION = 1.27
+ PACKAGE_NAME = UefiTestToolsPkg
+ PACKAGE_GUID = 7b3f1794-0c85-4b27-a536-44dbf0b0669c
+ PACKAGE_VERSION = 0.1
+
+[Includes]
+ Include
+
+[Guids]
+ gBiosTablesTestGuid = {0x5478594e, 0xdfcb, 0x425f, {0x8e, 0x42, 0xc8, 0xaf, 0xf8, 0x8a, 0x88, 0x7a}}
+
diff --git a/tests/uefi-test-tools/UefiTestToolsPkg/UefiTestToolsPkg.dsc b/tests/uefi-test-tools/UefiTestToolsPkg/UefiTestToolsPkg.dsc
new file mode 100644
index 0000000..c8511cd
--- /dev/null
+++ b/tests/uefi-test-tools/UefiTestToolsPkg/UefiTestToolsPkg.dsc
@@ -0,0 +1,69 @@
+## @file
+# edk2 platform description for the test helper UEFI applications that run in
+# guests.
+#
+# Copyright (C) 2019, Red Hat, Inc.
+#
+# This program and the accompanying materials are licensed and made available
+# under the terms and conditions of the BSD License that accompanies this
+# distribution. The full text of the license may be found at
+# <http://opensource.org/licenses/bsd-license.php>.
+#
+# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, WITHOUT
+# WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+##
+
+[Defines]
+ DSC_SPECIFICATION = 1.28
+ PLATFORM_GUID = 6750ccc1-8365-49f0-8437-948e516a9f55
+ PLATFORM_VERSION = 0.1
+ PLATFORM_NAME = UefiTestTools
+ SKUID_IDENTIFIER = DEFAULT
+ SUPPORTED_ARCHITECTURES = ARM|AARCH64|IA32|X64
+ BUILD_TARGETS = DEBUG
+
+[BuildOptions.IA32]
+ GCC:*_*_IA32_CC_FLAGS = -mno-mmx -mno-sse
+
+[BuildOptions.X64]
+ GCC:*_*_X64_CC_FLAGS = -mno-mmx -mno-sse
+
+[BuildOptions.ARM.EDKII.UEFI_APPLICATION]
+ GCC:*_*_ARM_DLINK_FLAGS = -z common-page-size=0x1000
+
+[BuildOptions.AARCH64.EDKII.UEFI_APPLICATION]
+ GCC:*_*_AARCH64_DLINK_FLAGS = -z common-page-size=0x1000
+
+[BuildOptions]
+ GCC:*_*_*_CC_FLAGS = -D DISABLE_NEW_DEPRECATED_INTERFACES
+
+[SkuIds]
+ 0|DEFAULT
+
+[LibraryClasses]
+ BaseLib|MdePkg/Library/BaseLib/BaseLib.inf
+ DebugLib|MdePkg/Library/UefiDebugLibConOut/UefiDebugLibConOut.inf
+ DebugPrintErrorLevelLib|MdePkg/Library/BaseDebugPrintErrorLevelLib/BaseDebugPrintErrorLevelLib.inf
+ DevicePathLib|MdePkg/Library/UefiDevicePathLibDevicePathProtocol/UefiDevicePathLibDevicePathProtocol.inf
+ MemoryAllocationLib|MdePkg/Library/UefiMemoryAllocationLib/UefiMemoryAllocationLib.inf
+ PcdLib|MdePkg/Library/BasePcdLibNull/BasePcdLibNull.inf
+ PrintLib|MdePkg/Library/BasePrintLib/BasePrintLib.inf
+ UefiApplicationEntryPoint|MdePkg/Library/UefiApplicationEntryPoint/UefiApplicationEntryPoint.inf
+ UefiBootServicesTableLib|MdePkg/Library/UefiBootServicesTableLib/UefiBootServicesTableLib.inf
+ UefiLib|MdePkg/Library/UefiLib/UefiLib.inf
+ UefiRuntimeServicesTableLib|MdePkg/Library/UefiRuntimeServicesTableLib/UefiRuntimeServicesTableLib.inf
+
+[LibraryClasses.ARM, LibraryClasses.AARCH64]
+ BaseMemoryLib|MdePkg/Library/BaseMemoryLibOptDxe/BaseMemoryLibOptDxe.inf
+ NULL|ArmPkg/Library/CompilerIntrinsicsLib/CompilerIntrinsicsLib.inf
+ NULL|MdePkg/Library/BaseStackCheckLib/BaseStackCheckLib.inf
+
+[LibraryClasses.IA32, LibraryClasses.X64]
+ BaseMemoryLib|MdePkg/Library/BaseMemoryLibRepStr/BaseMemoryLibRepStr.inf
+
+[PcdsFixedAtBuild]
+ gEfiMdePkgTokenSpaceGuid.PcdDebugPrintErrorLevel|0x8040004F
+ gEfiMdePkgTokenSpaceGuid.PcdDebugPropertyMask|0x2F
+
+[Components]
+ UefiTestToolsPkg/BiosTablesTest/BiosTablesTest.inf
diff --git a/tests/uefi-test-tools/build.sh b/tests/uefi-test-tools/build.sh
new file mode 100755
index 0000000..155cb75
--- /dev/null
+++ b/tests/uefi-test-tools/build.sh
@@ -0,0 +1,145 @@
+#!/bin/bash
+
+# Build script that determines the edk2 toolchain to use, invokes the edk2
+# "build" utility, and copies the built UEFI binary to the requested location.
+#
+# Copyright (C) 2019, Red Hat, Inc.
+#
+# This program and the accompanying materials are licensed and made available
+# under the terms and conditions of the BSD License that accompanies this
+# distribution. The full text of the license may be found at
+# <http://opensource.org/licenses/bsd-license.php>.
+#
+# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, WITHOUT
+# WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+set -e -u -C
+
+# Save the command line arguments. We need to reset $# to 0 before sourcing
+# "edksetup.sh", as it will inherit $@.
+program_name=$(basename -- "$0")
+edk2_dir=$1
+dsc_component=$2
+emulation_target=$3
+uefi_binary=$4
+shift 4
+
+# Set up the environment for edk2 building.
+export PACKAGES_PATH=$(realpath -- "$edk2_dir")
+export WORKSPACE=$PWD
+mkdir -p Conf
+
+# Source "edksetup.sh" carefully.
+set +e +u +C
+source "$PACKAGES_PATH/edksetup.sh"
+ret=$?
+set -e -u -C
+if [ $ret -ne 0 ]; then
+ exit $ret
+fi
+
+# Map the QEMU system emulation target to the following types of architecture
+# identifiers:
+# - edk2,
+# - gcc cross-compilation.
+# Cover only those targets that are supported by the UEFI spec and edk2.
+case "$emulation_target" in
+ (arm)
+ edk2_arch=ARM
+ gcc_arch=arm
+ ;;
+ (aarch64)
+ edk2_arch=AARCH64
+ gcc_arch=aarch64
+ ;;
+ (i386)
+ edk2_arch=IA32
+ gcc_arch=i686
+ ;;
+ (x86_64)
+ edk2_arch=X64
+ gcc_arch=x86_64
+ ;;
+ (*)
+ printf '%s: unknown/unsupported QEMU system emulation target "%s"\n' \
+ "$program_name" "$emulation_target" >&2
+ exit 1
+ ;;
+esac
+
+# Check if cross-compilation is needed.
+host_arch=$(uname -m)
+if [ "$gcc_arch" == "$host_arch" ] ||
+ ( [ "$gcc_arch" == i686 ] && [ "$host_arch" == x86_64 ] ); then
+ cross_prefix=
+else
+ cross_prefix=${gcc_arch}-linux-gnu-
+fi
+
+# Expose cross_prefix (which is possibly empty) to the edk2 tools. While at it,
+# determine the suitable edk2 toolchain as well.
+# - For ARM and AARCH64, edk2 only offers the GCC5 toolchain tag, which covers
+# the gcc-5+ releases.
+# - For IA32 and X64, edk2 offers the GCC44 through GCC49 toolchain tags, in
+# addition to GCC5. Unfortunately, the mapping between the toolchain tags and
+# the actual gcc releases isn't entirely trivial. Run "git-blame" on
+# "OvmfPkg/build.sh" in edk2 for more information.
+# And, because the above is too simple, we have to assign cross_prefix to an
+# edk2 build variable that is specific to both the toolchain tag and the target
+# architecture.
+case "$edk2_arch" in
+ (ARM)
+ edk2_toolchain=GCC5
+ export GCC5_ARM_PREFIX=$cross_prefix
+ ;;
+ (AARCH64)
+ edk2_toolchain=GCC5
+ export GCC5_AARCH64_PREFIX=$cross_prefix
+ ;;
+ (IA32|X64)
+ gcc_version=$("${cross_prefix}gcc" -v 2>&1 | tail -1 | awk '{print $3}')
+ case "$gcc_version" in
+ ([1-3].*|4.[0-3].*)
+ printf '%s: unsupported gcc version "%s"\n' \
+ "$program_name" "$gcc_version" >&2
+ exit 1
+ ;;
+ (4.4.*)
+ edk2_toolchain=GCC44
+ ;;
+ (4.5.*)
+ edk2_toolchain=GCC45
+ ;;
+ (4.6.*)
+ edk2_toolchain=GCC46
+ ;;
+ (4.7.*)
+ edk2_toolchain=GCC47
+ ;;
+ (4.8.*)
+ edk2_toolchain=GCC48
+ ;;
+ (4.9.*|6.[0-2].*)
+ edk2_toolchain=GCC49
+ ;;
+ (*)
+ edk2_toolchain=GCC5
+ ;;
+ esac
+ eval "export ${edk2_toolchain}_BIN=\$cross_prefix"
+ ;;
+esac
+
+# Build the UEFI binary
+mkdir -p log
+build \
+ --arch="$edk2_arch" \
+ --buildtarget=DEBUG \
+ --platform=UefiTestToolsPkg/UefiTestToolsPkg.dsc \
+ --tagname="$edk2_toolchain" \
+ --module="UefiTestToolsPkg/$dsc_component/$dsc_component.inf" \
+ --log="log/$dsc_component.$edk2_arch.log" \
+ --report-file="log/$dsc_component.$edk2_arch.report"
+cp -a -- \
+ "Build/UefiTestTools/DEBUG_${edk2_toolchain}/$edk2_arch/$dsc_component.efi" \
+ "$uefi_binary"
diff --git a/tests/vhost-user-test.c b/tests/vhost-user-test.c
index d961bd0..4cd0a97 100644
--- a/tests/vhost-user-test.c
+++ b/tests/vhost-user-test.c
@@ -27,10 +27,13 @@
#include "libqos/malloc-pc.h"
#include "hw/virtio/virtio-net.h"
-#include <linux/vhost.h>
-#include <linux/virtio_ids.h>
-#include <linux/virtio_net.h>
+#include "standard-headers/linux/vhost_types.h"
+#include "standard-headers/linux/virtio_ids.h"
+#include "standard-headers/linux/virtio_net.h"
+
+#ifdef CONFIG_LINUX
#include <sys/vfs.h>
+#endif
#define QEMU_CMD_MEM " -m %d -object memory-backend-file,id=mem,size=%dM," \
@@ -139,10 +142,15 @@
gchar *socket_path;
gchar *mig_path;
gchar *chr_name;
+ const gchar *mem_path;
+ gchar *tmpfs;
CharBackend chr;
int fds_num;
int fds[VHOST_MEMORY_MAX_NREGIONS];
VhostUserMemory memory;
+ GMainContext *context;
+ GMainLoop *loop;
+ GThread *thread;
GMutex data_mutex;
GCond data_cond;
int log_fd;
@@ -157,9 +165,6 @@
static void test_server_free(TestServer *server);
static void test_server_listen(TestServer *server);
-static const char *tmpfs;
-static const char *root;
-
enum test_memfd {
TEST_MEMFD_AUTO,
TEST_MEMFD_YES,
@@ -167,7 +172,7 @@
};
static char *get_qemu_cmd(TestServer *s,
- int mem, enum test_memfd memfd, const char *mem_path,
+ int mem, enum test_memfd memfd,
const char *chr_opts, const char *extra)
{
if (memfd == TEST_MEMFD_AUTO && qemu_memfd_check(0)) {
@@ -182,7 +187,7 @@
} else {
return g_strdup_printf(QEMU_CMD_MEM QEMU_CMD_CHR
QEMU_CMD_NETDEV QEMU_CMD_NET "%s", mem, mem,
- mem_path, s->chr_name, s->socket_path,
+ s->mem_path, s->chr_name, s->socket_path,
chr_opts, s->chr_name, extra);
}
}
@@ -459,13 +464,20 @@
g_mutex_unlock(&s->data_mutex);
}
-static const char *init_hugepagefs(const char *path)
+static const char *init_hugepagefs(void)
{
+#ifdef CONFIG_LINUX
+ const char *path = getenv("QTEST_HUGETLBFS_PATH");
struct statfs fs;
int ret;
+ if (!path) {
+ return NULL;
+ }
+
if (access(path, R_OK | W_OK | X_OK)) {
g_test_message("access on path (%s): %s\n", path, strerror(errno));
+ abort();
return NULL;
}
@@ -475,21 +487,42 @@
if (ret != 0) {
g_test_message("statfs on path (%s): %s\n", path, strerror(errno));
+ abort();
return NULL;
}
if (fs.f_type != HUGETLBFS_MAGIC) {
g_test_message("Warning: path not on HugeTLBFS: %s\n", path);
+ abort();
return NULL;
}
return path;
+#else
+ return NULL;
+#endif
}
static TestServer *test_server_new(const gchar *name)
{
TestServer *server = g_new0(TestServer, 1);
+ char template[] = "/tmp/vhost-test-XXXXXX";
+ const char *tmpfs;
+ server->context = g_main_context_new();
+ server->loop = g_main_loop_new(server->context, FALSE);
+
+ /* run the main loop thread so the chardev may operate */
+ server->thread = g_thread_new(NULL, thread_function, server->loop);
+
+ tmpfs = mkdtemp(template);
+ if (!tmpfs) {
+ g_test_message("mkdtemp on path (%s): %s", template, strerror(errno));
+ }
+ g_assert(tmpfs);
+
+ server->tmpfs = g_strdup(tmpfs);
+ server->mem_path = init_hugepagefs() ? : server->tmpfs;
server->socket_path = g_strdup_printf("%s/%s.sock", tmpfs, name);
server->mig_path = g_strdup_printf("%s/%s.mig", tmpfs, name);
server->chr_name = g_strdup_printf("chr-%s", name);
@@ -519,13 +552,13 @@
Chardev *chr;
chr_path = g_strdup_printf("unix:%s%s", server->socket_path, opt);
- chr = qemu_chr_new(server->chr_name, chr_path, NULL);
+ chr = qemu_chr_new(server->chr_name, chr_path, server->context);
g_free(chr_path);
g_assert_nonnull(chr);
qemu_chr_fe_init(&server->chr, chr, &error_abort);
qemu_chr_fe_set_handlers(&server->chr, chr_can_read, chr_read,
- chr_event, NULL, server, NULL, true);
+ chr_event, NULL, server, server->context, true);
}
static void test_server_listen(TestServer *server)
@@ -533,9 +566,28 @@
test_server_create_chr(server, ",server,nowait");
}
-static gboolean _test_server_free(TestServer *server)
+static void test_server_free(TestServer *server)
{
- int i;
+ int i, ret;
+
+ /* finish the helper thread and dispatch pending sources */
+ g_main_loop_quit(server->loop);
+ g_thread_join(server->thread);
+ while (g_main_context_pending(NULL)) {
+ g_main_context_iteration(NULL, TRUE);
+ }
+
+ unlink(server->socket_path);
+ g_free(server->socket_path);
+
+ unlink(server->mig_path);
+ g_free(server->mig_path);
+
+ ret = rmdir(server->tmpfs);
+ if (ret != 0) {
+ g_test_message("unable to rmdir: path (%s): %s",
+ server->tmpfs, strerror(errno));
+ }
qemu_chr_fe_deinit(&server->chr, true);
@@ -547,24 +599,13 @@
close(server->log_fd);
}
- unlink(server->socket_path);
- g_free(server->socket_path);
-
- unlink(server->mig_path);
- g_free(server->mig_path);
-
g_free(server->chr_name);
g_assert(server->bus);
qpci_free_pc(server->bus);
+ g_main_loop_unref(server->loop);
+ g_main_context_unref(server->context);
g_free(server);
-
- return FALSE;
-}
-
-static void test_server_free(TestServer *server)
-{
- g_idle_add((GSourceFunc)_test_server_free, server);
}
static void wait_for_log_fd(TestServer *s)
@@ -665,7 +706,7 @@
"read-guest-memfd" : "read-guest-mem");
test_server_listen(server);
- qemu_cmd = get_qemu_cmd(server, 512, memfd, root, "", "");
+ qemu_cmd = get_qemu_cmd(server, 512, memfd, "", "");
s = qtest_start(qemu_cmd);
g_free(qemu_cmd);
@@ -700,7 +741,7 @@
test_server_listen(s);
test_server_listen(dest);
- cmd = get_qemu_cmd(s, 2, TEST_MEMFD_AUTO, root, "", "");
+ cmd = get_qemu_cmd(s, 2, TEST_MEMFD_AUTO, "", "");
from = qtest_start(cmd);
g_free(cmd);
@@ -713,7 +754,7 @@
g_assert_cmpint(size, ==, (2 * 1024 * 1024) / (VHOST_LOG_PAGE * 8));
tmp = g_strdup_printf(" -incoming %s", uri);
- cmd = get_qemu_cmd(dest, 2, TEST_MEMFD_AUTO, root, "", tmp);
+ cmd = get_qemu_cmd(dest, 2, TEST_MEMFD_AUTO, "", tmp);
g_free(tmp);
to = qtest_init(cmd);
g_free(cmd);
@@ -723,7 +764,7 @@
sizeof(TestMigrateSource));
((TestMigrateSource *)source)->src = s;
((TestMigrateSource *)source)->dest = dest;
- g_source_attach(source, NULL);
+ g_source_attach(source, s->context);
/* slow down migration to have time to fiddle with log */
/* TODO: qtest could learn to break on some places */
@@ -820,10 +861,11 @@
static void test_reconnect_subprocess(void)
{
TestServer *s = test_server_new("reconnect");
+ GSource *src;
char *cmd;
g_thread_new("connect", connect_thread, s);
- cmd = get_qemu_cmd(s, 2, TEST_MEMFD_AUTO, root, ",server", "");
+ cmd = get_qemu_cmd(s, 2, TEST_MEMFD_AUTO, ",server", "");
qtest_start(cmd);
g_free(cmd);
@@ -837,7 +879,10 @@
/* reconnect */
s->fds_num = 0;
s->rings = 0;
- g_idle_add(reconnect_cb, s);
+ src = g_idle_source_new();
+ g_source_set_callback(src, reconnect_cb, s, NULL);
+ g_source_attach(src, s->context);
+ g_source_unref(src);
g_assert(wait_for_fds(s));
wait_for_rings_started(s, 2);
@@ -865,7 +910,7 @@
s->test_fail = true;
g_thread_new("connect", connect_thread, s);
- cmd = get_qemu_cmd(s, 2, TEST_MEMFD_AUTO, root, ",server", "");
+ cmd = get_qemu_cmd(s, 2, TEST_MEMFD_AUTO, ",server", "");
qtest_start(cmd);
g_free(cmd);
@@ -898,7 +943,7 @@
s->test_flags = TEST_FLAGS_DISCONNECT;
g_thread_new("connect", connect_thread, s);
- cmd = get_qemu_cmd(s, 2, TEST_MEMFD_AUTO, root, ",server", "");
+ cmd = get_qemu_cmd(s, 2, TEST_MEMFD_AUTO, ",server", "");
qtest_start(cmd);
g_free(cmd);
@@ -946,7 +991,7 @@
cmd = g_strdup_printf(
QEMU_CMD_MEM QEMU_CMD_CHR QEMU_CMD_NETDEV ",queues=%d "
"-device virtio-net-pci,netdev=net0,mq=on,vectors=%d",
- 512, 512, root, s->chr_name,
+ 512, 512, s->mem_path, s->chr_name,
s->socket_path, "", s->chr_name,
s->queues, s->queues * 2 + 2);
}
@@ -966,35 +1011,11 @@
int main(int argc, char **argv)
{
- const char *hugefs;
- int ret;
- char template[] = "/tmp/vhost-test-XXXXXX";
- GMainLoop *loop;
- GThread *thread;
-
g_test_init(&argc, &argv, NULL);
module_call_init(MODULE_INIT_QOM);
qemu_add_opts(&qemu_chardev_opts);
- tmpfs = mkdtemp(template);
- if (!tmpfs) {
- g_test_message("mkdtemp on path (%s): %s\n", template, strerror(errno));
- }
- g_assert(tmpfs);
-
- hugefs = getenv("QTEST_HUGETLBFS_PATH");
- if (hugefs) {
- root = init_hugepagefs(hugefs);
- g_assert(root);
- } else {
- root = tmpfs;
- }
-
- loop = g_main_loop_new(NULL, FALSE);
- /* run the main loop thread so the chardev may operate */
- thread = g_thread_new(NULL, thread_function, loop);
-
if (qemu_memfd_check(0)) {
qtest_add_data_func("/vhost-user/read-guest-mem/memfd",
GINT_TO_POINTER(TEST_MEMFD_YES),
@@ -1018,24 +1039,5 @@
qtest_add_func("/vhost-user/flags-mismatch", test_flags_mismatch);
}
- ret = g_test_run();
-
- /* cleanup */
-
- /* finish the helper thread and dispatch pending sources */
- g_main_loop_quit(loop);
- g_thread_join(thread);
- while (g_main_context_pending(NULL)) {
- g_main_context_iteration (NULL, TRUE);
- }
- g_main_loop_unref(loop);
-
- ret = rmdir(tmpfs);
- if (ret != 0) {
- g_test_message("unable to rmdir: path (%s): %s\n",
- tmpfs, strerror(errno));
- }
- g_assert_cmpint(ret, ==, 0);
-
- return ret;
+ return g_test_run();
}
diff --git a/tests/virtio-blk-test.c b/tests/virtio-blk-test.c
index 04c6087..8d2fc9c 100644
--- a/tests/virtio-blk-test.c
+++ b/tests/virtio-blk-test.c
@@ -46,6 +46,12 @@
uint8_t status;
} QVirtioBlkReq;
+#ifdef HOST_WORDS_BIGENDIAN
+const bool host_is_big_endian = true;
+#else
+const bool host_is_big_endian; /* false */
+#endif
+
static char *drive_create(void)
{
int fd, ret;
@@ -125,12 +131,6 @@
static inline void virtio_blk_fix_request(QVirtioDevice *d, QVirtioBlkReq *req)
{
-#ifdef HOST_WORDS_BIGENDIAN
- const bool host_is_big_endian = true;
-#else
- const bool host_is_big_endian = false;
-#endif
-
if (qvirtio_is_big_endian(d) != host_is_big_endian) {
req->type = bswap32(req->type);
req->ioprio = bswap32(req->ioprio);
@@ -138,13 +138,37 @@
}
}
+
+static inline void virtio_blk_fix_dwz_hdr(QVirtioDevice *d,
+ struct virtio_blk_discard_write_zeroes *dwz_hdr)
+{
+ if (qvirtio_is_big_endian(d) != host_is_big_endian) {
+ dwz_hdr->sector = bswap64(dwz_hdr->sector);
+ dwz_hdr->num_sectors = bswap32(dwz_hdr->num_sectors);
+ dwz_hdr->flags = bswap32(dwz_hdr->flags);
+ }
+}
+
static uint64_t virtio_blk_request(QGuestAllocator *alloc, QVirtioDevice *d,
QVirtioBlkReq *req, uint64_t data_size)
{
uint64_t addr;
uint8_t status = 0xFF;
- g_assert_cmpuint(data_size % 512, ==, 0);
+ switch (req->type) {
+ case VIRTIO_BLK_T_IN:
+ case VIRTIO_BLK_T_OUT:
+ g_assert_cmpuint(data_size % 512, ==, 0);
+ break;
+ case VIRTIO_BLK_T_DISCARD:
+ case VIRTIO_BLK_T_WRITE_ZEROES:
+ g_assert_cmpuint(data_size %
+ sizeof(struct virtio_blk_discard_write_zeroes), ==, 0);
+ break;
+ default:
+ g_assert_cmpuint(data_size, ==, 0);
+ }
+
addr = guest_alloc(alloc, sizeof(*req) + data_size);
virtio_blk_fix_request(d, req);
@@ -231,6 +255,95 @@
guest_free(alloc, req_addr);
+ if (features & (1u << VIRTIO_BLK_F_WRITE_ZEROES)) {
+ struct virtio_blk_discard_write_zeroes dwz_hdr;
+ void *expected;
+
+ /*
+ * WRITE_ZEROES request on the same sector of previous test where
+ * we wrote "TEST".
+ */
+ req.type = VIRTIO_BLK_T_WRITE_ZEROES;
+ req.data = (char *) &dwz_hdr;
+ dwz_hdr.sector = 0;
+ dwz_hdr.num_sectors = 1;
+ dwz_hdr.flags = 0;
+
+ virtio_blk_fix_dwz_hdr(dev, &dwz_hdr);
+
+ req_addr = virtio_blk_request(alloc, dev, &req, sizeof(dwz_hdr));
+
+ free_head = qvirtqueue_add(vq, req_addr, 16, false, true);
+ qvirtqueue_add(vq, req_addr + 16, sizeof(dwz_hdr), false, true);
+ qvirtqueue_add(vq, req_addr + 16 + sizeof(dwz_hdr), 1, true, false);
+
+ qvirtqueue_kick(dev, vq, free_head);
+
+ qvirtio_wait_used_elem(dev, vq, free_head, NULL,
+ QVIRTIO_BLK_TIMEOUT_US);
+ status = readb(req_addr + 16 + sizeof(dwz_hdr));
+ g_assert_cmpint(status, ==, 0);
+
+ guest_free(alloc, req_addr);
+
+ /* Read request to check if the sector contains all zeroes */
+ req.type = VIRTIO_BLK_T_IN;
+ req.ioprio = 1;
+ req.sector = 0;
+ req.data = g_malloc0(512);
+
+ req_addr = virtio_blk_request(alloc, dev, &req, 512);
+
+ g_free(req.data);
+
+ free_head = qvirtqueue_add(vq, req_addr, 16, false, true);
+ qvirtqueue_add(vq, req_addr + 16, 512, true, true);
+ qvirtqueue_add(vq, req_addr + 528, 1, true, false);
+
+ qvirtqueue_kick(dev, vq, free_head);
+
+ qvirtio_wait_used_elem(dev, vq, free_head, NULL,
+ QVIRTIO_BLK_TIMEOUT_US);
+ status = readb(req_addr + 528);
+ g_assert_cmpint(status, ==, 0);
+
+ data = g_malloc(512);
+ expected = g_malloc0(512);
+ memread(req_addr + 16, data, 512);
+ g_assert_cmpmem(data, 512, expected, 512);
+ g_free(expected);
+ g_free(data);
+
+ guest_free(alloc, req_addr);
+ }
+
+ if (features & (1u << VIRTIO_BLK_F_DISCARD)) {
+ struct virtio_blk_discard_write_zeroes dwz_hdr;
+
+ req.type = VIRTIO_BLK_T_DISCARD;
+ req.data = (char *) &dwz_hdr;
+ dwz_hdr.sector = 0;
+ dwz_hdr.num_sectors = 1;
+ dwz_hdr.flags = 0;
+
+ virtio_blk_fix_dwz_hdr(dev, &dwz_hdr);
+
+ req_addr = virtio_blk_request(alloc, dev, &req, sizeof(dwz_hdr));
+
+ free_head = qvirtqueue_add(vq, req_addr, 16, false, true);
+ qvirtqueue_add(vq, req_addr + 16, sizeof(dwz_hdr), false, true);
+ qvirtqueue_add(vq, req_addr + 16 + sizeof(dwz_hdr), 1, true, false);
+
+ qvirtqueue_kick(dev, vq, free_head);
+
+ qvirtio_wait_used_elem(dev, vq, free_head, NULL,
+ QVIRTIO_BLK_TIMEOUT_US);
+ status = readb(req_addr + 16 + sizeof(dwz_hdr));
+ g_assert_cmpint(status, ==, 0);
+
+ guest_free(alloc, req_addr);
+ }
+
if (features & (1u << VIRTIO_F_ANY_LAYOUT)) {
/* Write and read with 2 descriptor layout */
/* Write request */
diff --git a/thunk.c b/thunk.c
index d5d8645..17f3d32 100644
--- a/thunk.c
+++ b/thunk.c
@@ -89,7 +89,7 @@
for(i = 0;i < 2; i++) {
offset = 0;
max_align = 1;
- se->field_offsets[i] = malloc(nb_fields * sizeof(int));
+ se->field_offsets[i] = g_new(int, nb_fields);
type_ptr = se->field_types;
for(j = 0;j < nb_fields; j++) {
size = thunk_type_size(type_ptr, i);
diff --git a/ui/Makefile.objs b/ui/Makefile.objs
index 7f8b3da..fe1a7ae 100644
--- a/ui/Makefile.objs
+++ b/ui/Makefile.objs
@@ -49,6 +49,11 @@
curses.mo-cflags := $(CURSES_CFLAGS)
curses.mo-libs := $(CURSES_LIBS)
+common-obj-$(call land,$(CONFIG_SPICE),$(CONFIG_GIO)) += spice-app.mo
+spice-app.mo-objs := spice-app.o
+spice-app.mo-cflags := $(GIO_CFLAGS)
+spice-app.mo-libs := $(GIO_LIBS)
+
common-obj-$(CONFIG_OPENGL) += shader.o
common-obj-$(CONFIG_OPENGL) += console-gl.o
common-obj-$(CONFIG_OPENGL) += egl-helpers.o
diff --git a/ui/cocoa.m b/ui/cocoa.m
index e2567d6..420b241 100644
--- a/ui/cocoa.m
+++ b/ui/cocoa.m
@@ -129,6 +129,40 @@
NSTextField *pauseLabel;
NSArray * supportedImageFileTypes;
+static QemuSemaphore display_init_sem;
+static QemuSemaphore app_started_sem;
+
+// Utility functions to run specified code block with iothread lock held
+typedef void (^CodeBlock)(void);
+typedef bool (^BoolCodeBlock)(void);
+
+static void with_iothread_lock(CodeBlock block)
+{
+ bool locked = qemu_mutex_iothread_locked();
+ if (!locked) {
+ qemu_mutex_lock_iothread();
+ }
+ block();
+ if (!locked) {
+ qemu_mutex_unlock_iothread();
+ }
+}
+
+static bool bool_with_iothread_lock(BoolCodeBlock block)
+{
+ bool locked = qemu_mutex_iothread_locked();
+ bool val;
+
+ if (!locked) {
+ qemu_mutex_lock_iothread();
+ }
+ val = block();
+ if (!locked) {
+ qemu_mutex_unlock_iothread();
+ }
+ return val;
+}
+
// Mac to QKeyCode conversion
const int mac_to_qkeycode_map[] = {
[kVK_ANSI_A] = Q_KEY_CODE_A,
@@ -294,18 +328,20 @@
NSWindow *fullScreenWindow;
float cx,cy,cw,ch,cdx,cdy;
CGDataProviderRef dataProviderRef;
+ pixman_image_t *pixman_image;
BOOL modifiers_state[256];
BOOL isMouseGrabbed;
BOOL isFullscreen;
BOOL isAbsoluteEnabled;
BOOL isMouseDeassociated;
}
-- (void) switchSurface:(DisplaySurface *)surface;
+- (void) switchSurface:(pixman_image_t *)image;
- (void) grabMouse;
- (void) ungrabMouse;
- (void) toggleFullScreen:(id)sender;
- (void) handleMonitorInput:(NSEvent *)event;
-- (void) handleEvent:(NSEvent *)event;
+- (bool) handleEvent:(NSEvent *)event;
+- (bool) handleEventLocked:(NSEvent *)event;
- (void) setAbsoluteEnabled:(BOOL)tIsAbsoluteEnabled;
/* The state surrounding mouse grabbing is potentially confusing.
* isAbsoluteEnabled tracks qemu_input_is_absolute() [ie "is the emulated
@@ -351,8 +387,10 @@
{
COCOA_DEBUG("QemuCocoaView: dealloc\n");
- if (dataProviderRef)
+ if (dataProviderRef) {
CGDataProviderRelease(dataProviderRef);
+ pixman_image_unref(pixman_image);
+ }
[super dealloc];
}
@@ -479,12 +517,13 @@
}
}
-- (void) switchSurface:(DisplaySurface *)surface
+- (void) switchSurface:(pixman_image_t *)image
{
COCOA_DEBUG("QemuCocoaView: switchSurface\n");
- int w = surface_width(surface);
- int h = surface_height(surface);
+ int w = pixman_image_get_width(image);
+ int h = pixman_image_get_height(image);
+ pixman_format_code_t image_format = pixman_image_get_format(image);
/* cdx == 0 means this is our very first surface, in which case we need
* to recalculate the content dimensions even if it happens to be the size
* of the initial empty window.
@@ -502,14 +541,17 @@
}
// update screenBuffer
- if (dataProviderRef)
+ if (dataProviderRef) {
CGDataProviderRelease(dataProviderRef);
+ pixman_image_unref(pixman_image);
+ }
//sync host window color space with guests
- screen.bitsPerPixel = surface_bits_per_pixel(surface);
- screen.bitsPerComponent = surface_bytes_per_pixel(surface) * 2;
+ screen.bitsPerPixel = PIXMAN_FORMAT_BPP(image_format);
+ screen.bitsPerComponent = DIV_ROUND_UP(screen.bitsPerPixel, 8) * 2;
- dataProviderRef = CGDataProviderCreateWithData(NULL, surface_data(surface), w * 4 * h, NULL);
+ pixman_image = image;
+ dataProviderRef = CGDataProviderCreateWithData(NULL, pixman_image_get_data(image), w * 4 * h, NULL);
// update windows
if (isFullscreen) {
@@ -647,10 +689,17 @@
}
}
-- (void) handleEvent:(NSEvent *)event
+- (bool) handleEvent:(NSEvent *)event
{
- COCOA_DEBUG("QemuCocoaView: handleEvent\n");
+ return bool_with_iothread_lock(^{
+ return [self handleEventLocked:event];
+ });
+}
+- (bool) handleEventLocked:(NSEvent *)event
+{
+ /* Return true if we handled the event, false if it should be given to OSX */
+ COCOA_DEBUG("QemuCocoaView: handleEvent\n");
int buttons = 0;
int keycode = 0;
bool mouse_event = false;
@@ -720,8 +769,7 @@
if (keycode == Q_KEY_CODE_F) {
switched_to_fullscreen = true;
}
- [NSApp sendEvent:event];
- return;
+ return false;
}
// default
@@ -736,12 +784,12 @@
// enable graphic console
case '1' ... '9':
console_select(key - '0' - 1); /* ascii math */
- return;
+ return true;
// release the mouse grab
case 'g':
[self ungrabMouse];
- return;
+ return true;
}
}
}
@@ -758,7 +806,7 @@
// don't pass the guest a spurious key-up if we treated this
// command-key combo as a host UI action
if (!isMouseGrabbed && ([event modifierFlags] & NSEventModifierFlagCommand)) {
- return;
+ return true;
}
if (qemu_console_is_graphic(NULL)) {
@@ -852,7 +900,7 @@
mouse_event = false;
break;
default:
- [NSApp sendEvent:event];
+ return false;
}
if (mouse_event) {
@@ -888,10 +936,11 @@
qemu_input_queue_rel(dcl->con, INPUT_AXIS_Y, (int)[event deltaY]);
}
} else {
- [NSApp sendEvent:event];
+ return false;
}
qemu_input_event_sync();
}
+ return true;
}
- (void) grabMouse
@@ -945,15 +994,18 @@
*/
- (void) raiseAllKeys
{
- int index;
const int max_index = ARRAY_SIZE(modifiers_state);
- for (index = 0; index < max_index; index++) {
- if (modifiers_state[index]) {
- modifiers_state[index] = 0;
- qemu_input_event_send_key_qcode(dcl->con, index, false);
- }
- }
+ with_iothread_lock(^{
+ int index;
+
+ for (index = 0; index < max_index; index++) {
+ if (modifiers_state[index]) {
+ modifiers_state[index] = 0;
+ qemu_input_event_send_key_qcode(dcl->con, index, false);
+ }
+ }
+ });
}
@end
@@ -970,7 +1022,6 @@
#endif
{
}
-- (void)startEmulationWithArgc:(int)argc argv:(char**)argv;
- (void)doToggleFullScreen:(id)sender;
- (void)toggleFullScreen:(id)sender;
- (void)showQEMUDoc:(id)sender;
@@ -1058,8 +1109,8 @@
- (void)applicationDidFinishLaunching: (NSNotification *) note
{
COCOA_DEBUG("QemuCocoaAppController: applicationDidFinishLaunching\n");
- // launch QEMU, with the global args
- [self startEmulationWithArgc:gArgc argv:(char **)gArgv];
+ /* Tell cocoa_display_init to proceed */
+ qemu_sem_post(&app_started_sem);
}
- (void)applicationWillTerminate:(NSNotification *)aNotification
@@ -1102,15 +1153,6 @@
[cocoaView raiseAllKeys];
}
-- (void)startEmulationWithArgc:(int)argc argv:(char**)argv
-{
- COCOA_DEBUG("QemuCocoaAppController: startEmulationWithArgc\n");
-
- int status;
- status = qemu_main(argc, argv, *_NSGetEnviron());
- exit(status);
-}
-
/* We abstract the method called by the Enter Fullscreen menu item
* because Mac OS 10.7 and higher disables it. This is because of the
* menu item's old selector's name toggleFullScreen:
@@ -1178,7 +1220,9 @@
/* Pause the guest */
- (void)pauseQEMU:(id)sender
{
- qmp_stop(NULL);
+ with_iothread_lock(^{
+ qmp_stop(NULL);
+ });
[sender setEnabled: NO];
[[[sender menu] itemWithTitle: @"Resume"] setEnabled: YES];
[self displayPause];
@@ -1187,7 +1231,9 @@
/* Resume running the guest operating system */
- (void)resumeQEMU:(id) sender
{
- qmp_cont(NULL);
+ with_iothread_lock(^{
+ qmp_cont(NULL);
+ });
[sender setEnabled: NO];
[[[sender menu] itemWithTitle: @"Pause"] setEnabled: YES];
[self removePause];
@@ -1215,13 +1261,17 @@
/* Restarts QEMU */
- (void)restartQEMU:(id)sender
{
- qmp_system_reset(NULL);
+ with_iothread_lock(^{
+ qmp_system_reset(NULL);
+ });
}
/* Powers down QEMU */
- (void)powerDownQEMU:(id)sender
{
- qmp_system_powerdown(NULL);
+ with_iothread_lock(^{
+ qmp_system_powerdown(NULL);
+ });
}
/* Ejects the media.
@@ -1237,9 +1287,11 @@
return;
}
- Error *err = NULL;
- qmp_eject(true, [drive cStringUsingEncoding: NSASCIIStringEncoding],
- false, NULL, false, false, &err);
+ __block Error *err = NULL;
+ with_iothread_lock(^{
+ qmp_eject(true, [drive cStringUsingEncoding: NSASCIIStringEncoding],
+ false, NULL, false, false, &err);
+ });
handleAnyDeviceErrors(err);
}
@@ -1271,16 +1323,18 @@
return;
}
- Error *err = NULL;
- qmp_blockdev_change_medium(true,
- [drive cStringUsingEncoding:
- NSASCIIStringEncoding],
- false, NULL,
- [file cStringUsingEncoding:
- NSASCIIStringEncoding],
- true, "raw",
- false, 0,
- &err);
+ __block Error *err = NULL;
+ with_iothread_lock(^{
+ qmp_blockdev_change_medium(true,
+ [drive cStringUsingEncoding:
+ NSASCIIStringEncoding],
+ false, NULL,
+ [file cStringUsingEncoding:
+ NSASCIIStringEncoding],
+ true, "raw",
+ false, 0,
+ &err);
+ });
handleAnyDeviceErrors(err);
}
}
@@ -1419,49 +1473,29 @@
// get the throttle percentage
throttle_pct = [sender tag];
- cpu_throttle_set(throttle_pct);
+ with_iothread_lock(^{
+ cpu_throttle_set(throttle_pct);
+ });
COCOA_DEBUG("cpu throttling at %d%c\n", cpu_throttle_get_percentage(), '%');
}
@end
+@interface QemuApplication : NSApplication
+@end
-int main (int argc, const char * argv[]) {
-
- gArgc = argc;
- gArgv = (char **)argv;
- int i;
-
- /* In case we don't need to display a window, let's not do that */
- for (i = 1; i < argc; i++) {
- const char *opt = argv[i];
-
- if (opt[0] == '-') {
- /* Treat --foo the same as -foo. */
- if (opt[1] == '-') {
- opt++;
- }
- if (!strcmp(opt, "-h") || !strcmp(opt, "-help") ||
- !strcmp(opt, "-vnc") ||
- !strcmp(opt, "-nographic") ||
- !strcmp(opt, "-version") ||
- !strcmp(opt, "-curses") ||
- !strcmp(opt, "-display") ||
- !strcmp(opt, "-qtest")) {
- return qemu_main(gArgc, gArgv, *_NSGetEnviron());
- }
- }
+@implementation QemuApplication
+- (void)sendEvent:(NSEvent *)event
+{
+ COCOA_DEBUG("QemuApplication: sendEvent\n");
+ if (![cocoaView handleEvent:event]) {
+ [super sendEvent: event];
}
+}
+@end
- NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
-
- // Pull this console process up to being a fully-fledged graphical
- // app with a menubar and Dock icon
- ProcessSerialNumber psn = { 0, kCurrentProcess };
- TransformProcessType(&psn, kProcessTransformToForegroundApplication);
-
- [NSApplication sharedApplication];
-
+static void create_initial_menus(void)
+{
// Add menus
NSMenu *menu;
NSMenuItem *menuItem;
@@ -1545,97 +1579,8 @@
menuItem = [[[NSMenuItem alloc] initWithTitle:@"Window" action:nil keyEquivalent:@""] autorelease];
[menuItem setSubmenu:menu];
[[NSApp mainMenu] addItem:menuItem];
-
- // Create an Application controller
- QemuCocoaAppController *appController = [[QemuCocoaAppController alloc] init];
- [NSApp setDelegate:appController];
-
- // Start the main event loop
- [NSApp run];
-
- [appController release];
- [pool release];
-
- return 0;
}
-
-
-#pragma mark qemu
-static void cocoa_update(DisplayChangeListener *dcl,
- int x, int y, int w, int h)
-{
- NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
-
- COCOA_DEBUG("qemu_cocoa: cocoa_update\n");
-
- NSRect rect;
- if ([cocoaView cdx] == 1.0) {
- rect = NSMakeRect(x, [cocoaView gscreen].height - y - h, w, h);
- } else {
- rect = NSMakeRect(
- x * [cocoaView cdx],
- ([cocoaView gscreen].height - y - h) * [cocoaView cdy],
- w * [cocoaView cdx],
- h * [cocoaView cdy]);
- }
- [cocoaView setNeedsDisplayInRect:rect];
-
- [pool release];
-}
-
-static void cocoa_switch(DisplayChangeListener *dcl,
- DisplaySurface *surface)
-{
- NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
-
- COCOA_DEBUG("qemu_cocoa: cocoa_switch\n");
- [cocoaView switchSurface:surface];
- [pool release];
-}
-
-static void cocoa_refresh(DisplayChangeListener *dcl)
-{
- NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
-
- COCOA_DEBUG("qemu_cocoa: cocoa_refresh\n");
- graphic_hw_update(NULL);
-
- if (qemu_input_is_absolute()) {
- if (![cocoaView isAbsoluteEnabled]) {
- if ([cocoaView isMouseGrabbed]) {
- [cocoaView ungrabMouse];
- }
- }
- [cocoaView setAbsoluteEnabled:YES];
- }
-
- NSDate *distantPast;
- NSEvent *event;
- distantPast = [NSDate distantPast];
- do {
- event = [NSApp nextEventMatchingMask:NSEventMaskAny untilDate:distantPast
- inMode: NSDefaultRunLoopMode dequeue:YES];
- if (event != nil) {
- [cocoaView handleEvent:event];
- }
- } while(event != nil);
- [pool release];
-}
-
-static void cocoa_cleanup(void)
-{
- COCOA_DEBUG("qemu_cocoa: cocoa_cleanup\n");
- g_free(dcl);
-}
-
-static const DisplayChangeListenerOps dcl_ops = {
- .dpy_name = "cocoa",
- .dpy_gfx_update = cocoa_update,
- .dpy_gfx_switch = cocoa_switch,
- .dpy_refresh = cocoa_refresh,
-};
-
/* Returns a name for a given console */
static NSString * getConsoleName(QemuConsole * console)
{
@@ -1728,14 +1673,191 @@
qapi_free_BlockInfoList(pointerToFree);
}
+/*
+ * The startup process for the OSX/Cocoa UI is complicated, because
+ * OSX insists that the UI runs on the initial main thread, and so we
+ * need to start a second thread which runs the vl.c qemu_main():
+ *
+ * Initial thread: 2nd thread:
+ * in main():
+ * create qemu-main thread
+ * wait on display_init semaphore
+ * call qemu_main()
+ * ...
+ * in cocoa_display_init():
+ * post the display_init semaphore
+ * wait on app_started semaphore
+ * create application, menus, etc
+ * enter OSX run loop
+ * in applicationDidFinishLaunching:
+ * post app_started semaphore
+ * tell main thread to fullscreen if needed
+ * [...]
+ * run qemu main-loop
+ *
+ * We do this in two stages so that we don't do the creation of the
+ * GUI application menus and so on for command line options like --help
+ * where we want to just print text to stdout and exit immediately.
+ */
+
+static void *call_qemu_main(void *opaque)
+{
+ int status;
+
+ COCOA_DEBUG("Second thread: calling qemu_main()\n");
+ status = qemu_main(gArgc, gArgv, *_NSGetEnviron());
+ COCOA_DEBUG("Second thread: qemu_main() returned, exiting\n");
+ exit(status);
+}
+
+int main (int argc, const char * argv[]) {
+ QemuThread thread;
+
+ COCOA_DEBUG("Entered main()\n");
+ gArgc = argc;
+ gArgv = (char **)argv;
+
+ qemu_sem_init(&display_init_sem, 0);
+ qemu_sem_init(&app_started_sem, 0);
+
+ qemu_thread_create(&thread, "qemu_main", call_qemu_main,
+ NULL, QEMU_THREAD_DETACHED);
+
+ COCOA_DEBUG("Main thread: waiting for display_init_sem\n");
+ qemu_sem_wait(&display_init_sem);
+ COCOA_DEBUG("Main thread: initializing app\n");
+
+ NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
+
+ // Pull this console process up to being a fully-fledged graphical
+ // app with a menubar and Dock icon
+ ProcessSerialNumber psn = { 0, kCurrentProcess };
+ TransformProcessType(&psn, kProcessTransformToForegroundApplication);
+
+ [QemuApplication sharedApplication];
+
+ create_initial_menus();
+
+ /*
+ * Create the menu entries which depend on QEMU state (for consoles
+ * and removeable devices). These make calls back into QEMU functions,
+ * which is OK because at this point we know that the second thread
+ * holds the iothread lock and is synchronously waiting for us to
+ * finish.
+ */
+ add_console_menu_entries();
+ addRemovableDevicesMenuItems();
+
+ // Create an Application controller
+ QemuCocoaAppController *appController = [[QemuCocoaAppController alloc] init];
+ [NSApp setDelegate:appController];
+
+ // Start the main event loop
+ COCOA_DEBUG("Main thread: entering OSX run loop\n");
+ [NSApp run];
+ COCOA_DEBUG("Main thread: left OSX run loop, exiting\n");
+
+ [appController release];
+ [pool release];
+
+ return 0;
+}
+
+
+
+#pragma mark qemu
+static void cocoa_update(DisplayChangeListener *dcl,
+ int x, int y, int w, int h)
+{
+ NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
+
+ COCOA_DEBUG("qemu_cocoa: cocoa_update\n");
+
+ dispatch_async(dispatch_get_main_queue(), ^{
+ NSRect rect;
+ if ([cocoaView cdx] == 1.0) {
+ rect = NSMakeRect(x, [cocoaView gscreen].height - y - h, w, h);
+ } else {
+ rect = NSMakeRect(
+ x * [cocoaView cdx],
+ ([cocoaView gscreen].height - y - h) * [cocoaView cdy],
+ w * [cocoaView cdx],
+ h * [cocoaView cdy]);
+ }
+ [cocoaView setNeedsDisplayInRect:rect];
+ });
+
+ [pool release];
+}
+
+static void cocoa_switch(DisplayChangeListener *dcl,
+ DisplaySurface *surface)
+{
+ NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
+ pixman_image_t *image = surface->image;
+
+ COCOA_DEBUG("qemu_cocoa: cocoa_switch\n");
+
+ // The DisplaySurface will be freed as soon as this callback returns.
+ // We take a reference to the underlying pixman image here so it does
+ // not disappear from under our feet; the switchSurface method will
+ // deref the old image when it is done with it.
+ pixman_image_ref(image);
+
+ dispatch_async(dispatch_get_main_queue(), ^{
+ [cocoaView switchSurface:image];
+ });
+ [pool release];
+}
+
+static void cocoa_refresh(DisplayChangeListener *dcl)
+{
+ NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
+
+ COCOA_DEBUG("qemu_cocoa: cocoa_refresh\n");
+ graphic_hw_update(NULL);
+
+ if (qemu_input_is_absolute()) {
+ dispatch_async(dispatch_get_main_queue(), ^{
+ if (![cocoaView isAbsoluteEnabled]) {
+ if ([cocoaView isMouseGrabbed]) {
+ [cocoaView ungrabMouse];
+ }
+ }
+ [cocoaView setAbsoluteEnabled:YES];
+ });
+ }
+ [pool release];
+}
+
+static void cocoa_cleanup(void)
+{
+ COCOA_DEBUG("qemu_cocoa: cocoa_cleanup\n");
+ g_free(dcl);
+}
+
+static const DisplayChangeListenerOps dcl_ops = {
+ .dpy_name = "cocoa",
+ .dpy_gfx_update = cocoa_update,
+ .dpy_gfx_switch = cocoa_switch,
+ .dpy_refresh = cocoa_refresh,
+};
+
static void cocoa_display_init(DisplayState *ds, DisplayOptions *opts)
{
COCOA_DEBUG("qemu_cocoa: cocoa_display_init\n");
+ /* Tell main thread to go ahead and create the app and enter the run loop */
+ qemu_sem_post(&display_init_sem);
+ qemu_sem_wait(&app_started_sem);
+ COCOA_DEBUG("cocoa_display_init: app start completed\n");
+
/* if fullscreen mode is to be used */
if (opts->has_full_screen && opts->full_screen) {
- [NSApp activateIgnoringOtherApps: YES];
- [(QemuCocoaAppController *)[[NSApplication sharedApplication] delegate] toggleFullScreen: nil];
+ dispatch_async(dispatch_get_main_queue(), ^{
+ [NSApp activateIgnoringOtherApps: YES];
+ [(QemuCocoaAppController *)[[NSApplication sharedApplication] delegate] toggleFullScreen: nil];
+ });
}
dcl = g_malloc0(sizeof(DisplayChangeListener));
@@ -1746,17 +1868,6 @@
// register cleanup function
atexit(cocoa_cleanup);
-
- /* At this point QEMU has created all the consoles, so we can add View
- * menu entries for them.
- */
- add_console_menu_entries();
-
- /* Give all removable devices a menu item.
- * Has to be called after QEMU has started to
- * find out what removable devices it has.
- */
- addRemovableDevicesMenuItems();
}
static QemuDisplay qemu_display_cocoa = {
diff --git a/ui/gtk.c b/ui/gtk.c
index 949b143..e96e154 100644
--- a/ui/gtk.c
+++ b/ui/gtk.c
@@ -6,29 +6,25 @@
* Authors:
* Anthony Liguori <aliguori@us.ibm.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.
+ * 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.
*
- * Portions from gtk-vnc:
+ * 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/>.
+ *
+ * Portions from gtk-vnc (originally licensed under the LGPL v2+):
*
* GTK VNC Widget
*
* Copyright (C) 2006 Anthony Liguori <anthony@codemonkey.ws>
* Copyright (C) 2009-2010 Daniel P. Berrange <dan@berrange.com>
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.0 of the License, or (at your option) any later version.
- *
- * 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, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#define GETTEXT_PACKAGE "qemu"
diff --git a/ui/kbd-state.c b/ui/kbd-state.c
index ac14add..f3ab2d7 100644
--- a/ui/kbd-state.c
+++ b/ui/kbd-state.c
@@ -42,14 +42,18 @@
{
bool state = test_bit(qcode, kbd->keys);
- if (state == down) {
+ if (down == false /* got key-up event */ &&
+ state == false /* key is not pressed */) {
/*
- * Filter out events which don't change the keyboard state.
+ * Filter out suspicious key-up events.
*
- * Most notably this allows to simply send along all key-up
- * events, and this function will filter out everything where
- * the corresponding key-down event wasn't send to the guest,
- * for example due to being a host hotkey.
+ * This allows simply sending along all key-up events, and
+ * this function will filter out everything where the
+ * corresponding key-down event wasn't sent to the guest, for
+ * example due to being a host hotkey.
+ *
+ * Note that key-down events on already pressed keys are *not*
+ * suspicious, those are keyboard autorepeat events.
*/
return;
}
diff --git a/ui/sdl2-input.c b/ui/sdl2-input.c
index 664364a..fb345f4 100644
--- a/ui/sdl2-input.c
+++ b/ui/sdl2-input.c
@@ -54,8 +54,5 @@
break;
}
}
- } else {
- qemu_input_event_send_key_qcode(con, qcode,
- ev->type == SDL_KEYDOWN);
}
}
diff --git a/ui/spice-app.c b/ui/spice-app.c
new file mode 100644
index 0000000..925b27b
--- /dev/null
+++ b/ui/spice-app.c
@@ -0,0 +1,202 @@
+/*
+ * QEMU external Spice client display driver
+ *
+ * Copyright (c) 2018 Marc-André Lureau <marcandre.lureau@redhat.com>
+ *
+ * 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"
+
+#include <gio/gio.h>
+
+#include "qemu-common.h"
+#include "ui/console.h"
+#include "qemu/config-file.h"
+#include "qemu/option.h"
+#include "qemu/cutils.h"
+#include "qapi/error.h"
+#include "io/channel-command.h"
+#include "chardev/spice.h"
+#include "sysemu/sysemu.h"
+
+static const char *tmp_dir;
+static char *app_dir;
+static char *sock_path;
+
+typedef struct VCChardev {
+ SpiceChardev parent;
+} VCChardev;
+
+#define TYPE_CHARDEV_VC "chardev-vc"
+#define VC_CHARDEV(obj) OBJECT_CHECK(VCChardev, (obj), TYPE_CHARDEV_VC)
+
+static ChardevBackend *
+chr_spice_backend_new(void)
+{
+ ChardevBackend *be = g_new0(ChardevBackend, 1);
+
+ be->type = CHARDEV_BACKEND_KIND_SPICEPORT;
+ be->u.spiceport.data = g_new0(ChardevSpicePort, 1);
+
+ return be;
+}
+
+static void vc_chr_open(Chardev *chr,
+ ChardevBackend *backend,
+ bool *be_opened,
+ Error **errp)
+{
+ ChardevBackend *be;
+ const char *fqdn = NULL;
+
+ if (strstart(chr->label, "serial", NULL)) {
+ fqdn = "org.qemu.console.serial.0";
+ } else if (strstart(chr->label, "parallel", NULL)) {
+ fqdn = "org.qemu.console.parallel.0";
+ } else if (strstart(chr->label, "compat_monitor", NULL)) {
+ fqdn = "org.qemu.monitor.hmp.0";
+ }
+
+ be = chr_spice_backend_new();
+ be->u.spiceport.data->fqdn = fqdn ?
+ g_strdup(fqdn) : g_strdup_printf("org.qemu.console.%s", chr->label);
+ qemu_chr_open_spice_port(chr, be, be_opened, errp);
+ qapi_free_ChardevBackend(be);
+}
+
+static void vc_chr_set_echo(Chardev *chr, bool echo)
+{
+ /* TODO: set echo for frontends QMP and qtest */
+}
+
+static void char_vc_class_init(ObjectClass *oc, void *data)
+{
+ ChardevClass *cc = CHARDEV_CLASS(oc);
+
+ cc->parse = qemu_chr_parse_vc;
+ cc->open = vc_chr_open;
+ cc->chr_set_echo = vc_chr_set_echo;
+}
+
+static const TypeInfo char_vc_type_info = {
+ .name = TYPE_CHARDEV_VC,
+ .parent = TYPE_CHARDEV_SPICEPORT,
+ .instance_size = sizeof(VCChardev),
+ .class_init = char_vc_class_init,
+};
+
+static void spice_app_atexit(void)
+{
+ if (sock_path) {
+ unlink(sock_path);
+ }
+ if (tmp_dir) {
+ rmdir(tmp_dir);
+ }
+ g_free(sock_path);
+ g_free(app_dir);
+}
+
+static void spice_app_display_early_init(DisplayOptions *opts)
+{
+ QemuOpts *qopts;
+ ChardevBackend *be = chr_spice_backend_new();
+ GError *err = NULL;
+
+ if (opts->has_full_screen) {
+ error_report("spice-app full-screen isn't supported yet.");
+ exit(1);
+ }
+ if (opts->has_window_close) {
+ error_report("spice-app window-close isn't supported yet.");
+ exit(1);
+ }
+
+ atexit(spice_app_atexit);
+
+ if (qemu_name) {
+ app_dir = g_build_filename(g_get_user_runtime_dir(),
+ "qemu", qemu_name, NULL);
+ if (g_mkdir_with_parents(app_dir, S_IRWXU) < -1) {
+ error_report("Failed to create directory %s: %s",
+ app_dir, strerror(errno));
+ exit(1);
+ }
+ } else {
+ app_dir = g_dir_make_tmp(NULL, &err);
+ tmp_dir = app_dir;
+ if (err) {
+ error_report("Failed to create temporary directory: %s",
+ err->message);
+ exit(1);
+ }
+ }
+
+ type_register(&char_vc_type_info);
+
+ sock_path = g_strjoin("", app_dir, "/", "spice.sock", NULL);
+ qopts = qemu_opts_create(qemu_find_opts("spice"), NULL, 0, &error_abort);
+ qemu_opt_set(qopts, "disable-ticketing", "on", &error_abort);
+ qemu_opt_set(qopts, "unix", "on", &error_abort);
+ 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);
+ qemu_opt_set(qopts, "gl", opts->has_gl ? "on" : "off", &error_abort);
+ display_opengl = opts->has_gl;
+
+ 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);
+ qopts = qemu_opts_create(qemu_find_opts("mon"),
+ NULL, 0, &error_fatal);
+ qemu_opt_set(qopts, "chardev", "org.qemu.monitor.qmp", &error_abort);
+ qemu_opt_set(qopts, "mode", "control", &error_abort);
+
+ qapi_free_ChardevBackend(be);
+}
+
+static void spice_app_display_init(DisplayState *ds, DisplayOptions *opts)
+{
+ GError *err = NULL;
+ gchar *uri;
+
+ uri = g_strjoin("", "spice+unix://", app_dir, "/", "spice.sock", NULL);
+ info_report("Launching display with URI: %s", uri);
+ g_app_info_launch_default_for_uri(uri, NULL, &err);
+ if (err) {
+ error_report("Failed to launch %s URI: %s", uri, err->message);
+ error_report("You need a capable Spice client, "
+ "such as virt-viewer 8.0");
+ exit(1);
+ }
+ g_free(uri);
+}
+
+static QemuDisplay qemu_display_spice_app = {
+ .type = DISPLAY_TYPE_SPICE_APP,
+ .early_init = spice_app_display_early_init,
+ .init = spice_app_display_init,
+};
+
+static void register_spice_app(void)
+{
+ qemu_display_register(&qemu_display_spice_app);
+}
+
+type_init(register_spice_app);
diff --git a/ui/spice-core.c b/ui/spice-core.c
index a40fb2c..0632c74 100644
--- a/ui/spice-core.c
+++ b/ui/spice-core.c
@@ -34,6 +34,7 @@
#include "qemu/option.h"
#include "migration/misc.h"
#include "hw/hw.h"
+#include "hw/pci/pci_bus.h"
#include "ui/spice-display.h"
/* core bits */
@@ -397,6 +398,7 @@
static QemuOptsList qemu_spice_opts = {
.name = "spice",
.head = QTAILQ_HEAD_INITIALIZER(qemu_spice_opts.head),
+ .merge_lists = true,
.desc = {
{
.name = "port",
@@ -626,7 +628,7 @@
{
if (running) {
qemu_spice_display_start();
- } else {
+ } else if (state != RUN_STATE_PAUSED) {
qemu_spice_display_stop();
}
}
@@ -783,7 +785,7 @@
qemu_opt_foreach(opts, add_channel, &tls_port, &error_fatal);
- spice_server_set_name(spice_server, qemu_name);
+ spice_server_set_name(spice_server, qemu_name ?: "QEMU " QEMU_VERSION);
spice_server_set_uuid(spice_server, (unsigned char *)&qemu_uuid);
seamless_migration = qemu_opt_get_bool(opts, "seamless-migration", 0);
@@ -863,6 +865,56 @@
return false;
}
+/*
+ * Recursively (in reverse order) appends addresses of PCI devices as it moves
+ * up in the PCI hierarchy.
+ *
+ * @returns true on success, false when the buffer wasn't large enough
+ */
+static bool append_pci_address(char *buf, size_t buf_size, const PCIDevice *pci)
+{
+ PCIBus *bus = pci_get_bus(pci);
+ /*
+ * equivalent to if (!pci_bus_is_root(bus)), but the function is not built
+ * with PCI_CONFIG=n, avoid using an #ifdef by checking directly
+ */
+ if (bus->parent_dev != NULL) {
+ append_pci_address(buf, buf_size, bus->parent_dev);
+ }
+
+ size_t len = strlen(buf);
+ ssize_t written = snprintf(buf + len, buf_size - len, "/%02x.%x",
+ PCI_SLOT(pci->devfn), PCI_FUNC(pci->devfn));
+
+ return written > 0 && written < buf_size - len;
+}
+
+bool qemu_spice_fill_device_address(QemuConsole *con,
+ char *device_address,
+ size_t size)
+{
+ DeviceState *dev = DEVICE(object_property_get_link(OBJECT(con),
+ "device",
+ &error_abort));
+ PCIDevice *pci = (PCIDevice *) object_dynamic_cast(OBJECT(dev),
+ TYPE_PCI_DEVICE);
+
+ if (pci == NULL) {
+ warn_report("Setting device address of a display device to SPICE: "
+ "Not a PCI device.");
+ return false;
+ }
+
+ strncpy(device_address, "pci/0000", size);
+ if (!append_pci_address(device_address, size, pci)) {
+ warn_report("Setting device address of a display device to SPICE: "
+ "Too many PCI devices in the chain.");
+ return false;
+ }
+
+ return true;
+}
+
int qemu_spice_add_display_interface(QXLInstance *qxlin, QemuConsole *con)
{
if (g_slist_find(spice_consoles, con)) {
@@ -921,12 +973,20 @@
void qemu_spice_display_start(void)
{
+ if (spice_display_is_running) {
+ return;
+ }
+
spice_display_is_running = true;
spice_server_vm_start(spice_server);
}
void qemu_spice_display_stop(void)
{
+ if (!spice_display_is_running) {
+ return;
+ }
+
spice_server_vm_stop(spice_server);
spice_display_is_running = false;
}
diff --git a/ui/spice-display.c b/ui/spice-display.c
index aea6f6e..a5e2647 100644
--- a/ui/spice-display.c
+++ b/ui/spice-display.c
@@ -1147,6 +1147,17 @@
ssd->qxl.base.sif = &dpy_interface.base;
qemu_spice_add_display_interface(&ssd->qxl, con);
+
+#if SPICE_SERVER_VERSION >= 0x000e02 /* release 0.14.2 */
+ char device_address[256] = "";
+ if (qemu_spice_fill_device_address(con, device_address, 256)) {
+ spice_qxl_set_device_info(&ssd->qxl,
+ device_address,
+ qemu_console_get_head(con),
+ 1);
+ }
+#endif
+
qemu_spice_create_host_memslot(ssd);
register_displaychangelistener(&ssd->dcl);
diff --git a/ui/vnc-auth-sasl.c b/ui/vnc-auth-sasl.c
index 3751a77..7b2b09f 100644
--- a/ui/vnc-auth-sasl.c
+++ b/ui/vnc-auth-sasl.c
@@ -24,6 +24,7 @@
#include "qemu/osdep.h"
#include "qapi/error.h"
+#include "authz/base.h"
#include "vnc.h"
#include "trace.h"
@@ -146,13 +147,14 @@
static int vnc_auth_sasl_check_access(VncState *vs)
{
const void *val;
- int err;
- int allow;
+ int rv;
+ Error *err = NULL;
+ bool allow;
- err = sasl_getprop(vs->sasl.conn, SASL_USERNAME, &val);
- if (err != SASL_OK) {
+ rv = sasl_getprop(vs->sasl.conn, SASL_USERNAME, &val);
+ if (rv != SASL_OK) {
trace_vnc_auth_fail(vs, vs->auth, "Cannot fetch SASL username",
- sasl_errstring(err, NULL, NULL));
+ sasl_errstring(rv, NULL, NULL));
return -1;
}
if (val == NULL) {
@@ -163,12 +165,19 @@
vs->sasl.username = g_strdup((const char*)val);
trace_vnc_auth_sasl_username(vs, vs->sasl.username);
- if (vs->vd->sasl.acl == NULL) {
+ if (vs->vd->sasl.authzid == NULL) {
trace_vnc_auth_sasl_acl(vs, 1);
return 0;
}
- allow = qemu_acl_party_is_allowed(vs->vd->sasl.acl, vs->sasl.username);
+ allow = qauthz_is_allowed_by_id(vs->vd->sasl.authzid,
+ vs->sasl.username, &err);
+ if (err) {
+ trace_vnc_auth_fail(vs, vs->auth, "Error from authz",
+ error_get_pretty(err));
+ error_free(err);
+ return -1;
+ }
trace_vnc_auth_sasl_acl(vs, allow);
return allow ? 0 : -1;
diff --git a/ui/vnc-auth-sasl.h b/ui/vnc-auth-sasl.h
index 2ae224e..fb55fe0 100644
--- a/ui/vnc-auth-sasl.h
+++ b/ui/vnc-auth-sasl.h
@@ -30,8 +30,8 @@
typedef struct VncStateSASL VncStateSASL;
typedef struct VncDisplaySASL VncDisplaySASL;
-#include "qemu/acl.h"
#include "qemu/main-loop.h"
+#include "authz/base.h"
struct VncStateSASL {
sasl_conn_t *conn;
@@ -60,7 +60,8 @@
};
struct VncDisplaySASL {
- qemu_acl *acl;
+ QAuthZ *authz;
+ char *authzid;
};
void vnc_sasl_client_cleanup(VncState *vs);
diff --git a/ui/vnc-auth-vencrypt.c b/ui/vnc-auth-vencrypt.c
index d99ea36..f072e16 100644
--- a/ui/vnc-auth-vencrypt.c
+++ b/ui/vnc-auth-vencrypt.c
@@ -109,7 +109,7 @@
tls = qio_channel_tls_new_server(
vs->ioc,
vs->vd->tlscreds,
- vs->vd->tlsaclname,
+ vs->vd->tlsauthzid,
&err);
if (!tls) {
trace_vnc_auth_fail(vs, vs->auth, "TLS setup failed",
diff --git a/ui/vnc-ws.c b/ui/vnc-ws.c
index 950f1cd..95c9703 100644
--- a/ui/vnc-ws.c
+++ b/ui/vnc-ws.c
@@ -62,7 +62,7 @@
tls = qio_channel_tls_new_server(
vs->ioc,
vs->vd->tlscreds,
- vs->vd->tlsaclname,
+ vs->vd->tlsauthzid,
&err);
if (!tls) {
VNC_DEBUG("Failed to setup TLS %s\n", error_get_pretty(err));
diff --git a/ui/vnc.c b/ui/vnc.c
index 7e0710e..da4a21d 100644
--- a/ui/vnc.c
+++ b/ui/vnc.c
@@ -33,7 +33,7 @@
#include "qemu/option.h"
#include "qemu/sockets.h"
#include "qemu/timer.h"
-#include "qemu/acl.h"
+#include "authz/list.h"
#include "qemu/config-file.h"
#include "qapi/qapi-emit-events.h"
#include "qapi/qapi-events-ui.h"
@@ -3229,12 +3229,24 @@
object_unparent(OBJECT(vd->tlscreds));
vd->tlscreds = NULL;
}
- g_free(vd->tlsaclname);
- vd->tlsaclname = NULL;
+ if (vd->tlsauthz) {
+ object_unparent(OBJECT(vd->tlsauthz));
+ vd->tlsauthz = NULL;
+ }
+ g_free(vd->tlsauthzid);
+ vd->tlsauthzid = NULL;
if (vd->lock_key_sync) {
qemu_remove_led_event_handler(vd->led);
vd->led = NULL;
}
+#ifdef CONFIG_VNC_SASL
+ if (vd->sasl.authz) {
+ object_unparent(OBJECT(vd->sasl.authz));
+ vd->sasl.authz = NULL;
+ }
+ g_free(vd->sasl.authzid);
+ vd->sasl.authzid = NULL;
+#endif
}
int vnc_display_password(const char *id, const char *password)
@@ -3887,23 +3899,24 @@
if (acl) {
if (strcmp(vd->id, "default") == 0) {
- vd->tlsaclname = g_strdup("vnc.x509dname");
+ vd->tlsauthzid = g_strdup("vnc.x509dname");
} else {
- vd->tlsaclname = g_strdup_printf("vnc.%s.x509dname", vd->id);
+ vd->tlsauthzid = g_strdup_printf("vnc.%s.x509dname", vd->id);
}
- qemu_acl_init(vd->tlsaclname);
+ vd->tlsauthz = QAUTHZ(qauthz_list_new(vd->tlsauthzid,
+ QAUTHZ_LIST_POLICY_DENY,
+ &error_abort));
}
#ifdef CONFIG_VNC_SASL
if (acl && sasl) {
- char *aclname;
-
if (strcmp(vd->id, "default") == 0) {
- aclname = g_strdup("vnc.username");
+ vd->sasl.authzid = g_strdup("vnc.username");
} else {
- aclname = g_strdup_printf("vnc.%s.username", vd->id);
+ vd->sasl.authzid = g_strdup_printf("vnc.%s.username", vd->id);
}
- vd->sasl.acl = qemu_acl_init(aclname);
- g_free(aclname);
+ vd->sasl.authz = QAUTHZ(qauthz_list_new(vd->sasl.authzid,
+ QAUTHZ_LIST_POLICY_DENY,
+ &error_abort));
}
#endif
diff --git a/ui/vnc.h b/ui/vnc.h
index 81daa7a..ee3da08 100644
--- a/ui/vnc.h
+++ b/ui/vnc.h
@@ -39,6 +39,7 @@
#include "io/channel-socket.h"
#include "io/channel-tls.h"
#include "io/net-listener.h"
+#include "authz/base.h"
#include <zlib.h>
#include "keymaps.h"
@@ -178,7 +179,8 @@
bool lossy;
bool non_adaptive;
QCryptoTLSCreds *tlscreds;
- char *tlsaclname;
+ QAuthZ *tlsauthz;
+ char *tlsauthzid;
#ifdef CONFIG_VNC_SASL
VncDisplaySASL sasl;
#endif
diff --git a/util/Makefile.objs b/util/Makefile.objs
index 0820923..0808575 100644
--- a/util/Makefile.objs
+++ b/util/Makefile.objs
@@ -20,7 +20,6 @@
util-obj-y += host-utils.o
util-obj-y += bitmap.o bitops.o hbitmap.o
util-obj-y += fifo8.o
-util-obj-y += acl.o
util-obj-y += cacheinfo.o
util-obj-y += error.o qemu-error.o
util-obj-y += id.o
@@ -50,5 +49,8 @@
util-obj-y += stats64.o
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
+
+stub-obj-y += filemonitor-stub.o
diff --git a/util/acl.c b/util/acl.c
deleted file mode 100644
index c105add..0000000
--- a/util/acl.c
+++ /dev/null
@@ -1,179 +0,0 @@
-/*
- * QEMU access control list management
- *
- * Copyright (C) 2009 Red Hat, Inc
- *
- * 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"
-#include "qemu-common.h"
-#include "qemu/acl.h"
-
-#ifdef CONFIG_FNMATCH
-#include <fnmatch.h>
-#endif
-
-
-static unsigned int nacls = 0;
-static qemu_acl **acls = NULL;
-
-
-
-qemu_acl *qemu_acl_find(const char *aclname)
-{
- int i;
- for (i = 0 ; i < nacls ; i++) {
- if (strcmp(acls[i]->aclname, aclname) == 0)
- return acls[i];
- }
-
- return NULL;
-}
-
-qemu_acl *qemu_acl_init(const char *aclname)
-{
- qemu_acl *acl;
-
- acl = qemu_acl_find(aclname);
- if (acl)
- return acl;
-
- acl = g_malloc(sizeof(*acl));
- acl->aclname = g_strdup(aclname);
- /* Deny by default, so there is no window of "open
- * access" between QEMU starting, and the user setting
- * up ACLs in the monitor */
- acl->defaultDeny = 1;
-
- acl->nentries = 0;
- QTAILQ_INIT(&acl->entries);
-
- acls = g_realloc(acls, sizeof(*acls) * (nacls +1));
- acls[nacls] = acl;
- nacls++;
-
- return acl;
-}
-
-int qemu_acl_party_is_allowed(qemu_acl *acl,
- const char *party)
-{
- qemu_acl_entry *entry;
-
- QTAILQ_FOREACH(entry, &acl->entries, next) {
-#ifdef CONFIG_FNMATCH
- if (fnmatch(entry->match, party, 0) == 0)
- return entry->deny ? 0 : 1;
-#else
- /* No fnmatch, so fallback to exact string matching
- * instead of allowing wildcards */
- if (strcmp(entry->match, party) == 0)
- return entry->deny ? 0 : 1;
-#endif
- }
-
- return acl->defaultDeny ? 0 : 1;
-}
-
-
-void qemu_acl_reset(qemu_acl *acl)
-{
- qemu_acl_entry *entry, *next_entry;
-
- /* Put back to deny by default, so there is no window
- * of "open access" while the user re-initializes the
- * access control list */
- acl->defaultDeny = 1;
- QTAILQ_FOREACH_SAFE(entry, &acl->entries, next, next_entry) {
- QTAILQ_REMOVE(&acl->entries, entry, next);
- g_free(entry->match);
- g_free(entry);
- }
- acl->nentries = 0;
-}
-
-
-int qemu_acl_append(qemu_acl *acl,
- int deny,
- const char *match)
-{
- qemu_acl_entry *entry;
-
- entry = g_malloc(sizeof(*entry));
- entry->match = g_strdup(match);
- entry->deny = deny;
-
- QTAILQ_INSERT_TAIL(&acl->entries, entry, next);
- acl->nentries++;
-
- return acl->nentries;
-}
-
-
-int qemu_acl_insert(qemu_acl *acl,
- int deny,
- const char *match,
- int index)
-{
- qemu_acl_entry *tmp;
- int i = 0;
-
- if (index <= 0)
- return -1;
- if (index > acl->nentries) {
- return qemu_acl_append(acl, deny, match);
- }
-
- QTAILQ_FOREACH(tmp, &acl->entries, next) {
- i++;
- if (i == index) {
- qemu_acl_entry *entry;
- entry = g_malloc(sizeof(*entry));
- entry->match = g_strdup(match);
- entry->deny = deny;
-
- QTAILQ_INSERT_BEFORE(tmp, entry, next);
- acl->nentries++;
- break;
- }
- }
-
- return i;
-}
-
-int qemu_acl_remove(qemu_acl *acl,
- const char *match)
-{
- qemu_acl_entry *entry;
- int i = 0;
-
- QTAILQ_FOREACH(entry, &acl->entries, next) {
- i++;
- if (strcmp(entry->match, match) == 0) {
- QTAILQ_REMOVE(&acl->entries, entry, next);
- acl->nentries--;
- g_free(entry->match);
- g_free(entry);
- return i;
- }
- }
- return -1;
-}
diff --git a/util/aio-posix.c b/util/aio-posix.c
index 8640dfd..6fbfa79 100644
--- a/util/aio-posix.c
+++ b/util/aio-posix.c
@@ -613,6 +613,8 @@
int64_t timeout;
int64_t start = 0;
+ assert(in_aio_context_home_thread(ctx));
+
/* aio_notify can avoid the expensive event_notifier_set if
* everything (file descriptors, bottom halves, timers) will
* be re-evaluated before the next blocking poll(). This is
@@ -621,7 +623,6 @@
* so disable the optimization now.
*/
if (blocking) {
- assert(in_aio_context_home_thread(ctx));
atomic_add(&ctx->notify_me, 2);
}
diff --git a/util/filemonitor-inotify.c b/util/filemonitor-inotify.c
new file mode 100644
index 0000000..3a72be0
--- /dev/null
+++ b/util/filemonitor-inotify.c
@@ -0,0 +1,339 @@
+/*
+ * QEMU file monitor Linux inotify impl
+ *
+ * Copyright (c) 2018 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * 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 "qemu/filemonitor.h"
+#include "qemu/main-loop.h"
+#include "qemu/error-report.h"
+#include "qapi/error.h"
+#include "trace.h"
+
+#include <sys/inotify.h>
+
+struct QFileMonitor {
+ int fd;
+
+ QemuMutex lock; /* protects dirs & idmap */
+ GHashTable *dirs; /* dirname => QFileMonitorDir */
+ GHashTable *idmap; /* inotify ID => dirname */
+};
+
+
+typedef struct {
+ int id; /* watch ID */
+ char *filename; /* optional filter */
+ QFileMonitorHandler cb;
+ void *opaque;
+} QFileMonitorWatch;
+
+
+typedef struct {
+ char *path;
+ int id; /* inotify ID */
+ int nextid; /* watch ID counter */
+ GArray *watches; /* QFileMonitorWatch elements */
+} QFileMonitorDir;
+
+
+static void qemu_file_monitor_watch(void *arg)
+{
+ QFileMonitor *mon = arg;
+ char buf[4096]
+ __attribute__ ((aligned(__alignof__(struct inotify_event))));
+ int used = 0;
+ int len;
+
+ qemu_mutex_lock(&mon->lock);
+
+ if (mon->fd == -1) {
+ qemu_mutex_unlock(&mon->lock);
+ return;
+ }
+
+ len = read(mon->fd, buf, sizeof(buf));
+
+ if (len < 0) {
+ if (errno != EAGAIN) {
+ error_report("Failure monitoring inotify FD '%s',"
+ "disabling events", strerror(errno));
+ goto cleanup;
+ }
+
+ /* no more events right now */
+ goto cleanup;
+ }
+
+ /* Loop over all events in the buffer */
+ while (used < len) {
+ struct inotify_event *ev =
+ (struct inotify_event *)(buf + used);
+ const char *name = ev->len ? ev->name : "";
+ QFileMonitorDir *dir = g_hash_table_lookup(mon->idmap,
+ GINT_TO_POINTER(ev->wd));
+ uint32_t iev = ev->mask &
+ (IN_CREATE | IN_MODIFY | IN_DELETE | IN_IGNORED |
+ IN_MOVED_TO | IN_MOVED_FROM | IN_ATTRIB);
+ int qev;
+ gsize i;
+
+ used += sizeof(struct inotify_event) + ev->len;
+
+ if (!dir) {
+ continue;
+ }
+
+ /*
+ * During a rename operation, the old name gets
+ * IN_MOVED_FROM and the new name gets IN_MOVED_TO.
+ * To simplify life for callers, we turn these into
+ * DELETED and CREATED events
+ */
+ switch (iev) {
+ case IN_CREATE:
+ case IN_MOVED_TO:
+ qev = QFILE_MONITOR_EVENT_CREATED;
+ break;
+ case IN_MODIFY:
+ qev = QFILE_MONITOR_EVENT_MODIFIED;
+ break;
+ case IN_DELETE:
+ case IN_MOVED_FROM:
+ qev = QFILE_MONITOR_EVENT_DELETED;
+ break;
+ case IN_ATTRIB:
+ qev = QFILE_MONITOR_EVENT_ATTRIBUTES;
+ break;
+ case IN_IGNORED:
+ qev = QFILE_MONITOR_EVENT_IGNORED;
+ break;
+ default:
+ g_assert_not_reached();
+ }
+
+ trace_qemu_file_monitor_event(mon, dir->path, name, ev->mask, dir->id);
+ for (i = 0; i < dir->watches->len; i++) {
+ QFileMonitorWatch *watch = &g_array_index(dir->watches,
+ QFileMonitorWatch,
+ i);
+
+ if (watch->filename == NULL ||
+ (name && g_str_equal(watch->filename, name))) {
+ trace_qemu_file_monitor_dispatch(mon, dir->path, name,
+ qev, watch->cb,
+ watch->opaque, watch->id);
+ watch->cb(watch->id, qev, name, watch->opaque);
+ }
+ }
+ }
+
+ cleanup:
+ qemu_mutex_unlock(&mon->lock);
+}
+
+
+static void
+qemu_file_monitor_dir_free(void *data)
+{
+ QFileMonitorDir *dir = data;
+ gsize i;
+
+ for (i = 0; i < dir->watches->len; i++) {
+ QFileMonitorWatch *watch = &g_array_index(dir->watches,
+ QFileMonitorWatch, i);
+ g_free(watch->filename);
+ }
+ g_array_unref(dir->watches);
+ g_free(dir->path);
+ g_free(dir);
+}
+
+
+QFileMonitor *
+qemu_file_monitor_new(Error **errp)
+{
+ int fd;
+ QFileMonitor *mon;
+
+ fd = inotify_init1(IN_NONBLOCK);
+ if (fd < 0) {
+ error_setg_errno(errp, errno,
+ "Unable to initialize inotify");
+ return NULL;
+ }
+
+ mon = g_new0(QFileMonitor, 1);
+ qemu_mutex_init(&mon->lock);
+ mon->fd = fd;
+
+ mon->dirs = g_hash_table_new_full(g_str_hash, g_str_equal, NULL,
+ qemu_file_monitor_dir_free);
+ mon->idmap = g_hash_table_new(g_direct_hash, g_direct_equal);
+
+ trace_qemu_file_monitor_new(mon, mon->fd);
+
+ return mon;
+}
+
+static gboolean
+qemu_file_monitor_free_idle(void *opaque)
+{
+ QFileMonitor *mon = opaque;
+
+ if (!mon) {
+ return G_SOURCE_REMOVE;
+ }
+
+ qemu_mutex_lock(&mon->lock);
+
+ g_hash_table_unref(mon->idmap);
+ g_hash_table_unref(mon->dirs);
+
+ qemu_mutex_unlock(&mon->lock);
+
+ qemu_mutex_destroy(&mon->lock);
+ g_free(mon);
+
+ return G_SOURCE_REMOVE;
+}
+
+void
+qemu_file_monitor_free(QFileMonitor *mon)
+{
+ if (!mon) {
+ return;
+ }
+
+ qemu_mutex_lock(&mon->lock);
+ if (mon->fd != -1) {
+ qemu_set_fd_handler(mon->fd, NULL, NULL, NULL);
+ close(mon->fd);
+ mon->fd = -1;
+ }
+ qemu_mutex_unlock(&mon->lock);
+
+ /*
+ * Can't free it yet, because another thread
+ * may be running event loop, so the inotify
+ * callback might be pending. Using an idle
+ * source ensures we'll only free after the
+ * pending callback is done
+ */
+ g_idle_add((GSourceFunc)qemu_file_monitor_free_idle, mon);
+}
+
+int
+qemu_file_monitor_add_watch(QFileMonitor *mon,
+ const char *dirpath,
+ const char *filename,
+ QFileMonitorHandler cb,
+ void *opaque,
+ Error **errp)
+{
+ QFileMonitorDir *dir;
+ QFileMonitorWatch watch;
+ int ret = -1;
+
+ qemu_mutex_lock(&mon->lock);
+ dir = g_hash_table_lookup(mon->dirs, dirpath);
+ if (!dir) {
+ int rv = inotify_add_watch(mon->fd, dirpath,
+ IN_CREATE | IN_DELETE | IN_MODIFY |
+ IN_MOVED_TO | IN_MOVED_FROM | IN_ATTRIB);
+
+ if (rv < 0) {
+ error_setg_errno(errp, errno, "Unable to watch '%s'", dirpath);
+ goto cleanup;
+ }
+
+ trace_qemu_file_monitor_enable_watch(mon, dirpath, rv);
+
+ dir = g_new0(QFileMonitorDir, 1);
+ dir->path = g_strdup(dirpath);
+ dir->id = rv;
+ dir->watches = g_array_new(FALSE, TRUE, sizeof(QFileMonitorWatch));
+
+ g_hash_table_insert(mon->dirs, dir->path, dir);
+ g_hash_table_insert(mon->idmap, GINT_TO_POINTER(rv), dir);
+
+ if (g_hash_table_size(mon->dirs) == 1) {
+ qemu_set_fd_handler(mon->fd, qemu_file_monitor_watch, NULL, mon);
+ }
+ }
+
+ watch.id = dir->nextid++;
+ watch.filename = g_strdup(filename);
+ watch.cb = cb;
+ watch.opaque = opaque;
+
+ g_array_append_val(dir->watches, watch);
+
+ trace_qemu_file_monitor_add_watch(mon, dirpath,
+ filename ? filename : "<none>",
+ cb, opaque, watch.id);
+
+ ret = watch.id;
+
+ cleanup:
+ qemu_mutex_unlock(&mon->lock);
+ return ret;
+}
+
+
+void qemu_file_monitor_remove_watch(QFileMonitor *mon,
+ const char *dirpath,
+ int id)
+{
+ QFileMonitorDir *dir;
+ gsize i;
+
+ qemu_mutex_lock(&mon->lock);
+
+ trace_qemu_file_monitor_remove_watch(mon, dirpath, id);
+
+ dir = g_hash_table_lookup(mon->dirs, dirpath);
+ if (!dir) {
+ goto cleanup;
+ }
+
+ for (i = 0; i < dir->watches->len; i++) {
+ QFileMonitorWatch *watch = &g_array_index(dir->watches,
+ QFileMonitorWatch, i);
+ if (watch->id == id) {
+ g_free(watch->filename);
+ g_array_remove_index(dir->watches, i);
+ break;
+ }
+ }
+
+ if (dir->watches->len == 0) {
+ inotify_rm_watch(mon->fd, dir->id);
+ trace_qemu_file_monitor_disable_watch(mon, dir->path, dir->id);
+
+ g_hash_table_remove(mon->idmap, GINT_TO_POINTER(dir->id));
+ g_hash_table_remove(mon->dirs, dir->path);
+
+ if (g_hash_table_size(mon->dirs) == 0) {
+ qemu_set_fd_handler(mon->fd, NULL, NULL, NULL);
+ }
+ }
+
+ cleanup:
+ qemu_mutex_unlock(&mon->lock);
+}
diff --git a/util/filemonitor-stub.c b/util/filemonitor-stub.c
new file mode 100644
index 0000000..48268b2
--- /dev/null
+++ b/util/filemonitor-stub.c
@@ -0,0 +1,59 @@
+/*
+ * QEMU file monitor stub impl
+ *
+ * Copyright (c) 2018 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * 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 "qemu/filemonitor.h"
+#include "qemu/error-report.h"
+#include "qapi/error.h"
+
+
+QFileMonitor *
+qemu_file_monitor_new(Error **errp)
+{
+ error_setg(errp, "File monitoring not available on this platform");
+ return NULL;
+}
+
+
+void
+qemu_file_monitor_free(QFileMonitor *mon G_GNUC_UNUSED)
+{
+}
+
+
+int
+qemu_file_monitor_add_watch(QFileMonitor *mon G_GNUC_UNUSED,
+ const char *dirpath G_GNUC_UNUSED,
+ const char *filename G_GNUC_UNUSED,
+ QFileMonitorHandler cb G_GNUC_UNUSED,
+ void *opaque G_GNUC_UNUSED,
+ Error **errp)
+{
+ error_setg(errp, "File monitoring not available on this platform");
+ return -1;
+}
+
+
+void
+qemu_file_monitor_remove_watch(QFileMonitor *mon G_GNUC_UNUSED,
+ const char *dirpath G_GNUC_UNUSED,
+ int id G_GNUC_UNUSED)
+{
+}
diff --git a/util/trace-events b/util/trace-events
index 79569b7..ff19b25 100644
--- a/util/trace-events
+++ b/util/trace-events
@@ -21,6 +21,15 @@
buffer_move(const char *buf, size_t len, const char *from) "%s: %zd bytes from %s"
buffer_free(const char *buf, size_t len) "%s: capacity %zd"
+# util/filemonitor.c
+qemu_file_monitor_add_watch(void *mon, const char *dirpath, const char *filename, void *cb, void *opaque, int id) "File monitor %p add watch dir='%s' file='%s' cb=%p opaque=%p id=%u"
+qemu_file_monitor_remove_watch(void *mon, const char *dirpath, int id) "File monitor %p remove watch dir='%s' id=%u"
+qemu_file_monitor_new(void *mon, int fd) "File monitor %p created fd=%d"
+qemu_file_monitor_enable_watch(void *mon, const char *dirpath, int id) "File monitor %p enable watch dir='%s' id=%u"
+qemu_file_monitor_disable_watch(void *mon, const char *dirpath, int id) "Fle monitor %p disable watch dir='%s' id=%u"
+qemu_file_monitor_event(void *mon, const char *dirpath, const char *filename, int mask, unsigned int id) "File monitor %p event dir='%s' file='%s' mask=0x%x id=%u"
+qemu_file_monitor_dispatch(void *mon, const char *dirpath, const char *filename, int ev, void *cb, void *opaque, unsigned int id) "File monitor %p dispatch dir='%s' file='%s' ev=%d cb=%p opaque=%p id=%u"
+
# util/qemu-coroutine.c
qemu_aio_coroutine_enter(void *ctx, void *from, void *to, void *opaque) "ctx %p from %p to %p opaque %p"
qemu_coroutine_yield(void *from, void *to) "from %p to %p"
diff --git a/util/vfio-helpers.c b/util/vfio-helpers.c
index 342d4a2..2367fe8 100644
--- a/util/vfio-helpers.c
+++ b/util/vfio-helpers.c
@@ -391,10 +391,10 @@
}
}
-static int qemu_vfio_init_ramblock(const char *block_name, void *host_addr,
- ram_addr_t offset, ram_addr_t length,
- void *opaque)
+static int qemu_vfio_init_ramblock(RAMBlock *rb, void *opaque)
{
+ void *host_addr = qemu_ram_get_host_addr(rb);
+ ram_addr_t length = qemu_ram_get_used_length(rb);
int ret;
QEMUVFIOState *s = opaque;
diff --git a/vl.c b/vl.c
index 502857a..4c5cc0d 100644
--- a/vl.c
+++ b/vl.c
@@ -3039,6 +3039,7 @@
module_call_init(MODULE_INIT_OPTS);
runstate_init();
+ precopy_infrastructure_init();
postcopy_infrastructure_init();
monitor_init_globals();
@@ -4239,6 +4240,9 @@
machine_opts = qemu_get_machine_opts();
qemu_opt_foreach(machine_opts, machine_set_property, current_machine,
&error_fatal);
+ current_machine->ram_size = ram_size;
+ current_machine->maxram_size = maxram_size;
+ current_machine->ram_slots = ram_slots;
configure_accelerator(current_machine, argv[0]);
@@ -4434,9 +4438,6 @@
replay_checkpoint(CHECKPOINT_INIT);
qdev_machine_init();
- current_machine->ram_size = ram_size;
- current_machine->maxram_size = maxram_size;
- current_machine->ram_slots = ram_slots;
current_machine->boot_order = boot_order;
/* parse features once if machine provides default cpu_type */
@@ -4579,6 +4580,12 @@
gdbserver_cleanup();
+ /*
+ * cleaning up the migration object cancels any existing migration
+ * try to do this early so that it also stops using devices.
+ */
+ migration_shutdown();
+
/* No more vcpu or device emulation activity beyond this point */
vm_shutdown();
@@ -4594,7 +4601,6 @@
monitor_cleanup();
qemu_chr_cleanup();
user_creatable_cleanup();
- migration_object_finalize();
/* TODO: unref root container, check all devices are ok */
return 0;