* [PULL 00/33] MIPS patches for 2026-05-20
@ 2026-05-20 19:23 Philippe Mathieu-Daudé
2026-05-20 19:23 ` [PULL 01/33] docker: Remove LegacyKeyValueFormat warnings in non-generated files Philippe Mathieu-Daudé
` (33 more replies)
0 siblings, 34 replies; 35+ messages in thread
From: Philippe Mathieu-Daudé @ 2026-05-20 19:23 UTC (permalink / raw)
To: qemu-devel
The following changes since commit e89049b3ba5f1f0468bc0d294173345597514a1b:
Merge tag 'for-upstream' of https://repo.or.cz/qemu/kevin into staging (2026-05-19 15:23:10 -0400)
are available in the Git repository at:
https://github.com/philmd/qemu.git tags/mips-20260520
for you to fetch changes up to 2f3eee6bda6190d3acacfeb11fd1b723e08c5a2c:
target/mips: add Octeon LA* atomic instructions (2026-05-20 21:22:56 +0200)
----------------------------------------------------------------
MIPS patches queue
- Remove support for MIPS host
- Avoid Coverity complaint in gic_write (CID 1547545)
- Add various Octeon integer, multiplier, indexed memory, atomic instructions
----------------------------------------------------------------
James Hilliard (23):
linux-user/mips: implement sysmips(MIPS_FLUSH_CACHE)
linux-user/mips: implement sysmips(MIPS_ATOMIC_SET)
linux-user/mips, target/mips: honor MIPS_FIXADE for unaligned accesses
target/mips: expose Octeon68XX floating-point support
tests/tcg/mips: add Octeon instruction smoke test
target/mips: fix Octeon arithmetic destination handling
target/mips: drop Octeon zero-register fast paths
target/mips: split Octeon SEQ/SNE decode
target/mips: split Octeon SEQI/SNEI decode
target/mips: add Octeon LBX instruction
target/mips: add Octeon LHUX instruction
target/mips: add Octeon LWUX instruction
target/mips: add Octeon SAA instruction
target/mips: add Octeon SAAD instruction
target/mips: add Octeon ZCB and ZCBT instructions
target/mips: add Octeon multiplier state
target/mips: add Octeon MTM instructions
target/mips: add Octeon MTP instructions
target/mips: add Octeon VMULU instruction
target/mips: add Octeon VMM0 instruction
target/mips: add Octeon V3MULU instruction
target/mips: add Octeon QMAC instructions
target/mips: add Octeon LA* atomic instructions
Peter Maydell (1):
hw/intc/mips_gic: Avoid Coverity complaint in VP writes
Philippe Mathieu-Daudé (8):
docker: Remove LegacyKeyValueFormat warnings in non-generated files
docker: Remove LegacyKeyValueFormat warnings in generated files
buildsys: Remove MIPS cross containers
buildsys: Remove support for MIPS hosts
hw/mips: Include missing 'cpu.h' header
buildsys: Remove MIPS KVM
buildsys: Remove MIPS TCG backend
tcg: Introduce tcg_zero_i128()
Richard Henderson (1):
tcg: Introduce tcg_gen_addN_i64
MAINTAINERS | 17 +-
docs/about/deprecated.rst | 8 -
docs/about/removed-features.rst | 6 +
docs/system/target-mips.rst | 2 -
configure | 20 -
meson.build | 12 +-
include/qemu/timer.h | 30 -
include/tcg/tcg-op-common.h | 3 +
include/user/thunk.h | 2 +-
linux-user/include/host/mips64/host-signal.h | 75 -
linux-user/mips/target_syscall.h | 3 +
linux-user/mips64/target_syscall.h | 3 +
target/mips/cpu.h | 16 +
target/mips/kvm_mips.h | 28 -
target/mips/tcg/translate.h | 2 +
tcg/mips64/tcg-target-con-set.h | 30 -
tcg/mips64/tcg-target-con-str.h | 20 -
tcg/mips64/tcg-target-has.h | 69 -
tcg/mips64/tcg-target-mo.h | 13 -
tcg/mips64/tcg-target.h | 75 -
tcg/mips64/tcg-target-opc.h.inc | 1 -
target/mips/tcg/octeon.decode | 54 +-
hw/intc/mips_gic.c | 21 +-
hw/mips/loongson3_virt.c | 67 +-
hw/mips/malta.c | 1 -
hw/mips/mips_int.c | 7 +-
linux-user/mips/cpu_loop.c | 5 +
linux-user/mmap.c | 2 +-
linux-user/syscall.c | 56 +
target/arm/tcg/translate-a64.c | 5 +-
target/mips/cpu.c | 15 +-
target/mips/kvm.c | 1283 --------
target/mips/system/cp0_timer.c | 12 +-
target/mips/system/machine.c | 33 +
target/mips/system/physaddr.c | 1 -
target/mips/tcg/octeon_translate.c | 380 ++-
target/mips/tcg/translate.c | 24 +-
tcg/tcg-op.c | 52 +
tests/tcg/mips/user/isa/octeon/octeon-insns.c | 204 ++
util/cacheflush.c | 16 -
target/mips/cpu-defs.c.inc | 10 +-
tcg/mips64/tcg-target.c.inc | 2605 -----------------
tests/lcitool/refresh | 24 +-
tests/docker/dockerfiles/alpine.docker | 2 +-
tests/docker/dockerfiles/centos9.docker | 2 +-
.../dockerfiles/debian-all-test-cross.docker | 10 +-
.../dockerfiles/debian-amd64-cross.docker | 2 +-
.../dockerfiles/debian-arm64-cross.docker | 2 +-
.../dockerfiles/debian-armhf-cross.docker | 2 +-
.../dockerfiles/debian-hexagon-cross.docker | 14 +-
.../dockerfiles/debian-i686-cross.docker | 2 +-
.../dockerfiles/debian-loongarch-cross.docker | 10 +-
.../dockerfiles/debian-mips64el-cross.docker | 186 --
.../dockerfiles/debian-mipsel-cross.docker | 186 --
.../dockerfiles/debian-ppc64el-cross.docker | 2 +-
.../dockerfiles/debian-riscv64-cross.docker | 2 +-
.../dockerfiles/debian-s390x-cross.docker | 2 +-
.../dockerfiles/debian-tricore-cross.docker | 6 +-
.../dockerfiles/debian-xtensa-cross.docker | 8 +-
tests/docker/dockerfiles/debian.docker | 2 +-
.../dockerfiles/fedora-rust-nightly.docker | 2 +-
.../dockerfiles/fedora-win64-cross.docker | 2 +-
tests/docker/dockerfiles/fedora.docker | 2 +-
tests/docker/dockerfiles/opensuse-leap.docker | 2 +-
tests/docker/dockerfiles/python.docker | 5 +-
.gitlab-ci.d/container-cross.yml | 6 -
.gitlab-ci.d/containers.yml | 1 -
.gitlab-ci.d/crossbuilds.yml | 22 -
common-user/host/mips64/safe-syscall.inc.S | 114 -
scripts/coverity-scan/coverity-scan.docker | 12 +-
scripts/git.orderfile | 4 +
target/mips/meson.build | 6 +-
tests/docker/Makefile.include | 1 -
tests/tcg/mips64/Makefile.target | 20 +
tests/tcg/mips64el/Makefile.target | 8 +
75 files changed, 924 insertions(+), 5035 deletions(-)
delete mode 100644 linux-user/include/host/mips64/host-signal.h
delete mode 100644 target/mips/kvm_mips.h
delete mode 100644 tcg/mips64/tcg-target-con-set.h
delete mode 100644 tcg/mips64/tcg-target-con-str.h
delete mode 100644 tcg/mips64/tcg-target-has.h
delete mode 100644 tcg/mips64/tcg-target-mo.h
delete mode 100644 tcg/mips64/tcg-target.h
delete mode 100644 tcg/mips64/tcg-target-opc.h.inc
delete mode 100644 target/mips/kvm.c
create mode 100644 tests/tcg/mips/user/isa/octeon/octeon-insns.c
delete mode 100644 tcg/mips64/tcg-target.c.inc
delete mode 100644 tests/docker/dockerfiles/debian-mips64el-cross.docker
delete mode 100644 tests/docker/dockerfiles/debian-mipsel-cross.docker
delete mode 100644 common-user/host/mips64/safe-syscall.inc.S
create mode 100644 tests/tcg/mips64/Makefile.target
create mode 100644 tests/tcg/mips64el/Makefile.target
--
2.53.0
^ permalink raw reply [flat|nested] 35+ messages in thread
* [PULL 01/33] docker: Remove LegacyKeyValueFormat warnings in non-generated files
2026-05-20 19:23 [PULL 00/33] MIPS patches for 2026-05-20 Philippe Mathieu-Daudé
@ 2026-05-20 19:23 ` Philippe Mathieu-Daudé
2026-05-20 19:23 ` [PULL 02/33] docker: Remove LegacyKeyValueFormat warnings in generated files Philippe Mathieu-Daudé
` (32 subsequent siblings)
33 siblings, 0 replies; 35+ messages in thread
From: Philippe Mathieu-Daudé @ 2026-05-20 19:23 UTC (permalink / raw)
To: qemu-devel
Manually update Dockerfiles to not use legacy 'ENV key value' format:
https://docs.docker.com/reference/build-checks/legacy-key-value-format/
This removes warnings when building / using the containers:
- LegacyKeyValueFormat: "ENV key=value" should be used instead of legacy "ENV key value" format (line 98)
- LegacyKeyValueFormat: "ENV key=value" should be used instead of legacy "ENV key value" format (line 64)
- LegacyKeyValueFormat: "ENV key=value" should be used instead of legacy "ENV key value" format (line 97)
Signed-off-by: Philippe Mathieu-Daudé <philmd@linaro.org>
Reviewed-by: Pierrick Bouvier <pierrick.bouvier@oss.qualcomm.com>
Reviewed-by: Brian Cain <brian.cain@oss.qualcomm.com>
Message-ID: <20260518102222.80735-7-philmd@linaro.org>
Signed-off-by: Alex Bennée <alex.bennee@linaro.org>
---
.../docker/dockerfiles/debian-hexagon-cross.docker | 14 +++++++-------
.../dockerfiles/debian-loongarch-cross.docker | 10 +++++-----
.../docker/dockerfiles/debian-tricore-cross.docker | 6 +++---
.../docker/dockerfiles/debian-xtensa-cross.docker | 8 ++++----
tests/docker/dockerfiles/python.docker | 5 +++--
scripts/coverity-scan/coverity-scan.docker | 12 ++++++------
6 files changed, 28 insertions(+), 27 deletions(-)
diff --git a/tests/docker/dockerfiles/debian-hexagon-cross.docker b/tests/docker/dockerfiles/debian-hexagon-cross.docker
index 91d4b71ac95..3c94f040b81 100644
--- a/tests/docker/dockerfiles/debian-hexagon-cross.docker
+++ b/tests/docker/dockerfiles/debian-hexagon-cross.docker
@@ -39,15 +39,15 @@ RUN apt-get update && \
ln -s /usr/bin/ccache /usr/libexec/ccache-wrappers/gcc && \
dpkg-query --showformat '${Package}_${Version}_${Architecture}\n' --show > /packages.txt
-ENV TOOLCHAIN_INSTALL /opt
-ENV TOOLCHAIN_RELEASE 12.Dec.2023
-ENV TOOLCHAIN_BASENAME "clang+llvm-${TOOLCHAIN_RELEASE}-cross-hexagon-unknown-linux-musl"
-ENV TOOLCHAIN_URL https://codelinaro.jfrog.io/artifactory/codelinaro-toolchain-for-hexagon/${TOOLCHAIN_RELEASE}/${TOOLCHAIN_BASENAME}.tar.xz
-ENV CCACHE_WRAPPERSDIR "/usr/libexec/ccache-wrappers"
+ENV TOOLCHAIN_INSTALL=/opt
+ENV TOOLCHAIN_RELEASE=12.Dec.2023
+ENV TOOLCHAIN_BASENAME=clang+llvm-${TOOLCHAIN_RELEASE}-cross-hexagon-unknown-linux-musl
+ENV TOOLCHAIN_URL=https://codelinaro.jfrog.io/artifactory/codelinaro-toolchain-for-hexagon/${TOOLCHAIN_RELEASE}/${TOOLCHAIN_BASENAME}.tar.xz
+ENV CCACHE_WRAPPERSDIR=/usr/libexec/ccache-wrappers
RUN curl -#SL "$TOOLCHAIN_URL" | tar -xJC "$TOOLCHAIN_INSTALL"
-ENV PATH $PATH:${TOOLCHAIN_INSTALL}/${TOOLCHAIN_BASENAME}/x86_64-linux-gnu/bin
-ENV MAKE /usr/bin/make
+ENV PATH=$PATH:${TOOLCHAIN_INSTALL}/${TOOLCHAIN_BASENAME}/x86_64-linux-gnu/bin
+ENV MAKE=/usr/bin/make
# As a final step configure the user (if env is defined)
ARG USER
ARG UID
diff --git a/tests/docker/dockerfiles/debian-loongarch-cross.docker b/tests/docker/dockerfiles/debian-loongarch-cross.docker
index 55b3dbe4510..d2ba07972ce 100644
--- a/tests/docker/dockerfiles/debian-loongarch-cross.docker
+++ b/tests/docker/dockerfiles/debian-loongarch-cross.docker
@@ -40,12 +40,12 @@ RUN apt-get update && \
RUN curl -#SL https://github.com/loongson/build-tools/releases/download/2023.08.08/CLFS-loongarch64-8.1-x86_64-cross-tools-gcc-glibc.tar.xz \
| tar -xJC /opt
-ENV PATH $PATH:/opt/cross-tools/bin
-ENV LD_LIBRARY_PATH /opt/cross-tools/lib:/opt/cross-tools/loongarch64-unknown-linux-gnu/lib:$LD_LIBRARY_PATH
+ENV PATH=$PATH:/opt/cross-tools/bin
+ENV LD_LIBRARY_PATH=/opt/cross-tools/lib:/opt/cross-tools/loongarch64-unknown-linux-gnu/lib:$LD_LIBRARY_PATH
-ENV QEMU_CONFIGURE_OPTS --disable-docs --disable-tools
-ENV DEF_TARGET_LIST loongarch64-linux-user,loongarch64-softmmu
-ENV MAKE /usr/bin/make
+ENV QEMU_CONFIGURE_OPTS="--disable-docs --disable-tools"
+ENV DEF_TARGET_LIST=loongarch64-linux-user,loongarch64-softmmu
+ENV MAKE=/usr/bin/make
# As a final step configure the user (if env is defined)
ARG USER
diff --git a/tests/docker/dockerfiles/debian-tricore-cross.docker b/tests/docker/dockerfiles/debian-tricore-cross.docker
index fd797dc7ee4..9e7ff321677 100644
--- a/tests/docker/dockerfiles/debian-tricore-cross.docker
+++ b/tests/docker/dockerfiles/debian-tricore-cross.docker
@@ -40,9 +40,9 @@ RUN curl -#SL https://github.com/bkoppelmann/package_940/releases/download/trico
| tar -xzC /usr/local/
# This image can only build a very minimal QEMU as well as the tests
-ENV DEF_TARGET_LIST tricore-softmmu
-ENV QEMU_CONFIGURE_OPTS --disable-user --disable-tools --disable-fdt
-ENV MAKE /usr/bin/make
+ENV DEF_TARGET_LIST=tricore-softmmu
+ENV QEMU_CONFIGURE_OPTS="--disable-user --disable-tools --disable-fdt"
+ENV MAKE=/usr/bin/make
# As a final step configure the user (if env is defined)
ARG USER
ARG UID
diff --git a/tests/docker/dockerfiles/debian-xtensa-cross.docker b/tests/docker/dockerfiles/debian-xtensa-cross.docker
index ef63e44e2ef..d9130fc3378 100644
--- a/tests/docker/dockerfiles/debian-xtensa-cross.docker
+++ b/tests/docker/dockerfiles/debian-xtensa-cross.docker
@@ -19,16 +19,16 @@ RUN apt-get update && \
python3-minimal && \
dpkg-query --showformat '${Package}_${Version}_${Architecture}\n' --show > /packages.txt
-ENV CPU_LIST dc232b dc233c de233_fpu dsp3400
-ENV TOOLCHAIN_RELEASE 2020.07
+ENV CPU_LIST="dc232b dc233c de233_fpu dsp3400"
+ENV TOOLCHAIN_RELEASE=2020.07
RUN for cpu in $CPU_LIST; do \
curl -#SL http://github.com/foss-xtensa/toolchain/releases/download/$TOOLCHAIN_RELEASE/x86_64-$TOOLCHAIN_RELEASE-xtensa-$cpu-elf.tar.gz \
| tar -xzC /opt; \
done
-ENV PATH $PATH:/opt/$TOOLCHAIN_RELEASE/xtensa-dc232b-elf/bin:/opt/$TOOLCHAIN_RELEASE/xtensa-dc233c-elf/bin:/opt/$TOOLCHAIN_RELEASE/xtensa-de233_fpu-elf/bin:/opt/$TOOLCHAIN_RELEASE/xtensa-dsp3400-elf/bin
-ENV MAKE /usr/bin/make
+ENV PATH=$PATH:/opt/$TOOLCHAIN_RELEASE/xtensa-dc232b-elf/bin:/opt/$TOOLCHAIN_RELEASE/xtensa-dc233c-elf/bin:/opt/$TOOLCHAIN_RELEASE/xtensa-de233_fpu-elf/bin:/opt/$TOOLCHAIN_RELEASE/xtensa-dsp3400-elf/bin
+ENV MAKE=/usr/bin/make
# As a final step configure the user (if env is defined)
ARG USER
ARG UID
diff --git a/tests/docker/dockerfiles/python.docker b/tests/docker/dockerfiles/python.docker
index 59e70a02484..79c554a2d87 100644
--- a/tests/docker/dockerfiles/python.docker
+++ b/tests/docker/dockerfiles/python.docker
@@ -4,7 +4,7 @@ FROM fedora:latest
MAINTAINER John Snow <jsnow@redhat.com>
# Please keep this list sorted alphabetically
-ENV PACKAGES \
+ENV PACKAGES="\
gcc \
make \
python3 \
@@ -15,7 +15,8 @@ ENV PACKAGES \
python3.11 \
python3.12 \
python3.13 \
- python3.9
+ python3.9 \
+ "
RUN dnf install -y $PACKAGES
RUN rpm -q $PACKAGES | sort > /packages.txt
diff --git a/scripts/coverity-scan/coverity-scan.docker b/scripts/coverity-scan/coverity-scan.docker
index 93e558c8623..30d154c0d86 100644
--- a/scripts/coverity-scan/coverity-scan.docker
+++ b/scripts/coverity-scan/coverity-scan.docker
@@ -152,12 +152,12 @@ exec "$@"' > /usr/bin/nosync && \
ln -s /usr/bin/ccache /usr/libexec/ccache-wrappers/g++ && \
ln -s /usr/bin/ccache /usr/libexec/ccache-wrappers/gcc
-ENV CCACHE_WRAPPERSDIR "/usr/libexec/ccache-wrappers"
-ENV LANG "en_US.UTF-8"
-ENV MAKE "/usr/bin/make"
-ENV NINJA "/usr/bin/ninja"
-ENV PYTHON "/usr/bin/python3"
-ENV QEMU_CONFIGURE_OPTS --meson=internal
+ENV CCACHE_WRAPPERSDIR=/usr/libexec/ccache-wrappers
+ENV LANG=en_US.UTF-8
+ENV MAKE=/usr/bin/make
+ENV NINJA=/usr/bin/ninja
+ENV PYTHON=/usr/bin/python3
+ENV QEMU_CONFIGURE_OPTS=--meson=internal
RUN dnf install -y curl wget
ENV COVERITY_TOOL_BASE=/coverity-tools
--
2.53.0
^ permalink raw reply related [flat|nested] 35+ messages in thread
* [PULL 02/33] docker: Remove LegacyKeyValueFormat warnings in generated files
2026-05-20 19:23 [PULL 00/33] MIPS patches for 2026-05-20 Philippe Mathieu-Daudé
2026-05-20 19:23 ` [PULL 01/33] docker: Remove LegacyKeyValueFormat warnings in non-generated files Philippe Mathieu-Daudé
@ 2026-05-20 19:23 ` Philippe Mathieu-Daudé
2026-05-20 19:23 ` [PULL 03/33] buildsys: Remove MIPS cross containers Philippe Mathieu-Daudé
` (31 subsequent siblings)
33 siblings, 0 replies; 35+ messages in thread
From: Philippe Mathieu-Daudé @ 2026-05-20 19:23 UTC (permalink / raw)
To: qemu-devel
Display lcitool changes before generated ones.
Update lcitool refresh script to not use legacy 'ENV key value'
format:
https://docs.docker.com/reference/build-checks/legacy-key-value-format/
Run "make lcitool-refresh" to update the generated container files.
Signed-off-by: Philippe Mathieu-Daudé <philmd@linaro.org>
Reviewed-by: Pierrick Bouvier <pierrick.bouvier@oss.qualcomm.com>
Message-ID: <20260518102222.80735-8-philmd@linaro.org>
Signed-off-by: Alex Bennée <alex.bennee@linaro.org>
---
tests/lcitool/refresh | 12 +++++++-----
tests/docker/dockerfiles/alpine.docker | 2 +-
tests/docker/dockerfiles/centos9.docker | 2 +-
.../docker/dockerfiles/debian-all-test-cross.docker | 10 ++++++----
tests/docker/dockerfiles/debian-amd64-cross.docker | 2 +-
tests/docker/dockerfiles/debian-arm64-cross.docker | 2 +-
tests/docker/dockerfiles/debian-armhf-cross.docker | 2 +-
tests/docker/dockerfiles/debian-i686-cross.docker | 2 +-
.../docker/dockerfiles/debian-mips64el-cross.docker | 2 +-
tests/docker/dockerfiles/debian-mipsel-cross.docker | 2 +-
tests/docker/dockerfiles/debian-ppc64el-cross.docker | 2 +-
tests/docker/dockerfiles/debian-riscv64-cross.docker | 2 +-
tests/docker/dockerfiles/debian-s390x-cross.docker | 2 +-
tests/docker/dockerfiles/debian.docker | 2 +-
tests/docker/dockerfiles/fedora-rust-nightly.docker | 2 +-
tests/docker/dockerfiles/fedora-win64-cross.docker | 2 +-
tests/docker/dockerfiles/fedora.docker | 2 +-
tests/docker/dockerfiles/opensuse-leap.docker | 2 +-
scripts/git.orderfile | 4 ++++
19 files changed, 33 insertions(+), 25 deletions(-)
diff --git a/tests/lcitool/refresh b/tests/lcitool/refresh
index e4d01d792b7..a736f7f0ae6 100755
--- a/tests/lcitool/refresh
+++ b/tests/lcitool/refresh
@@ -77,7 +77,7 @@ def generate_dockerfile(host, target, project="qemu", cross=None, trailer=None,
trailer = "\n".join(add_user_mapping)
if enable_rust:
- trailer += "\nENV ENABLE_RUST 1\n"
+ trailer += "\nENV ENABLE_RUST=1\n"
generate(filename, cmd, trailer)
@@ -169,7 +169,8 @@ debian_all_test_cross_compilers = [
" dpkg-dev\\\n",
" gdb-multiarch\\\n",
" libclang-rt-dev\n",
- "ENV AVAILABLE_COMPILERS gcc-aarch64-linux-gnu \\\n",
+ "ENV AVAILABLE_COMPILERS=\"\\\n",
+ " gcc-aarch64-linux-gnu \\\n",
" libc6-dev-arm64-cross \\\n",
" gcc-arm-linux-gnueabihf \\\n",
" libc6-dev-armhf-cross \\\n",
@@ -190,7 +191,8 @@ debian_all_test_cross_compilers = [
" gcc-s390x-linux-gnu \\\n",
" libc6-dev-s390x-cross\\\n",
" gcc-sh4-linux-gnu \\\n",
- " libc6-dev-sh4-cross\n",
+ " libc6-dev-sh4-cross \\\n",
+ " \"\n",
"RUN if dpkg-architecture -e amd64; then \\\n",
" export AVAILABLE_COMPILERS=\"${AVAILABLE_COMPILERS} gcc-hppa-linux-gnu libc6-dev-hppa-cross\"; \\\n",
" export AVAILABLE_COMPILERS=\"${AVAILABLE_COMPILERS} gcc-m68k-linux-gnu libc6-dev-m68k-cross\"; \\\n",
@@ -202,8 +204,8 @@ debian_all_test_cross_compilers = [
"apt install -y --no-install-recommends \\\n",
"${AVAILABLE_COMPILERS} && \\\n",
"dpkg-query --showformat '${Package}_${Version}_${Architecture}' --show > /packages.txt\n",
- "ENV QEMU_CONFIGURE_OPTS --disable-docs\n",
- "ENV DEF_TARGET_LIST aarch64-linux-user,alpha-linux-user,arm-linux-user,hppa-linux-user,i386-linux-user,m68k-linux-user,mips-linux-user,mips64-linux-user,mips64el-linux-user,mipsel-linux-user,ppc-linux-user,ppc64-linux-user,ppc64le-linux-user,riscv64-linux-user,s390x-linux-user,sh4-linux-user,sparc64-linux-user\n",
+ "ENV QEMU_CONFIGURE_OPTS=--disable-docs\n",
+ "ENV DEF_TARGET_LIST=aarch64-linux-user,alpha-linux-user,arm-linux-user,hppa-linux-user,i386-linux-user,m68k-linux-user,mips-linux-user,mips64-linux-user,mips64el-linux-user,mipsel-linux-user,ppc-linux-user,ppc64-linux-user,ppc64le-linux-user,riscv64-linux-user,s390x-linux-user,sh4-linux-user,sparc64-linux-user\n",
]
def cross_build(prefix, targets):
diff --git a/tests/docker/dockerfiles/alpine.docker b/tests/docker/dockerfiles/alpine.docker
index a7ee85fcda7..118c6e8eeaf 100644
--- a/tests/docker/dockerfiles/alpine.docker
+++ b/tests/docker/dockerfiles/alpine.docker
@@ -141,4 +141,4 @@ ARG UID
RUN if [ "${USER}" ]; then \
id ${USER} 2>/dev/null || useradd -u ${UID} -U ${USER}; fi
-ENV ENABLE_RUST 1
+ENV ENABLE_RUST=1
diff --git a/tests/docker/dockerfiles/centos9.docker b/tests/docker/dockerfiles/centos9.docker
index 41a1225856e..0d5b5fa7f59 100644
--- a/tests/docker/dockerfiles/centos9.docker
+++ b/tests/docker/dockerfiles/centos9.docker
@@ -145,4 +145,4 @@ ARG UID
RUN if [ "${USER}" ]; then \
id ${USER} 2>/dev/null || useradd -u ${UID} -U ${USER}; fi
-ENV ENABLE_RUST 1
+ENV ENABLE_RUST=1
diff --git a/tests/docker/dockerfiles/debian-all-test-cross.docker b/tests/docker/dockerfiles/debian-all-test-cross.docker
index 287770a995a..a10ffc73500 100644
--- a/tests/docker/dockerfiles/debian-all-test-cross.docker
+++ b/tests/docker/dockerfiles/debian-all-test-cross.docker
@@ -61,7 +61,8 @@ RUN DEBIAN_FRONTEND=noninteractive eatmydata \
dpkg-dev\
gdb-multiarch\
libclang-rt-dev
-ENV AVAILABLE_COMPILERS gcc-aarch64-linux-gnu \
+ENV AVAILABLE_COMPILERS="\
+ gcc-aarch64-linux-gnu \
libc6-dev-arm64-cross \
gcc-arm-linux-gnueabihf \
libc6-dev-armhf-cross \
@@ -82,7 +83,8 @@ ENV AVAILABLE_COMPILERS gcc-aarch64-linux-gnu \
gcc-s390x-linux-gnu \
libc6-dev-s390x-cross\
gcc-sh4-linux-gnu \
- libc6-dev-sh4-cross
+ libc6-dev-sh4-cross \
+ "
RUN if dpkg-architecture -e amd64; then \
export AVAILABLE_COMPILERS="${AVAILABLE_COMPILERS} gcc-hppa-linux-gnu libc6-dev-hppa-cross"; \
export AVAILABLE_COMPILERS="${AVAILABLE_COMPILERS} gcc-m68k-linux-gnu libc6-dev-m68k-cross"; \
@@ -94,8 +96,8 @@ DEBIAN_FRONTEND=noninteractive eatmydata \
apt install -y --no-install-recommends \
${AVAILABLE_COMPILERS} && \
dpkg-query --showformat '${Package}_${Version}_${Architecture}' --show > /packages.txt
-ENV QEMU_CONFIGURE_OPTS --disable-docs
-ENV DEF_TARGET_LIST aarch64-linux-user,alpha-linux-user,arm-linux-user,hppa-linux-user,i386-linux-user,m68k-linux-user,mips-linux-user,mips64-linux-user,mips64el-linux-user,mipsel-linux-user,ppc-linux-user,ppc64-linux-user,ppc64le-linux-user,riscv64-linux-user,s390x-linux-user,sh4-linux-user,sparc64-linux-user
+ENV QEMU_CONFIGURE_OPTS=--disable-docs
+ENV DEF_TARGET_LIST=aarch64-linux-user,alpha-linux-user,arm-linux-user,hppa-linux-user,i386-linux-user,m68k-linux-user,mips-linux-user,mips64-linux-user,mips64el-linux-user,mipsel-linux-user,ppc-linux-user,ppc64-linux-user,ppc64le-linux-user,riscv64-linux-user,s390x-linux-user,sh4-linux-user,sparc64-linux-user
# As a final step configure the user (if env is defined)
ARG USER
ARG UID
diff --git a/tests/docker/dockerfiles/debian-amd64-cross.docker b/tests/docker/dockerfiles/debian-amd64-cross.docker
index 35c593502fc..061cd8e9b82 100644
--- a/tests/docker/dockerfiles/debian-amd64-cross.docker
+++ b/tests/docker/dockerfiles/debian-amd64-cross.docker
@@ -188,4 +188,4 @@ ARG UID
RUN if [ "${USER}" ]; then \
id ${USER} 2>/dev/null || useradd -u ${UID} -U ${USER}; fi
-ENV ENABLE_RUST 1
+ENV ENABLE_RUST=1
diff --git a/tests/docker/dockerfiles/debian-arm64-cross.docker b/tests/docker/dockerfiles/debian-arm64-cross.docker
index d188d538365..3dfa60fdfd7 100644
--- a/tests/docker/dockerfiles/debian-arm64-cross.docker
+++ b/tests/docker/dockerfiles/debian-arm64-cross.docker
@@ -187,4 +187,4 @@ ARG UID
RUN if [ "${USER}" ]; then \
id ${USER} 2>/dev/null || useradd -u ${UID} -U ${USER}; fi
-ENV ENABLE_RUST 1
+ENV ENABLE_RUST=1
diff --git a/tests/docker/dockerfiles/debian-armhf-cross.docker b/tests/docker/dockerfiles/debian-armhf-cross.docker
index 988c87075f6..401c64269c1 100644
--- a/tests/docker/dockerfiles/debian-armhf-cross.docker
+++ b/tests/docker/dockerfiles/debian-armhf-cross.docker
@@ -185,4 +185,4 @@ ARG UID
RUN if [ "${USER}" ]; then \
id ${USER} 2>/dev/null || useradd -u ${UID} -U ${USER}; fi
-ENV ENABLE_RUST 1
+ENV ENABLE_RUST=1
diff --git a/tests/docker/dockerfiles/debian-i686-cross.docker b/tests/docker/dockerfiles/debian-i686-cross.docker
index d720ebb0bca..8b60c7b085f 100644
--- a/tests/docker/dockerfiles/debian-i686-cross.docker
+++ b/tests/docker/dockerfiles/debian-i686-cross.docker
@@ -185,4 +185,4 @@ ARG UID
RUN if [ "${USER}" ]; then \
id ${USER} 2>/dev/null || useradd -u ${UID} -U ${USER}; fi
-ENV ENABLE_RUST 1
+ENV ENABLE_RUST=1
diff --git a/tests/docker/dockerfiles/debian-mips64el-cross.docker b/tests/docker/dockerfiles/debian-mips64el-cross.docker
index d139c10c555..fc83fc0c00b 100644
--- a/tests/docker/dockerfiles/debian-mips64el-cross.docker
+++ b/tests/docker/dockerfiles/debian-mips64el-cross.docker
@@ -183,4 +183,4 @@ ARG UID
RUN if [ "${USER}" ]; then \
id ${USER} 2>/dev/null || useradd -u ${UID} -U ${USER}; fi
-ENV ENABLE_RUST 1
+ENV ENABLE_RUST=1
diff --git a/tests/docker/dockerfiles/debian-mipsel-cross.docker b/tests/docker/dockerfiles/debian-mipsel-cross.docker
index 2cfc33e8249..5f105b1d687 100644
--- a/tests/docker/dockerfiles/debian-mipsel-cross.docker
+++ b/tests/docker/dockerfiles/debian-mipsel-cross.docker
@@ -183,4 +183,4 @@ ARG UID
RUN if [ "${USER}" ]; then \
id ${USER} 2>/dev/null || useradd -u ${UID} -U ${USER}; fi
-ENV ENABLE_RUST 1
+ENV ENABLE_RUST=1
diff --git a/tests/docker/dockerfiles/debian-ppc64el-cross.docker b/tests/docker/dockerfiles/debian-ppc64el-cross.docker
index 7198036380b..2a7e8cba056 100644
--- a/tests/docker/dockerfiles/debian-ppc64el-cross.docker
+++ b/tests/docker/dockerfiles/debian-ppc64el-cross.docker
@@ -186,4 +186,4 @@ ARG UID
RUN if [ "${USER}" ]; then \
id ${USER} 2>/dev/null || useradd -u ${UID} -U ${USER}; fi
-ENV ENABLE_RUST 1
+ENV ENABLE_RUST=1
diff --git a/tests/docker/dockerfiles/debian-riscv64-cross.docker b/tests/docker/dockerfiles/debian-riscv64-cross.docker
index eb49da9781a..349de3a0bbb 100644
--- a/tests/docker/dockerfiles/debian-riscv64-cross.docker
+++ b/tests/docker/dockerfiles/debian-riscv64-cross.docker
@@ -186,4 +186,4 @@ ARG UID
RUN if [ "${USER}" ]; then \
id ${USER} 2>/dev/null || useradd -u ${UID} -U ${USER}; fi
-ENV ENABLE_RUST 1
+ENV ENABLE_RUST=1
diff --git a/tests/docker/dockerfiles/debian-s390x-cross.docker b/tests/docker/dockerfiles/debian-s390x-cross.docker
index f4c7896a75f..8bc42b1e00b 100644
--- a/tests/docker/dockerfiles/debian-s390x-cross.docker
+++ b/tests/docker/dockerfiles/debian-s390x-cross.docker
@@ -185,4 +185,4 @@ ARG UID
RUN if [ "${USER}" ]; then \
id ${USER} 2>/dev/null || useradd -u ${UID} -U ${USER}; fi
-ENV ENABLE_RUST 1
+ENV ENABLE_RUST=1
diff --git a/tests/docker/dockerfiles/debian.docker b/tests/docker/dockerfiles/debian.docker
index 85b78f7e5f8..ee8b313d654 100644
--- a/tests/docker/dockerfiles/debian.docker
+++ b/tests/docker/dockerfiles/debian.docker
@@ -175,4 +175,4 @@ ARG UID
RUN if [ "${USER}" ]; then \
id ${USER} 2>/dev/null || useradd -u ${UID} -U ${USER}; fi
-ENV ENABLE_RUST 1
+ENV ENABLE_RUST=1
diff --git a/tests/docker/dockerfiles/fedora-rust-nightly.docker b/tests/docker/dockerfiles/fedora-rust-nightly.docker
index 5e88354f133..4f84b803798 100644
--- a/tests/docker/dockerfiles/fedora-rust-nightly.docker
+++ b/tests/docker/dockerfiles/fedora-rust-nightly.docker
@@ -185,4 +185,4 @@ ARG UID
RUN if [ "${USER}" ]; then \
id ${USER} 2>/dev/null || useradd -u ${UID} -U ${USER}; fi
-ENV ENABLE_RUST 1
+ENV ENABLE_RUST=1
diff --git a/tests/docker/dockerfiles/fedora-win64-cross.docker b/tests/docker/dockerfiles/fedora-win64-cross.docker
index 751789e849b..c1e63feb46f 100644
--- a/tests/docker/dockerfiles/fedora-win64-cross.docker
+++ b/tests/docker/dockerfiles/fedora-win64-cross.docker
@@ -120,4 +120,4 @@ ARG UID
RUN if [ "${USER}" ]; then \
id ${USER} 2>/dev/null || useradd -u ${UID} -U ${USER}; fi
-ENV ENABLE_RUST 1
+ENV ENABLE_RUST=1
diff --git a/tests/docker/dockerfiles/fedora.docker b/tests/docker/dockerfiles/fedora.docker
index 393ac0cce73..a6996917c4b 100644
--- a/tests/docker/dockerfiles/fedora.docker
+++ b/tests/docker/dockerfiles/fedora.docker
@@ -162,4 +162,4 @@ ARG UID
RUN if [ "${USER}" ]; then \
id ${USER} 2>/dev/null || useradd -u ${UID} -U ${USER}; fi
-ENV ENABLE_RUST 1
+ENV ENABLE_RUST=1
diff --git a/tests/docker/dockerfiles/opensuse-leap.docker b/tests/docker/dockerfiles/opensuse-leap.docker
index 4b126b7e7de..fc363c647cd 100644
--- a/tests/docker/dockerfiles/opensuse-leap.docker
+++ b/tests/docker/dockerfiles/opensuse-leap.docker
@@ -149,4 +149,4 @@ ARG UID
RUN if [ "${USER}" ]; then \
id ${USER} 2>/dev/null || useradd -u ${UID} -U ${USER}; fi
-ENV ENABLE_RUST 1
+ENV ENABLE_RUST=1
diff --git a/scripts/git.orderfile b/scripts/git.orderfile
index 8edac0380ba..4b693c9deec 100644
--- a/scripts/git.orderfile
+++ b/scripts/git.orderfile
@@ -39,3 +39,7 @@ qga/*.json
# code
*.c
*.c.inc
+
+# Generated Dockerfiles
+tests/lcitool/refresh
+tests/docker/dockerfiles/*
--
2.53.0
^ permalink raw reply related [flat|nested] 35+ messages in thread
* [PULL 03/33] buildsys: Remove MIPS cross containers
2026-05-20 19:23 [PULL 00/33] MIPS patches for 2026-05-20 Philippe Mathieu-Daudé
2026-05-20 19:23 ` [PULL 01/33] docker: Remove LegacyKeyValueFormat warnings in non-generated files Philippe Mathieu-Daudé
2026-05-20 19:23 ` [PULL 02/33] docker: Remove LegacyKeyValueFormat warnings in generated files Philippe Mathieu-Daudé
@ 2026-05-20 19:23 ` Philippe Mathieu-Daudé
2026-05-20 19:23 ` [PULL 04/33] buildsys: Remove support for MIPS hosts Philippe Mathieu-Daudé
` (30 subsequent siblings)
33 siblings, 0 replies; 35+ messages in thread
From: Philippe Mathieu-Daudé @ 2026-05-20 19:23 UTC (permalink / raw)
To: qemu-devel
As mentioned in commit 269ffaabc84 ("buildsys: Remove support
for 32-bit MIPS hosts"), Debian 13 "Trixie" removed support for
MIPS.
Signed-off-by: Philippe Mathieu-Daudé <philmd@linaro.org>
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
Message-Id: <20260511135312.38705-2-philmd@linaro.org>
---
configure | 1 -
tests/lcitool/refresh | 12 --
.../dockerfiles/debian-mips64el-cross.docker | 186 ------------------
.../dockerfiles/debian-mipsel-cross.docker | 186 ------------------
.gitlab-ci.d/container-cross.yml | 6 -
.gitlab-ci.d/containers.yml | 1 -
.gitlab-ci.d/crossbuilds.yml | 22 ---
tests/docker/Makefile.include | 1 -
8 files changed, 415 deletions(-)
delete mode 100644 tests/docker/dockerfiles/debian-mips64el-cross.docker
delete mode 100644 tests/docker/dockerfiles/debian-mipsel-cross.docker
diff --git a/configure b/configure
index eea90306728..b6dd797de5b 100755
--- a/configure
+++ b/configure
@@ -1525,7 +1525,6 @@ probe_target_compiler() {
aarch64_be:aarch64 | \
armeb:arm | \
i386:x86_64 | \
- mips*:mips64 | \
ppc*:ppc64 | \
sparc:sparc64 | \
"$cpu:$cpu")
diff --git a/tests/lcitool/refresh b/tests/lcitool/refresh
index a736f7f0ae6..365435b0d70 100755
--- a/tests/lcitool/refresh
+++ b/tests/lcitool/refresh
@@ -265,18 +265,6 @@ try:
trailer=cross_build("i686-linux-gnu-",
"i386-softmmu,i386-linux-user"))
- # mips no longer supported in debian-13
- # https://www.debian.org/releases/trixie/release-notes/issues.html#mips-architectures-removed
- generate_dockerfile("debian-mips64el-cross", "debian-12",
- cross="mips64el",
- trailer=cross_build("mips64el-linux-gnuabi64-",
- "mips64el-softmmu,mips64el-linux-user"))
-
- generate_dockerfile("debian-mipsel-cross", "debian-12",
- cross="mipsel",
- trailer=cross_build("mipsel-linux-gnu-",
- "mipsel-softmmu,mipsel-linux-user"))
-
generate_dockerfile("debian-ppc64el-cross", "debian-13",
cross="ppc64le",
trailer=cross_build("powerpc64le-linux-gnu-",
diff --git a/tests/docker/dockerfiles/debian-mips64el-cross.docker b/tests/docker/dockerfiles/debian-mips64el-cross.docker
deleted file mode 100644
index fc83fc0c00b..00000000000
--- a/tests/docker/dockerfiles/debian-mips64el-cross.docker
+++ /dev/null
@@ -1,186 +0,0 @@
-# THIS FILE WAS AUTO-GENERATED
-#
-# $ lcitool dockerfile --layers all --cross-arch mips64el debian-12 qemu
-#
-# https://gitlab.com/libvirt/libvirt-ci
-
-FROM docker.io/library/debian:12-slim
-
-RUN export DEBIAN_FRONTEND=noninteractive && \
- apt-get update && \
- apt-get install -y eatmydata && \
- eatmydata apt-get dist-upgrade -y && \
- eatmydata apt-get install --no-install-recommends -y \
- bash \
- bc \
- bindgen \
- bison \
- bsdextrautils \
- bzip2 \
- ca-certificates \
- ccache \
- coreutils \
- dbus \
- debianutils \
- diffutils \
- exuberant-ctags \
- findutils \
- flex \
- gcc \
- gcovr \
- gettext \
- git \
- hostname \
- libclang-rt-dev \
- libglib2.0-dev \
- llvm \
- locales \
- make \
- mtools \
- ninja-build \
- openssh-client \
- pkgconf \
- python3 \
- python3-numpy \
- python3-opencv \
- python3-pillow \
- python3-pip \
- python3-setuptools \
- python3-sphinx \
- python3-sphinx-rtd-theme \
- python3-venv \
- python3-wheel \
- python3-yaml \
- rpm2cpio \
- rustc-web \
- sed \
- socat \
- sparse \
- swtpm \
- tar \
- tesseract-ocr \
- tesseract-ocr-eng \
- vulkan-tools \
- xorriso \
- zstd && \
- eatmydata apt-get autoremove -y && \
- eatmydata apt-get autoclean -y && \
- sed -Ei 's,^# (en_US\.UTF-8 .*)$,\1,' /etc/locale.gen && \
- dpkg-reconfigure locales && \
- rm -f /usr/lib*/python3*/EXTERNALLY-MANAGED
-
-RUN /usr/bin/pip3 install meson==1.8.1
-
-ENV CCACHE_WRAPPERSDIR="/usr/libexec/ccache-wrappers"
-ENV LANG="en_US.UTF-8"
-ENV MAKE="/usr/bin/make"
-ENV NINJA="/usr/bin/ninja"
-ENV PYTHON="/usr/bin/python3"
-
-RUN export DEBIAN_FRONTEND=noninteractive && \
- dpkg --add-architecture mips64el && \
- eatmydata apt-get update && \
- eatmydata apt-get dist-upgrade -y && \
- eatmydata apt-get install --no-install-recommends -y dpkg-dev && \
- eatmydata apt-get install --no-install-recommends -y \
- gcc-mips64el-linux-gnuabi64 \
- libaio-dev:mips64el \
- libasound2-dev:mips64el \
- libattr1-dev:mips64el \
- libbpf-dev:mips64el \
- libbrlapi-dev:mips64el \
- libbz2-dev:mips64el \
- libc6-dev:mips64el \
- libcacard-dev:mips64el \
- libcap-ng-dev:mips64el \
- libcapstone-dev:mips64el \
- libcbor-dev:mips64el \
- libcmocka-dev:mips64el \
- libcurl4-gnutls-dev:mips64el \
- libdaxctl-dev:mips64el \
- libdrm-dev:mips64el \
- libepoxy-dev:mips64el \
- libfdt-dev:mips64el \
- libffi-dev:mips64el \
- libfuse3-dev:mips64el \
- libgbm-dev:mips64el \
- libgcrypt20-dev:mips64el \
- libglib2.0-dev:mips64el \
- libgnutls28-dev:mips64el \
- libgtk-3-dev:mips64el \
- libgtk-vnc-2.0-dev:mips64el \
- libibverbs-dev:mips64el \
- libiscsi-dev:mips64el \
- libjemalloc-dev:mips64el \
- libjpeg62-turbo-dev:mips64el \
- libjson-c-dev:mips64el \
- liblttng-ust-dev:mips64el \
- liblzo2-dev:mips64el \
- libncursesw5-dev:mips64el \
- libnfs-dev:mips64el \
- libnuma-dev:mips64el \
- libpam0g-dev:mips64el \
- libpcre2-dev:mips64el \
- libpipewire-0.3-dev:mips64el \
- libpixman-1-dev:mips64el \
- libpng-dev:mips64el \
- libpulse-dev:mips64el \
- librbd-dev:mips64el \
- librdmacm-dev:mips64el \
- libsasl2-dev:mips64el \
- libsdl2-dev:mips64el \
- libsdl2-image-dev:mips64el \
- libseccomp-dev:mips64el \
- libselinux1-dev:mips64el \
- libslirp-dev:mips64el \
- libsnappy-dev:mips64el \
- libsndio-dev:mips64el \
- libspice-protocol-dev:mips64el \
- libspice-server-dev:mips64el \
- libssh-dev:mips64el \
- libstd-rust-dev:mips64el \
- libsystemd-dev:mips64el \
- libtasn1-6-dev:mips64el \
- libudev-dev:mips64el \
- liburing-dev:mips64el \
- libusb-1.0-0-dev:mips64el \
- libusbredirhost-dev:mips64el \
- libvdeplug-dev:mips64el \
- libvirglrenderer-dev:mips64el \
- libvte-2.91-dev:mips64el \
- libxdp-dev:mips64el \
- libzstd-dev:mips64el \
- nettle-dev:mips64el \
- systemtap-sdt-dev:mips64el \
- zlib1g-dev:mips64el && \
- eatmydata apt-get autoremove -y && \
- eatmydata apt-get autoclean -y && \
- mkdir -p /usr/local/share/meson/cross && \
- printf "[binaries]\n\
-c = '/usr/bin/mips64el-linux-gnuabi64-gcc'\n\
-ar = '/usr/bin/mips64el-linux-gnuabi64-gcc-ar'\n\
-strip = '/usr/bin/mips64el-linux-gnuabi64-strip'\n\
-pkgconfig = '/usr/bin/mips64el-linux-gnuabi64-pkg-config'\n\
-\n\
-[host_machine]\n\
-system = 'linux'\n\
-cpu_family = 'mips64'\n\
-cpu = 'mips64el'\n\
-endian = 'little'\n" > /usr/local/share/meson/cross/mips64el-linux-gnuabi64 && \
- dpkg-query --showformat '${Package}_${Version}_${Architecture}\n' --show > /packages.txt && \
- mkdir -p /usr/libexec/ccache-wrappers && \
- ln -s /usr/bin/ccache /usr/libexec/ccache-wrappers/mips64el-linux-gnuabi64-cc && \
- ln -s /usr/bin/ccache /usr/libexec/ccache-wrappers/mips64el-linux-gnuabi64-gcc
-
-ENV ABI="mips64el-linux-gnuabi64"
-ENV MESON_OPTS="--cross-file=mips64el-linux-gnuabi64"
-ENV RUST_TARGET="mips64el-unknown-linux-gnuabi64"
-ENV QEMU_CONFIGURE_OPTS=--cross-prefix=mips64el-linux-gnuabi64-
-ENV DEF_TARGET_LIST=mips64el-softmmu,mips64el-linux-user
-# As a final step configure the user (if env is defined)
-ARG USER
-ARG UID
-RUN if [ "${USER}" ]; then \
- id ${USER} 2>/dev/null || useradd -u ${UID} -U ${USER}; fi
-
-ENV ENABLE_RUST=1
diff --git a/tests/docker/dockerfiles/debian-mipsel-cross.docker b/tests/docker/dockerfiles/debian-mipsel-cross.docker
deleted file mode 100644
index 5f105b1d687..00000000000
--- a/tests/docker/dockerfiles/debian-mipsel-cross.docker
+++ /dev/null
@@ -1,186 +0,0 @@
-# THIS FILE WAS AUTO-GENERATED
-#
-# $ lcitool dockerfile --layers all --cross-arch mipsel debian-12 qemu
-#
-# https://gitlab.com/libvirt/libvirt-ci
-
-FROM docker.io/library/debian:12-slim
-
-RUN export DEBIAN_FRONTEND=noninteractive && \
- apt-get update && \
- apt-get install -y eatmydata && \
- eatmydata apt-get dist-upgrade -y && \
- eatmydata apt-get install --no-install-recommends -y \
- bash \
- bc \
- bindgen \
- bison \
- bsdextrautils \
- bzip2 \
- ca-certificates \
- ccache \
- coreutils \
- dbus \
- debianutils \
- diffutils \
- exuberant-ctags \
- findutils \
- flex \
- gcc \
- gcovr \
- gettext \
- git \
- hostname \
- libclang-rt-dev \
- libglib2.0-dev \
- llvm \
- locales \
- make \
- mtools \
- ninja-build \
- openssh-client \
- pkgconf \
- python3 \
- python3-numpy \
- python3-opencv \
- python3-pillow \
- python3-pip \
- python3-setuptools \
- python3-sphinx \
- python3-sphinx-rtd-theme \
- python3-venv \
- python3-wheel \
- python3-yaml \
- rpm2cpio \
- rustc-web \
- sed \
- socat \
- sparse \
- swtpm \
- tar \
- tesseract-ocr \
- tesseract-ocr-eng \
- vulkan-tools \
- xorriso \
- zstd && \
- eatmydata apt-get autoremove -y && \
- eatmydata apt-get autoclean -y && \
- sed -Ei 's,^# (en_US\.UTF-8 .*)$,\1,' /etc/locale.gen && \
- dpkg-reconfigure locales && \
- rm -f /usr/lib*/python3*/EXTERNALLY-MANAGED
-
-RUN /usr/bin/pip3 install meson==1.8.1
-
-ENV CCACHE_WRAPPERSDIR="/usr/libexec/ccache-wrappers"
-ENV LANG="en_US.UTF-8"
-ENV MAKE="/usr/bin/make"
-ENV NINJA="/usr/bin/ninja"
-ENV PYTHON="/usr/bin/python3"
-
-RUN export DEBIAN_FRONTEND=noninteractive && \
- dpkg --add-architecture mipsel && \
- eatmydata apt-get update && \
- eatmydata apt-get dist-upgrade -y && \
- eatmydata apt-get install --no-install-recommends -y dpkg-dev && \
- eatmydata apt-get install --no-install-recommends -y \
- gcc-mipsel-linux-gnu \
- libaio-dev:mipsel \
- libasound2-dev:mipsel \
- libattr1-dev:mipsel \
- libbpf-dev:mipsel \
- libbrlapi-dev:mipsel \
- libbz2-dev:mipsel \
- libc6-dev:mipsel \
- libcacard-dev:mipsel \
- libcap-ng-dev:mipsel \
- libcapstone-dev:mipsel \
- libcbor-dev:mipsel \
- libcmocka-dev:mipsel \
- libcurl4-gnutls-dev:mipsel \
- libdaxctl-dev:mipsel \
- libdrm-dev:mipsel \
- libepoxy-dev:mipsel \
- libfdt-dev:mipsel \
- libffi-dev:mipsel \
- libfuse3-dev:mipsel \
- libgbm-dev:mipsel \
- libgcrypt20-dev:mipsel \
- libglib2.0-dev:mipsel \
- libgnutls28-dev:mipsel \
- libgtk-3-dev:mipsel \
- libgtk-vnc-2.0-dev:mipsel \
- libibverbs-dev:mipsel \
- libiscsi-dev:mipsel \
- libjemalloc-dev:mipsel \
- libjpeg62-turbo-dev:mipsel \
- libjson-c-dev:mipsel \
- liblttng-ust-dev:mipsel \
- liblzo2-dev:mipsel \
- libncursesw5-dev:mipsel \
- libnfs-dev:mipsel \
- libnuma-dev:mipsel \
- libpam0g-dev:mipsel \
- libpcre2-dev:mipsel \
- libpipewire-0.3-dev:mipsel \
- libpixman-1-dev:mipsel \
- libpng-dev:mipsel \
- libpulse-dev:mipsel \
- librbd-dev:mipsel \
- librdmacm-dev:mipsel \
- libsasl2-dev:mipsel \
- libsdl2-dev:mipsel \
- libsdl2-image-dev:mipsel \
- libseccomp-dev:mipsel \
- libselinux1-dev:mipsel \
- libslirp-dev:mipsel \
- libsnappy-dev:mipsel \
- libsndio-dev:mipsel \
- libspice-protocol-dev:mipsel \
- libspice-server-dev:mipsel \
- libssh-dev:mipsel \
- libstd-rust-dev:mipsel \
- libsystemd-dev:mipsel \
- libtasn1-6-dev:mipsel \
- libudev-dev:mipsel \
- liburing-dev:mipsel \
- libusb-1.0-0-dev:mipsel \
- libusbredirhost-dev:mipsel \
- libvdeplug-dev:mipsel \
- libvirglrenderer-dev:mipsel \
- libvte-2.91-dev:mipsel \
- libxdp-dev:mipsel \
- libzstd-dev:mipsel \
- nettle-dev:mipsel \
- systemtap-sdt-dev:mipsel \
- zlib1g-dev:mipsel && \
- eatmydata apt-get autoremove -y && \
- eatmydata apt-get autoclean -y && \
- mkdir -p /usr/local/share/meson/cross && \
- printf "[binaries]\n\
-c = '/usr/bin/mipsel-linux-gnu-gcc'\n\
-ar = '/usr/bin/mipsel-linux-gnu-gcc-ar'\n\
-strip = '/usr/bin/mipsel-linux-gnu-strip'\n\
-pkgconfig = '/usr/bin/mipsel-linux-gnu-pkg-config'\n\
-\n\
-[host_machine]\n\
-system = 'linux'\n\
-cpu_family = 'mips'\n\
-cpu = 'mipsel'\n\
-endian = 'little'\n" > /usr/local/share/meson/cross/mipsel-linux-gnu && \
- dpkg-query --showformat '${Package}_${Version}_${Architecture}\n' --show > /packages.txt && \
- mkdir -p /usr/libexec/ccache-wrappers && \
- ln -s /usr/bin/ccache /usr/libexec/ccache-wrappers/mipsel-linux-gnu-cc && \
- ln -s /usr/bin/ccache /usr/libexec/ccache-wrappers/mipsel-linux-gnu-gcc
-
-ENV ABI="mipsel-linux-gnu"
-ENV MESON_OPTS="--cross-file=mipsel-linux-gnu"
-ENV RUST_TARGET="mipsel-unknown-linux-gnu"
-ENV QEMU_CONFIGURE_OPTS=--cross-prefix=mipsel-linux-gnu-
-ENV DEF_TARGET_LIST=mipsel-softmmu,mipsel-linux-user
-# As a final step configure the user (if env is defined)
-ARG USER
-ARG UID
-RUN if [ "${USER}" ]; then \
- id ${USER} 2>/dev/null || useradd -u ${UID} -U ${USER}; fi
-
-ENV ENABLE_RUST=1
diff --git a/.gitlab-ci.d/container-cross.yml b/.gitlab-ci.d/container-cross.yml
index 92a7f1c1b47..ab06083d754 100644
--- a/.gitlab-ci.d/container-cross.yml
+++ b/.gitlab-ci.d/container-cross.yml
@@ -28,12 +28,6 @@ loongarch-debian-cross-container:
variables:
NAME: debian-loongarch-cross
-mips64el-debian-cross-container:
- extends: .container_job_template
- stage: containers
- variables:
- NAME: debian-mips64el-cross
-
ppc64el-debian-cross-container:
extends: .container_job_template
stage: containers
diff --git a/.gitlab-ci.d/containers.yml b/.gitlab-ci.d/containers.yml
index c8b8e44ad86..515e7382f26 100644
--- a/.gitlab-ci.d/containers.yml
+++ b/.gitlab-ci.d/containers.yml
@@ -48,7 +48,6 @@ weekly-container-builds:
- arm64-debian-cross-container
- hexagon-cross-container
- loongarch-debian-cross-container
- - mips64el-debian-cross-container
- ppc64el-debian-cross-container
- riscv64-debian-cross-container
- s390x-debian-cross-container
diff --git a/.gitlab-ci.d/crossbuilds.yml b/.gitlab-ci.d/crossbuilds.yml
index cf977dfefb1..eaeeb533cee 100644
--- a/.gitlab-ci.d/crossbuilds.yml
+++ b/.gitlab-ci.d/crossbuilds.yml
@@ -23,20 +23,6 @@ cross-arm64-kvm-only:
IMAGE: debian-arm64-cross
EXTRA_CONFIGURE_OPTS: --disable-tcg --without-default-features
-cross-mips64el-system:
- extends: .cross_system_build_job
- needs:
- - job: mips64el-debian-cross-container
- variables:
- IMAGE: debian-mips64el-cross
-
-cross-mips64el-user:
- extends: .cross_user_build_job
- needs:
- - job: mips64el-debian-cross-container
- variables:
- IMAGE: debian-mips64el-cross
-
cross-ppc64el-system:
extends: .cross_system_build_job
needs:
@@ -95,14 +81,6 @@ cross-s390x-kvm-only:
IMAGE: debian-s390x-cross
EXTRA_CONFIGURE_OPTS: --disable-tcg --enable-trace-backends=ftrace
-cross-mips64el-kvm-only:
- extends: .cross_accel_build_job
- needs:
- - job: mips64el-debian-cross-container
- variables:
- IMAGE: debian-mips64el-cross
- EXTRA_CONFIGURE_OPTS: --disable-tcg --target-list=mips64el-softmmu
-
cross-win64-system:
extends: .cross_system_build_job
needs:
diff --git a/tests/docker/Makefile.include b/tests/docker/Makefile.include
index df14538c0f5..4725c39807b 100644
--- a/tests/docker/Makefile.include
+++ b/tests/docker/Makefile.include
@@ -94,7 +94,6 @@ endif
# For non-x86 hosts not all cross-compilers have been packaged
ifneq ($(HOST_ARCH),x86_64)
-DOCKER_PARTIAL_IMAGES += debian-mipsel-cross debian-mips64el-cross
DOCKER_PARTIAL_IMAGES += debian-ppc64el-cross
DOCKER_PARTIAL_IMAGES += debian-s390x-cross
DOCKER_PARTIAL_IMAGES += fedora
--
2.53.0
^ permalink raw reply related [flat|nested] 35+ messages in thread
* [PULL 04/33] buildsys: Remove support for MIPS hosts
2026-05-20 19:23 [PULL 00/33] MIPS patches for 2026-05-20 Philippe Mathieu-Daudé
` (2 preceding siblings ...)
2026-05-20 19:23 ` [PULL 03/33] buildsys: Remove MIPS cross containers Philippe Mathieu-Daudé
@ 2026-05-20 19:23 ` Philippe Mathieu-Daudé
2026-05-20 19:23 ` [PULL 05/33] hw/mips: Include missing 'cpu.h' header Philippe Mathieu-Daudé
` (29 subsequent siblings)
33 siblings, 0 replies; 35+ messages in thread
From: Philippe Mathieu-Daudé @ 2026-05-20 19:23 UTC (permalink / raw)
To: qemu-devel
MIPS host support is deprecated since commit 269ffaabc84
("buildsys: Remove support for 32-bit MIPS hosts"). Time
to remove.
Signed-off-by: Philippe Mathieu-Daudé <philmd@linaro.org>
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
Message-Id: <20260511135312.38705-3-philmd@linaro.org>
---
docs/about/deprecated.rst | 8 --------
docs/about/removed-features.rst | 6 ++++++
configure | 19 -------------------
meson.build | 10 +---------
include/qemu/timer.h | 30 ------------------------------
util/cacheflush.c | 16 ----------------
6 files changed, 7 insertions(+), 82 deletions(-)
diff --git a/docs/about/deprecated.rst b/docs/about/deprecated.rst
index e64328c5b2b..95bf7613295 100644
--- a/docs/about/deprecated.rst
+++ b/docs/about/deprecated.rst
@@ -177,14 +177,6 @@ The ``info capture`` command is deprecated and will be removed in a future relea
Host Architectures
------------------
-MIPS (since 10.2)
-'''''''''''''''''
-
-MIPS is not supported by Debian 13 ("Trixie") and newer, making it hard to
-maintain our cross-compilation CI tests of the architecture. As we no longer
-have CI coverage support may bitrot away before the deprecation process
-completes.
-
TCG Plugin support not enabled by default with TCI (since 9.2)
''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
diff --git a/docs/about/removed-features.rst b/docs/about/removed-features.rst
index 1ee4ab07944..2021e85f56a 100644
--- a/docs/about/removed-features.rst
+++ b/docs/about/removed-features.rst
@@ -938,6 +938,12 @@ From 10.0, QEMU has disabled configuration of 64-bit guests on 32-bit hosts.
Debian 12 "Bookworm" removed support for 32-bit MIPS, making it hard to
maintain our cross-compilation CI tests of the architecture.
+64-bit MIPS (removed in 11.1)
+'''''''''''''''''''''''''''''
+
+Debian 13 "Trixie" removed support for MIPS, making it hard to maintain our
+cross-compilation CI tests of the architecture.
+
32-bit PPC (removed in 10.2)
''''''''''''''''''''''''''''
diff --git a/configure b/configure
index b6dd797de5b..e138d83bc9f 100755
--- a/configure
+++ b/configure
@@ -399,8 +399,6 @@ elif check_define _ARCH_PPC64 ; then
else
cpu="ppc64"
fi
-elif check_define __mips64 ; then
- cpu="mips64"
elif check_define __s390__ ; then
if check_define __s390x__ ; then
cpu="s390x"
@@ -446,12 +444,6 @@ case "$cpu" in
linux_arch=loongarch
;;
- mips64*|mipsisa64*)
- cpu=mips64
- host_arch=mips64
- linux_arch=mips
- ;;
-
ppc64)
host_arch=ppc64
linux_arch=powerpc
@@ -1244,11 +1236,6 @@ EOF
rust_osvariant=${rust_osvariant}eabi
fi
;;
-
- mips64)
- # e.g. mips64-unknown-linux-gnuabi64
- rust_osvariant=${rust_osvariant}abi64
- ;;
esac
;;
@@ -1281,12 +1268,6 @@ EOF
test "$rust_arch" = arm && test "$rust_os" != linux && rust_arch=armv7
;;
- mips)
- # preserve ISA version (mipsisa64r6 etc.) and include endianness
- rust_arch=${raw_cpu%el}
- test "$bigendian" = no && rust_arch=${rust_arch}el
- ;;
-
riscv64)
# e.g. riscv64gc-unknown-linux-gnu, but riscv64-linux-android
test "$android" = no && rust_arch=${rust_arch}gc
diff --git a/meson.build b/meson.build
index 70613bf4afc..fe5211b2122 100644
--- a/meson.build
+++ b/meson.build
@@ -55,7 +55,7 @@ qapi_trace_events = []
bsd_oses = ['gnu/kfreebsd', 'freebsd', 'netbsd', 'openbsd', 'dragonfly', 'darwin']
supported_oses = ['windows', 'freebsd', 'netbsd', 'openbsd', 'darwin', 'sunos', 'linux', 'emscripten']
supported_cpus = ['ppc64', 's390x', 'riscv64', 'x86_64',
- 'aarch64', 'loongarch64', 'mips64', 'sparc64', 'wasm64']
+ 'aarch64', 'loongarch64', 'sparc64', 'wasm64']
cpu = host_machine.cpu_family()
@@ -5013,14 +5013,6 @@ if host_arch == 'unknown'
message('configure has succeeded and you can continue to build, but')
message('QEMU will use a slow interpreter to emulate the target CPU.')
endif
-elif host_arch == 'mips'
- message()
- warning('DEPRECATED HOST CPU')
- message()
- message('Support for CPU host architecture ' + cpu + ' is going to be')
- message('dropped as soon as the QEMU project stops supporting Debian 12')
- message('("Bookworm"). Going forward, the QEMU project will not guarantee')
- message('that QEMU will compile or work on this host CPU.')
endif
if not supported_oses.contains(host_os)
diff --git a/include/qemu/timer.h b/include/qemu/timer.h
index b931181f53d..ec03635dd34 100644
--- a/include/qemu/timer.h
+++ b/include/qemu/timer.h
@@ -922,36 +922,6 @@ static inline int64_t cpu_get_host_ticks (void)
#endif
}
-#elif defined(__mips__) && \
- ((defined(__mips_isa_rev) && __mips_isa_rev >= 2) || defined(__linux__))
-/*
- * binutils wants to use rdhwr only on mips32r2
- * but as linux kernel emulate it, it's fine
- * to use it.
- *
- */
-#define MIPS_RDHWR(rd, value) { \
- __asm__ __volatile__ (".set push\n\t" \
- ".set mips32r2\n\t" \
- "rdhwr %0, "rd"\n\t" \
- ".set pop" \
- : "=r" (value)); \
- }
-
-static inline int64_t cpu_get_host_ticks(void)
-{
- /* On kernels >= 2.6.25 rdhwr <reg>, $2 and $3 are emulated */
- uint32_t count;
- static uint32_t cyc_per_count = 0;
-
- if (!cyc_per_count) {
- MIPS_RDHWR("$3", cyc_per_count);
- }
-
- MIPS_RDHWR("$2", count);
- return (int64_t)(count * cyc_per_count);
-}
-
#elif defined(__alpha__)
static inline int64_t cpu_get_host_ticks(void)
diff --git a/util/cacheflush.c b/util/cacheflush.c
index c043c5f881a..247c4ce2980 100644
--- a/util/cacheflush.c
+++ b/util/cacheflush.c
@@ -301,22 +301,6 @@ void flush_idcache_range(uintptr_t rx, uintptr_t rw, size_t len)
}
#endif /* CONFIG_DARWIN */
-#elif defined(__mips__)
-
-#ifdef __OpenBSD__
-#include <machine/sysarch.h>
-#else
-#include <sys/cachectl.h>
-#endif
-
-void flush_idcache_range(uintptr_t rx, uintptr_t rw, size_t len)
-{
- if (rx != rw) {
- cacheflush((void *)rw, len, DCACHE);
- }
- cacheflush((void *)rx, len, ICACHE);
-}
-
#elif defined(__powerpc__)
void flush_idcache_range(uintptr_t rx, uintptr_t rw, size_t len)
--
2.53.0
^ permalink raw reply related [flat|nested] 35+ messages in thread
* [PULL 05/33] hw/mips: Include missing 'cpu.h' header
2026-05-20 19:23 [PULL 00/33] MIPS patches for 2026-05-20 Philippe Mathieu-Daudé
` (3 preceding siblings ...)
2026-05-20 19:23 ` [PULL 04/33] buildsys: Remove support for MIPS hosts Philippe Mathieu-Daudé
@ 2026-05-20 19:23 ` Philippe Mathieu-Daudé
2026-05-20 19:23 ` [PULL 06/33] buildsys: Remove MIPS KVM Philippe Mathieu-Daudé
` (28 subsequent siblings)
33 siblings, 0 replies; 35+ messages in thread
From: Philippe Mathieu-Daudé @ 2026-05-20 19:23 UTC (permalink / raw)
To: qemu-devel
"target/mips/cpu.h" is indirectly pulled in via the "system/kvm.h"
header, which next commit will remove. Explicitly include the "cpu.h"
header, otherwise we'd get:
hw/mips/mips_int.c:29:5: error: use of undeclared identifier 'MIPSCPU'
29 | MIPSCPU *cpu = opaque;
| ^
hw/mips/mips_int.c:30:5: error: use of undeclared identifier 'CPUMIPSState'
30 | CPUMIPSState *env = &cpu->env;
| ^
hw/mips/loongson3_virt.c:156:39: error: unknown type name 'MIPSCPU'
156 | static uint64_t get_cpu_freq_hz(const MIPSCPU *cpu)
| ^
Signed-off-by: Philippe Mathieu-Daudé <philmd@linaro.org>
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
Message-Id: <20260511135312.38705-4-philmd@linaro.org>
---
hw/mips/loongson3_virt.c | 1 +
hw/mips/mips_int.c | 1 +
2 files changed, 2 insertions(+)
diff --git a/hw/mips/loongson3_virt.c b/hw/mips/loongson3_virt.c
index cd94e9f5f77..c29cae86872 100644
--- a/hw/mips/loongson3_virt.c
+++ b/hw/mips/loongson3_virt.c
@@ -51,6 +51,7 @@
#include "system/runstate.h"
#include "system/system.h"
#include "qemu/error-report.h"
+#include "target/mips/cpu.h"
#define PM_CNTL_MODE 0x10
diff --git a/hw/mips/mips_int.c b/hw/mips/mips_int.c
index 2b740afc4d8..fa9c78e74de 100644
--- a/hw/mips/mips_int.c
+++ b/hw/mips/mips_int.c
@@ -25,6 +25,7 @@
#include "hw/core/irq.h"
#include "system/kvm.h"
#include "kvm_mips.h"
+#include "target/mips/cpu.h"
static void cpu_mips_irq_request(void *opaque, int irq, int level)
{
--
2.53.0
^ permalink raw reply related [flat|nested] 35+ messages in thread
* [PULL 06/33] buildsys: Remove MIPS KVM
2026-05-20 19:23 [PULL 00/33] MIPS patches for 2026-05-20 Philippe Mathieu-Daudé
` (4 preceding siblings ...)
2026-05-20 19:23 ` [PULL 05/33] hw/mips: Include missing 'cpu.h' header Philippe Mathieu-Daudé
@ 2026-05-20 19:23 ` Philippe Mathieu-Daudé
2026-05-20 19:23 ` [PULL 07/33] buildsys: Remove MIPS TCG backend Philippe Mathieu-Daudé
` (27 subsequent siblings)
33 siblings, 0 replies; 35+ messages in thread
From: Philippe Mathieu-Daudé @ 2026-05-20 19:23 UTC (permalink / raw)
To: qemu-devel
We removed support for MIPS host. The KVM MIPS code
is now unreachable, remove it.
Signed-off-by: Philippe Mathieu-Daudé <philmd@linaro.org>
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
Message-Id: <20260511135312.38705-5-philmd@linaro.org>
---
MAINTAINERS | 6 -
docs/system/target-mips.rst | 2 -
meson.build | 2 -
target/mips/kvm_mips.h | 28 -
hw/intc/mips_gic.c | 11 +-
hw/mips/loongson3_virt.c | 66 +-
hw/mips/malta.c | 1 -
hw/mips/mips_int.c | 6 -
target/mips/cpu.c | 5 -
target/mips/kvm.c | 1283 --------------------------------
target/mips/system/cp0_timer.c | 12 +-
target/mips/system/physaddr.c | 1 -
target/mips/meson.build | 6 +-
13 files changed, 21 insertions(+), 1408 deletions(-)
delete mode 100644 target/mips/kvm_mips.h
delete mode 100644 target/mips/kvm.c
diff --git a/MAINTAINERS b/MAINTAINERS
index b75f3222f2f..bd7ea53f950 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -483,12 +483,6 @@ S: Supported
F: target/arm/kvm.c
F: tests/functional/aarch64/test_kvm.py
-MIPS KVM CPUs
-M: Huacai Chen <chenhuacai@kernel.org>
-S: Odd Fixes
-F: target/mips/kvm*
-F: target/mips/system/
-
PPC KVM CPUs
M: Nicholas Piggin <npiggin@gmail.com>
R: Harsh Prateek Bora <harshpb@linux.ibm.com>
diff --git a/docs/system/target-mips.rst b/docs/system/target-mips.rst
index 2a152e13380..aebad0c86e9 100644
--- a/docs/system/target-mips.rst
+++ b/docs/system/target-mips.rst
@@ -76,8 +76,6 @@ The Loongson-3 virtual platform emulation supports:
- GPEX and virtio as peripheral devices
-- Both KVM and TCG supported
-
.. include:: cpu-models-mips.rst.inc
.. _nanoMIPS-System-emulator:
diff --git a/meson.build b/meson.build
index fe5211b2122..eb074918193 100644
--- a/meson.build
+++ b/meson.build
@@ -282,8 +282,6 @@ elif cpu == 's390x'
kvm_targets = ['s390x-softmmu']
elif cpu == 'ppc64'
kvm_targets = ['ppc-softmmu', 'ppc64-softmmu']
-elif cpu == 'mips64'
- kvm_targets = ['mips-softmmu', 'mipsel-softmmu', 'mips64-softmmu', 'mips64el-softmmu']
elif cpu == 'riscv64'
kvm_targets = ['riscv64-softmmu']
elif cpu == 'loongarch64'
diff --git a/target/mips/kvm_mips.h b/target/mips/kvm_mips.h
deleted file mode 100644
index c711269d0af..00000000000
--- a/target/mips/kvm_mips.h
+++ /dev/null
@@ -1,28 +0,0 @@
-/*
- * This file is subject to the terms and conditions of the GNU General Public
- * License. See the file "COPYING" in the main directory of this archive
- * for more details.
- *
- * KVM/MIPS: MIPS specific KVM APIs
- *
- * Copyright (C) 2012-2014 Imagination Technologies Ltd.
- * Authors: Sanjay Lal <sanjayl@kymasys.com>
- */
-
-#ifndef KVM_MIPS_H
-#define KVM_MIPS_H
-
-#include "cpu.h"
-
-/**
- * kvm_mips_reset_vcpu:
- * @cpu: MIPSCPU
- *
- * Called at reset time to set kernel registers to their initial values.
- */
-void kvm_mips_reset_vcpu(MIPSCPU *cpu);
-
-int kvm_mips_set_interrupt(MIPSCPU *cpu, int irq, int level);
-int kvm_mips_set_ipi_interrupt(MIPSCPU *cpu, int irq, int level);
-
-#endif /* KVM_MIPS_H */
diff --git a/hw/intc/mips_gic.c b/hw/intc/mips_gic.c
index ad9363a4c7d..23478df4b46 100644
--- a/hw/intc/mips_gic.c
+++ b/hw/intc/mips_gic.c
@@ -15,9 +15,7 @@
#include "qapi/error.h"
#include "hw/core/sysbus.h"
#include "system/memory.h"
-#include "system/kvm.h"
#include "system/reset.h"
-#include "kvm_mips.h"
#include "hw/intc/mips_gic.h"
#include "hw/core/irq.h"
#include "hw/core/qdev-properties.h"
@@ -45,14 +43,7 @@ static void mips_gic_set_vp_irq(MIPSGICState *gic, int vp, int pin)
ored_level |= (gic->vps[vp].pend & GIC_VP_MASK_CMP_MSK) >>
GIC_VP_MASK_CMP_SHF;
}
- if (kvm_enabled()) {
- kvm_mips_set_ipi_interrupt(env_archcpu(gic->vps[vp].env),
- pin + GIC_CPU_PIN_OFFSET,
- ored_level);
- } else {
- qemu_set_irq(gic->vps[vp].env->irq[pin + GIC_CPU_PIN_OFFSET],
- ored_level);
- }
+ qemu_set_irq(gic->vps[vp].env->irq[pin + GIC_CPU_PIN_OFFSET], ored_level);
}
static void gic_update_pin_for_irq(MIPSGICState *gic, int n_IRQ)
diff --git a/hw/mips/loongson3_virt.c b/hw/mips/loongson3_virt.c
index c29cae86872..7de3fb09c17 100644
--- a/hw/mips/loongson3_virt.c
+++ b/hw/mips/loongson3_virt.c
@@ -45,7 +45,6 @@
#include "hw/pci-host/gpex.h"
#include "hw/usb/usb.h"
#include "net/net.h"
-#include "system/kvm.h"
#include "system/qtest.h"
#include "system/reset.h"
#include "system/runstate.h"
@@ -157,21 +156,6 @@ static const MemoryRegionOps loongson3_pm_ops = {
static uint64_t get_cpu_freq_hz(const MIPSCPU *cpu)
{
-#ifdef CONFIG_KVM
- int ret;
- uint64_t freq;
- struct kvm_one_reg freq_reg = {
- .id = KVM_REG_MIPS_COUNT_HZ,
- .addr = (uintptr_t)(&freq)
- };
-
- if (kvm_enabled()) {
- ret = kvm_vcpu_ioctl(CPU(cpu), KVM_GET_ONE_REG, &freq_reg);
- if (ret >= 0) {
- return freq * 2;
- }
- }
-#endif
return DEF_LOONGSON3_FREQ;
}
@@ -511,23 +495,13 @@ static void mips_loongson3_virt_init(MachineState *machine)
MemoryRegion *iomem = g_new(MemoryRegion, 1);
MemoryRegion *iocsr = g_new(MemoryRegion, 1);
- /* TODO: TCG will support all CPU types */
- if (!kvm_enabled()) {
- if (!machine->cpu_type) {
- machine->cpu_type = MIPS_CPU_TYPE_NAME("Loongson-3A1000");
- }
- if (!cpu_type_supports_isa(machine->cpu_type, INSN_LOONGSON3A)) {
- error_report("Loongson-3/TCG needs a Loongson-3 series cpu");
- exit(1);
- }
- } else {
- if (!machine->cpu_type) {
- machine->cpu_type = MIPS_CPU_TYPE_NAME("Loongson-3A4000");
- }
- if (!strstr(machine->cpu_type, "Loongson-3A4000")) {
- error_report("Loongson-3/KVM needs cpu type Loongson-3A4000");
- exit(1);
- }
+ /* TODO: Support all CPU types */
+ if (!machine->cpu_type) {
+ machine->cpu_type = MIPS_CPU_TYPE_NAME("Loongson-3A1000");
+ }
+ if (!cpu_type_supports_isa(machine->cpu_type, INSN_LOONGSON3A)) {
+ error_report("Loongson-3/TCG needs a Loongson-3 series cpu");
+ exit(1);
}
if (ram_size < 512 * MiB) {
@@ -545,16 +519,13 @@ static void mips_loongson3_virt_init(MachineState *machine)
memory_region_init(iocsr, OBJECT(machine), "loongson3.iocsr", UINT32_MAX);
- /* IPI controller is in kernel for KVM */
- if (!kvm_enabled()) {
- ipi = qdev_new(TYPE_LOONGSON_IPI);
- qdev_prop_set_uint32(ipi, "num-cpu", machine->smp.cpus);
- sysbus_realize_and_unref(SYS_BUS_DEVICE(ipi), &error_fatal);
- memory_region_add_subregion(iocsr, SMP_IPI_MAILBOX,
- sysbus_mmio_get_region(SYS_BUS_DEVICE(ipi), 0));
- memory_region_add_subregion(iocsr, MAIL_SEND_ADDR,
- sysbus_mmio_get_region(SYS_BUS_DEVICE(ipi), 1));
- }
+ ipi = qdev_new(TYPE_LOONGSON_IPI);
+ qdev_prop_set_uint32(ipi, "num-cpu", machine->smp.cpus);
+ sysbus_realize_and_unref(SYS_BUS_DEVICE(ipi), &error_fatal);
+ memory_region_add_subregion(iocsr, SMP_IPI_MAILBOX,
+ sysbus_mmio_get_region(SYS_BUS_DEVICE(ipi), 0));
+ memory_region_add_subregion(iocsr, MAIL_SEND_ADDR,
+ sysbus_mmio_get_region(SYS_BUS_DEVICE(ipi), 1));
liointc = qdev_new("loongson.liointc");
sysbus_realize_and_unref(SYS_BUS_DEVICE(liointc), &error_fatal);
@@ -575,6 +546,7 @@ static void mips_loongson3_virt_init(MachineState *machine)
int node = i / LOONGSON3_CORE_PER_NODE;
int core = i % LOONGSON3_CORE_PER_NODE;
int ip;
+ hwaddr ipi_base = ((hwaddr)node << 44) + virt_memmap[VIRT_IPI].base;
/* init CPUs */
cpu = mips_cpu_create_with_clock(machine->cpu_type, cpuclk, false);
@@ -584,12 +556,8 @@ static void mips_loongson3_virt_init(MachineState *machine)
cpu_mips_clock_init(cpu);
qemu_register_reset(i ? generic_cpu_reset : main_cpu_reset, cpu);
- if (!kvm_enabled()) {
- hwaddr base = ((hwaddr)node << 44) + virt_memmap[VIRT_IPI].base;
- base += core * 0x100;
- qdev_connect_gpio_out(ipi, i, cpu->env.irq[6]);
- sysbus_mmio_map(SYS_BUS_DEVICE(ipi), i + 2, base);
- }
+ qdev_connect_gpio_out(ipi, i, cpu->env.irq[6]);
+ sysbus_mmio_map(SYS_BUS_DEVICE(ipi), i + 2, ipi_base + core * 0x100);
if (ase_lcsr_available(&MIPS_CPU(cpu)->env)) {
MemoryRegion *core_iocsr = g_new(MemoryRegion, 1);
diff --git a/hw/mips/malta.c b/hw/mips/malta.c
index 845b8d339e8..38c71f66f2e 100644
--- a/hw/mips/malta.c
+++ b/hw/mips/malta.c
@@ -55,7 +55,6 @@
#include "system/system.h"
#include "qapi/error.h"
#include "qemu/error-report.h"
-#include "system/kvm.h"
#include "semihosting/semihost.h"
#include "hw/mips/cps.h"
#include "hw/core/qdev-clock.h"
diff --git a/hw/mips/mips_int.c b/hw/mips/mips_int.c
index fa9c78e74de..26e7dd6d5f5 100644
--- a/hw/mips/mips_int.c
+++ b/hw/mips/mips_int.c
@@ -23,8 +23,6 @@
#include "qemu/osdep.h"
#include "qemu/main-loop.h"
#include "hw/core/irq.h"
-#include "system/kvm.h"
-#include "kvm_mips.h"
#include "target/mips/cpu.h"
static void cpu_mips_irq_request(void *opaque, int irq, int level)
@@ -45,10 +43,6 @@ static void cpu_mips_irq_request(void *opaque, int irq, int level)
env->CP0_Cause &= ~(1 << (irq + CP0Ca_IP));
}
- if (kvm_enabled() && (irq == 2 || irq == 3)) {
- kvm_mips_set_interrupt(cpu, irq, level);
- }
-
if (env->CP0_Cause & CP0Ca_IP_mask) {
cpu_interrupt(cs, CPU_INTERRUPT_HARD);
} else {
diff --git a/target/mips/cpu.c b/target/mips/cpu.c
index 88bb59d506b..99d43613828 100644
--- a/target/mips/cpu.c
+++ b/target/mips/cpu.c
@@ -25,9 +25,7 @@
#include "qapi/error.h"
#include "cpu.h"
#include "internal.h"
-#include "kvm_mips.h"
#include "qemu/module.h"
-#include "system/kvm.h"
#include "system/qtest.h"
#include "hw/core/qdev-properties.h"
#include "hw/core/qdev-clock.h"
@@ -416,9 +414,6 @@ static void mips_cpu_reset_hold(Object *obj, ResetType type)
/* UHI interface can be used to obtain argc and argv */
env->active_tc.gpr[4] = -1;
}
- if (kvm_enabled()) {
- kvm_mips_reset_vcpu(cpu);
- }
#endif
}
diff --git a/target/mips/kvm.c b/target/mips/kvm.c
deleted file mode 100644
index a85e162409c..00000000000
--- a/target/mips/kvm.c
+++ /dev/null
@@ -1,1283 +0,0 @@
-/*
- * This file is subject to the terms and conditions of the GNU General Public
- * License. See the file "COPYING" in the main directory of this archive
- * for more details.
- *
- * KVM/MIPS: MIPS specific KVM APIs
- *
- * Copyright (C) 2012-2014 Imagination Technologies Ltd.
- * Authors: Sanjay Lal <sanjayl@kymasys.com>
-*/
-
-#include "qemu/osdep.h"
-#include <sys/ioctl.h>
-
-#include <linux/kvm.h>
-
-#include "cpu.h"
-#include "internal.h"
-#include "qemu/error-report.h"
-#include "qemu/main-loop.h"
-#include "system/kvm.h"
-#include "system/kvm_int.h"
-#include "system/runstate.h"
-#include "kvm_mips.h"
-#include "hw/core/boards.h"
-#include "fpu_helper.h"
-
-#define DEBUG_KVM 0
-
-#define DPRINTF(fmt, ...) \
- do { if (DEBUG_KVM) { fprintf(stderr, fmt, ## __VA_ARGS__); } } while (0)
-
-static int kvm_mips_fpu_cap;
-static int kvm_mips_msa_cap;
-
-const KVMCapabilityInfo kvm_arch_required_capabilities[] = {
- KVM_CAP_LAST_INFO
-};
-
-static void kvm_mips_update_state(void *opaque, bool running, RunState state);
-
-unsigned long kvm_arch_vcpu_id(CPUState *cs)
-{
- return cs->cpu_index;
-}
-
-int kvm_arch_init(MachineState *ms, KVMState *s)
-{
- /* MIPS has 128 signals */
- kvm_set_sigmask_len(s, 16);
-
- kvm_mips_fpu_cap = kvm_check_extension(s, KVM_CAP_MIPS_FPU);
- kvm_mips_msa_cap = kvm_check_extension(s, KVM_CAP_MIPS_MSA);
-
- DPRINTF("%s\n", __func__);
- return 0;
-}
-
-int kvm_arch_irqchip_create(KVMState *s)
-{
- return 0;
-}
-
-int kvm_arch_pre_create_vcpu(CPUState *cpu, Error **errp)
-{
- return 0;
-}
-
-int kvm_arch_init_vcpu(CPUState *cs)
-{
- CPUMIPSState *env = cpu_env(cs);
- int ret = 0;
-
- qemu_add_vm_change_state_handler(kvm_mips_update_state, cs);
-
- if (kvm_mips_fpu_cap && env->CP0_Config1 & (1 << CP0C1_FP)) {
- ret = kvm_vcpu_enable_cap(cs, KVM_CAP_MIPS_FPU, 0, 0);
- if (ret < 0) {
- /* mark unsupported so it gets disabled on reset */
- kvm_mips_fpu_cap = 0;
- ret = 0;
- }
- }
-
- if (kvm_mips_msa_cap && ase_msa_available(env)) {
- ret = kvm_vcpu_enable_cap(cs, KVM_CAP_MIPS_MSA, 0, 0);
- if (ret < 0) {
- /* mark unsupported so it gets disabled on reset */
- kvm_mips_msa_cap = 0;
- ret = 0;
- }
- }
-
- DPRINTF("%s\n", __func__);
- return ret;
-}
-
-int kvm_arch_destroy_vcpu(CPUState *cs)
-{
- return 0;
-}
-
-void kvm_mips_reset_vcpu(MIPSCPU *cpu)
-{
- CPUMIPSState *env = &cpu->env;
-
- if (!kvm_mips_fpu_cap && env->CP0_Config1 & (1 << CP0C1_FP)) {
- warn_report("KVM does not support FPU, disabling");
- env->CP0_Config1 &= ~(1 << CP0C1_FP);
- }
- if (!kvm_mips_msa_cap && ase_msa_available(env)) {
- warn_report("KVM does not support MSA, disabling");
- env->CP0_Config3 &= ~(1 << CP0C3_MSAP);
- }
-
- DPRINTF("%s\n", __func__);
-}
-
-int kvm_arch_insert_sw_breakpoint(CPUState *cs, struct kvm_sw_breakpoint *bp)
-{
- DPRINTF("%s\n", __func__);
- return 0;
-}
-
-int kvm_arch_remove_sw_breakpoint(CPUState *cs, struct kvm_sw_breakpoint *bp)
-{
- DPRINTF("%s\n", __func__);
- return 0;
-}
-
-static inline int cpu_mips_io_interrupts_pending(MIPSCPU *cpu)
-{
- CPUMIPSState *env = &cpu->env;
-
- return env->CP0_Cause & (0x1 << (2 + CP0Ca_IP));
-}
-
-
-void kvm_arch_pre_run(CPUState *cs, struct kvm_run *run)
-{
- MIPSCPU *cpu = MIPS_CPU(cs);
- int r;
- struct kvm_mips_interrupt intr;
-
- bql_lock();
-
- if (cpu_test_interrupt(cs, CPU_INTERRUPT_HARD) &&
- cpu_mips_io_interrupts_pending(cpu)) {
- intr.cpu = -1;
- intr.irq = 2;
- r = kvm_vcpu_ioctl(cs, KVM_INTERRUPT, &intr);
- if (r < 0) {
- error_report("%s: cpu %d: failed to inject IRQ %x",
- __func__, cs->cpu_index, intr.irq);
- }
- }
-
- bql_unlock();
-}
-
-MemTxAttrs kvm_arch_post_run(CPUState *cs, struct kvm_run *run)
-{
- return MEMTXATTRS_UNSPECIFIED;
-}
-
-int kvm_arch_process_async_events(CPUState *cs)
-{
- return cs->halted;
-}
-
-int kvm_arch_handle_exit(CPUState *cs, struct kvm_run *run)
-{
- int ret;
-
- DPRINTF("%s\n", __func__);
- switch (run->exit_reason) {
- default:
- error_report("%s: unknown exit reason %d",
- __func__, run->exit_reason);
- ret = -1;
- break;
- }
-
- return ret;
-}
-
-bool kvm_arch_stop_on_emulation_error(CPUState *cs)
-{
- DPRINTF("%s\n", __func__);
- return true;
-}
-
-void kvm_arch_init_irq_routing(KVMState *s)
-{
-}
-
-int kvm_mips_set_interrupt(MIPSCPU *cpu, int irq, int level)
-{
- CPUState *cs = CPU(cpu);
- struct kvm_mips_interrupt intr;
-
- assert(kvm_enabled());
-
- intr.cpu = -1;
-
- if (level) {
- intr.irq = irq;
- } else {
- intr.irq = -irq;
- }
-
- kvm_vcpu_ioctl(cs, KVM_INTERRUPT, &intr);
-
- return 0;
-}
-
-int kvm_mips_set_ipi_interrupt(MIPSCPU *cpu, int irq, int level)
-{
- CPUState *cs = current_cpu;
- CPUState *dest_cs = CPU(cpu);
- struct kvm_mips_interrupt intr;
-
- assert(kvm_enabled());
-
- intr.cpu = dest_cs->cpu_index;
-
- if (level) {
- intr.irq = irq;
- } else {
- intr.irq = -irq;
- }
-
- DPRINTF("%s: CPU %d, IRQ: %d\n", __func__, intr.cpu, intr.irq);
-
- kvm_vcpu_ioctl(cs, KVM_INTERRUPT, &intr);
-
- return 0;
-}
-
-#define MIPS_CP0_32(_R, _S) \
- (KVM_REG_MIPS_CP0 | KVM_REG_SIZE_U32 | (8 * (_R) + (_S)))
-
-#define MIPS_CP0_64(_R, _S) \
- (KVM_REG_MIPS_CP0 | KVM_REG_SIZE_U64 | (8 * (_R) + (_S)))
-
-#define KVM_REG_MIPS_CP0_INDEX MIPS_CP0_32(0, 0)
-#define KVM_REG_MIPS_CP0_RANDOM MIPS_CP0_32(1, 0)
-#define KVM_REG_MIPS_CP0_CONTEXT MIPS_CP0_64(4, 0)
-#define KVM_REG_MIPS_CP0_USERLOCAL MIPS_CP0_64(4, 2)
-#define KVM_REG_MIPS_CP0_PAGEMASK MIPS_CP0_32(5, 0)
-#define KVM_REG_MIPS_CP0_PAGEGRAIN MIPS_CP0_32(5, 1)
-#define KVM_REG_MIPS_CP0_PWBASE MIPS_CP0_64(5, 5)
-#define KVM_REG_MIPS_CP0_PWFIELD MIPS_CP0_64(5, 6)
-#define KVM_REG_MIPS_CP0_PWSIZE MIPS_CP0_64(5, 7)
-#define KVM_REG_MIPS_CP0_WIRED MIPS_CP0_32(6, 0)
-#define KVM_REG_MIPS_CP0_PWCTL MIPS_CP0_32(6, 6)
-#define KVM_REG_MIPS_CP0_HWRENA MIPS_CP0_32(7, 0)
-#define KVM_REG_MIPS_CP0_BADVADDR MIPS_CP0_64(8, 0)
-#define KVM_REG_MIPS_CP0_COUNT MIPS_CP0_32(9, 0)
-#define KVM_REG_MIPS_CP0_ENTRYHI MIPS_CP0_64(10, 0)
-#define KVM_REG_MIPS_CP0_COMPARE MIPS_CP0_32(11, 0)
-#define KVM_REG_MIPS_CP0_STATUS MIPS_CP0_32(12, 0)
-#define KVM_REG_MIPS_CP0_CAUSE MIPS_CP0_32(13, 0)
-#define KVM_REG_MIPS_CP0_EPC MIPS_CP0_64(14, 0)
-#define KVM_REG_MIPS_CP0_PRID MIPS_CP0_32(15, 0)
-#define KVM_REG_MIPS_CP0_EBASE MIPS_CP0_64(15, 1)
-#define KVM_REG_MIPS_CP0_CONFIG MIPS_CP0_32(16, 0)
-#define KVM_REG_MIPS_CP0_CONFIG1 MIPS_CP0_32(16, 1)
-#define KVM_REG_MIPS_CP0_CONFIG2 MIPS_CP0_32(16, 2)
-#define KVM_REG_MIPS_CP0_CONFIG3 MIPS_CP0_32(16, 3)
-#define KVM_REG_MIPS_CP0_CONFIG4 MIPS_CP0_32(16, 4)
-#define KVM_REG_MIPS_CP0_CONFIG5 MIPS_CP0_32(16, 5)
-#define KVM_REG_MIPS_CP0_CONFIG6 MIPS_CP0_32(16, 6)
-#define KVM_REG_MIPS_CP0_XCONTEXT MIPS_CP0_64(20, 0)
-#define KVM_REG_MIPS_CP0_ERROREPC MIPS_CP0_64(30, 0)
-#define KVM_REG_MIPS_CP0_KSCRATCH1 MIPS_CP0_64(31, 2)
-#define KVM_REG_MIPS_CP0_KSCRATCH2 MIPS_CP0_64(31, 3)
-#define KVM_REG_MIPS_CP0_KSCRATCH3 MIPS_CP0_64(31, 4)
-#define KVM_REG_MIPS_CP0_KSCRATCH4 MIPS_CP0_64(31, 5)
-#define KVM_REG_MIPS_CP0_KSCRATCH5 MIPS_CP0_64(31, 6)
-#define KVM_REG_MIPS_CP0_KSCRATCH6 MIPS_CP0_64(31, 7)
-
-static inline int kvm_mips_put_one_reg(CPUState *cs, uint64_t reg_id,
- int32_t *addr)
-{
- struct kvm_one_reg cp0reg = {
- .id = reg_id,
- .addr = (uintptr_t)addr
- };
-
- return kvm_vcpu_ioctl(cs, KVM_SET_ONE_REG, &cp0reg);
-}
-
-static inline int kvm_mips_put_one_ureg(CPUState *cs, uint64_t reg_id,
- uint32_t *addr)
-{
- struct kvm_one_reg cp0reg = {
- .id = reg_id,
- .addr = (uintptr_t)addr
- };
-
- return kvm_vcpu_ioctl(cs, KVM_SET_ONE_REG, &cp0reg);
-}
-
-static inline int kvm_mips_put_one_ulreg(CPUState *cs, uint64_t reg_id,
- target_ulong *addr)
-{
- uint64_t val64 = *addr;
- struct kvm_one_reg cp0reg = {
- .id = reg_id,
- .addr = (uintptr_t)&val64
- };
-
- return kvm_vcpu_ioctl(cs, KVM_SET_ONE_REG, &cp0reg);
-}
-
-static inline int kvm_mips_put_one_reg64(CPUState *cs, uint64_t reg_id,
- int64_t *addr)
-{
- struct kvm_one_reg cp0reg = {
- .id = reg_id,
- .addr = (uintptr_t)addr
- };
-
- return kvm_vcpu_ioctl(cs, KVM_SET_ONE_REG, &cp0reg);
-}
-
-static inline int kvm_mips_put_one_ureg64(CPUState *cs, uint64_t reg_id,
- uint64_t *addr)
-{
- struct kvm_one_reg cp0reg = {
- .id = reg_id,
- .addr = (uintptr_t)addr
- };
-
- return kvm_vcpu_ioctl(cs, KVM_SET_ONE_REG, &cp0reg);
-}
-
-static inline int kvm_mips_get_one_reg(CPUState *cs, uint64_t reg_id,
- int32_t *addr)
-{
- struct kvm_one_reg cp0reg = {
- .id = reg_id,
- .addr = (uintptr_t)addr
- };
-
- return kvm_vcpu_ioctl(cs, KVM_GET_ONE_REG, &cp0reg);
-}
-
-static inline int kvm_mips_get_one_ureg(CPUState *cs, uint64_t reg_id,
- uint32_t *addr)
-{
- struct kvm_one_reg cp0reg = {
- .id = reg_id,
- .addr = (uintptr_t)addr
- };
-
- return kvm_vcpu_ioctl(cs, KVM_GET_ONE_REG, &cp0reg);
-}
-
-static inline int kvm_mips_get_one_ulreg(CPUState *cs, uint64_t reg_id,
- target_ulong *addr)
-{
- int ret;
- uint64_t val64 = 0;
- struct kvm_one_reg cp0reg = {
- .id = reg_id,
- .addr = (uintptr_t)&val64
- };
-
- ret = kvm_vcpu_ioctl(cs, KVM_GET_ONE_REG, &cp0reg);
- if (ret >= 0) {
- *addr = val64;
- }
- return ret;
-}
-
-static inline int kvm_mips_get_one_reg64(CPUState *cs, uint64_t reg_id,
- int64_t *addr)
-{
- struct kvm_one_reg cp0reg = {
- .id = reg_id,
- .addr = (uintptr_t)addr
- };
-
- return kvm_vcpu_ioctl(cs, KVM_GET_ONE_REG, &cp0reg);
-}
-
-static inline int kvm_mips_get_one_ureg64(CPUState *cs, uint64_t reg_id,
- uint64_t *addr)
-{
- struct kvm_one_reg cp0reg = {
- .id = reg_id,
- .addr = (uintptr_t)addr
- };
-
- return kvm_vcpu_ioctl(cs, KVM_GET_ONE_REG, &cp0reg);
-}
-
-#define KVM_REG_MIPS_CP0_CONFIG_MASK (1U << CP0C0_M)
-#define KVM_REG_MIPS_CP0_CONFIG1_MASK ((1U << CP0C1_M) | \
- (1U << CP0C1_FP))
-#define KVM_REG_MIPS_CP0_CONFIG2_MASK (1U << CP0C2_M)
-#define KVM_REG_MIPS_CP0_CONFIG3_MASK ((1U << CP0C3_M) | \
- (1U << CP0C3_MSAP))
-#define KVM_REG_MIPS_CP0_CONFIG4_MASK (1U << CP0C4_M)
-#define KVM_REG_MIPS_CP0_CONFIG5_MASK ((1U << CP0C5_MSAEn) | \
- (1U << CP0C5_UFE) | \
- (1U << CP0C5_FRE) | \
- (1U << CP0C5_UFR))
-#define KVM_REG_MIPS_CP0_CONFIG6_MASK ((1U << CP0C6_BPPASS) | \
- (0x3fU << CP0C6_KPOS) | \
- (1U << CP0C6_KE) | \
- (1U << CP0C6_VTLBONLY) | \
- (1U << CP0C6_LASX) | \
- (1U << CP0C6_SSEN) | \
- (1U << CP0C6_DISDRTIME) | \
- (1U << CP0C6_PIXNUEN) | \
- (1U << CP0C6_SCRAND) | \
- (1U << CP0C6_LLEXCEN) | \
- (1U << CP0C6_DISVC) | \
- (1U << CP0C6_VCLRU) | \
- (1U << CP0C6_DCLRU) | \
- (1U << CP0C6_PIXUEN) | \
- (1U << CP0C6_DISBLKLYEN) | \
- (1U << CP0C6_UMEMUALEN) | \
- (1U << CP0C6_SFBEN) | \
- (1U << CP0C6_FLTINT) | \
- (1U << CP0C6_VLTINT) | \
- (1U << CP0C6_DISBTB) | \
- (3U << CP0C6_STPREFCTL) | \
- (1U << CP0C6_INSTPREF) | \
- (1U << CP0C6_DATAPREF))
-
-static inline int kvm_mips_change_one_reg(CPUState *cs, uint64_t reg_id,
- int32_t *addr, int32_t mask)
-{
- int err;
- int32_t tmp, change;
-
- err = kvm_mips_get_one_reg(cs, reg_id, &tmp);
- if (err < 0) {
- return err;
- }
-
- /* only change bits in mask */
- change = (*addr ^ tmp) & mask;
- if (!change) {
- return 0;
- }
-
- tmp = tmp ^ change;
- return kvm_mips_put_one_reg(cs, reg_id, &tmp);
-}
-
-/*
- * We freeze the KVM timer when either the VM clock is stopped or the state is
- * saved (the state is dirty).
- */
-
-/*
- * Save the state of the KVM timer when VM clock is stopped or state is synced
- * to QEMU.
- */
-static int kvm_mips_save_count(CPUState *cs)
-{
- CPUMIPSState *env = cpu_env(cs);
- uint64_t count_ctl;
- int err, ret = 0;
-
- /* freeze KVM timer */
- err = kvm_mips_get_one_ureg64(cs, KVM_REG_MIPS_COUNT_CTL, &count_ctl);
- if (err < 0) {
- DPRINTF("%s: Failed to get COUNT_CTL (%d)\n", __func__, err);
- ret = err;
- } else if (!(count_ctl & KVM_REG_MIPS_COUNT_CTL_DC)) {
- count_ctl |= KVM_REG_MIPS_COUNT_CTL_DC;
- err = kvm_mips_put_one_ureg64(cs, KVM_REG_MIPS_COUNT_CTL, &count_ctl);
- if (err < 0) {
- DPRINTF("%s: Failed to set COUNT_CTL.DC=1 (%d)\n", __func__, err);
- ret = err;
- }
- }
-
- /* read CP0_Cause */
- err = kvm_mips_get_one_reg(cs, KVM_REG_MIPS_CP0_CAUSE, &env->CP0_Cause);
- if (err < 0) {
- DPRINTF("%s: Failed to get CP0_CAUSE (%d)\n", __func__, err);
- ret = err;
- }
-
- /* read CP0_Count */
- err = kvm_mips_get_one_reg(cs, KVM_REG_MIPS_CP0_COUNT, &env->CP0_Count);
- if (err < 0) {
- DPRINTF("%s: Failed to get CP0_COUNT (%d)\n", __func__, err);
- ret = err;
- }
-
- return ret;
-}
-
-/*
- * Restore the state of the KVM timer when VM clock is restarted or state is
- * synced to KVM.
- */
-static int kvm_mips_restore_count(CPUState *cs)
-{
- CPUMIPSState *env = cpu_env(cs);
- uint64_t count_ctl;
- int err_dc, err, ret = 0;
-
- /* check the timer is frozen */
- err_dc = kvm_mips_get_one_ureg64(cs, KVM_REG_MIPS_COUNT_CTL, &count_ctl);
- if (err_dc < 0) {
- DPRINTF("%s: Failed to get COUNT_CTL (%d)\n", __func__, err_dc);
- ret = err_dc;
- } else if (!(count_ctl & KVM_REG_MIPS_COUNT_CTL_DC)) {
- /* freeze timer (sets COUNT_RESUME for us) */
- count_ctl |= KVM_REG_MIPS_COUNT_CTL_DC;
- err = kvm_mips_put_one_ureg64(cs, KVM_REG_MIPS_COUNT_CTL, &count_ctl);
- if (err < 0) {
- DPRINTF("%s: Failed to set COUNT_CTL.DC=1 (%d)\n", __func__, err);
- ret = err;
- }
- }
-
- /* load CP0_Cause */
- err = kvm_mips_put_one_reg(cs, KVM_REG_MIPS_CP0_CAUSE, &env->CP0_Cause);
- if (err < 0) {
- DPRINTF("%s: Failed to put CP0_CAUSE (%d)\n", __func__, err);
- ret = err;
- }
-
- /* load CP0_Count */
- err = kvm_mips_put_one_reg(cs, KVM_REG_MIPS_CP0_COUNT, &env->CP0_Count);
- if (err < 0) {
- DPRINTF("%s: Failed to put CP0_COUNT (%d)\n", __func__, err);
- ret = err;
- }
-
- /* resume KVM timer */
- if (err_dc >= 0) {
- count_ctl &= ~KVM_REG_MIPS_COUNT_CTL_DC;
- err = kvm_mips_put_one_ureg64(cs, KVM_REG_MIPS_COUNT_CTL, &count_ctl);
- if (err < 0) {
- DPRINTF("%s: Failed to set COUNT_CTL.DC=0 (%d)\n", __func__, err);
- ret = err;
- }
- }
-
- return ret;
-}
-
-/*
- * Handle the VM clock being started or stopped
- */
-static void kvm_mips_update_state(void *opaque, bool running, RunState state)
-{
- CPUState *cs = opaque;
- int ret;
- uint64_t count_resume;
-
- /*
- * If state is already dirty (synced to QEMU) then the KVM timer state is
- * already saved and can be restored when it is synced back to KVM.
- */
- if (!running) {
- if (!cs->vcpu_dirty) {
- ret = kvm_mips_save_count(cs);
- if (ret < 0) {
- warn_report("Failed saving count");
- }
- }
- } else {
- /* Set clock restore time to now */
- count_resume = qemu_clock_get_ns(QEMU_CLOCK_REALTIME);
- ret = kvm_mips_put_one_ureg64(cs, KVM_REG_MIPS_COUNT_RESUME,
- &count_resume);
- if (ret < 0) {
- warn_report("Failed setting COUNT_RESUME");
- return;
- }
-
- if (!cs->vcpu_dirty) {
- ret = kvm_mips_restore_count(cs);
- if (ret < 0) {
- warn_report("Failed restoring count");
- }
- }
- }
-}
-
-static int kvm_mips_put_fpu_registers(CPUState *cs, KvmPutState level)
-{
- CPUMIPSState *env = cpu_env(cs);
- int err, ret = 0;
- unsigned int i;
-
- /* Only put FPU state if we're emulating a CPU with an FPU */
- if (env->CP0_Config1 & (1 << CP0C1_FP)) {
- /* FPU Control Registers */
- if (level == KVM_PUT_FULL_STATE) {
- err = kvm_mips_put_one_ureg(cs, KVM_REG_MIPS_FCR_IR,
- &env->active_fpu.fcr0);
- if (err < 0) {
- DPRINTF("%s: Failed to put FCR_IR (%d)\n", __func__, err);
- ret = err;
- }
- }
- err = kvm_mips_put_one_ureg(cs, KVM_REG_MIPS_FCR_CSR,
- &env->active_fpu.fcr31);
- if (err < 0) {
- DPRINTF("%s: Failed to put FCR_CSR (%d)\n", __func__, err);
- ret = err;
- }
-
- /*
- * FPU register state is a subset of MSA vector state, so don't put FPU
- * registers if we're emulating a CPU with MSA.
- */
- if (!ase_msa_available(env)) {
- /* Floating point registers */
- for (i = 0; i < 32; ++i) {
- if (env->CP0_Status & (1 << CP0St_FR)) {
- err = kvm_mips_put_one_ureg64(cs, KVM_REG_MIPS_FPR_64(i),
- &env->active_fpu.fpr[i].d);
- } else {
- err = kvm_mips_get_one_ureg(cs, KVM_REG_MIPS_FPR_32(i),
- &env->active_fpu.fpr[i].w[FP_ENDIAN_IDX]);
- }
- if (err < 0) {
- DPRINTF("%s: Failed to put FPR%u (%d)\n", __func__, i, err);
- ret = err;
- }
- }
- }
- }
-
- /* Only put MSA state if we're emulating a CPU with MSA */
- if (ase_msa_available(env)) {
- /* MSA Control Registers */
- if (level == KVM_PUT_FULL_STATE) {
- err = kvm_mips_put_one_reg(cs, KVM_REG_MIPS_MSA_IR,
- &env->msair);
- if (err < 0) {
- DPRINTF("%s: Failed to put MSA_IR (%d)\n", __func__, err);
- ret = err;
- }
- }
- err = kvm_mips_put_one_reg(cs, KVM_REG_MIPS_MSA_CSR,
- &env->active_tc.msacsr);
- if (err < 0) {
- DPRINTF("%s: Failed to put MSA_CSR (%d)\n", __func__, err);
- ret = err;
- }
-
- /* Vector registers (includes FP registers) */
- for (i = 0; i < 32; ++i) {
- /* Big endian MSA not supported by QEMU yet anyway */
- err = kvm_mips_put_one_reg64(cs, KVM_REG_MIPS_VEC_128(i),
- env->active_fpu.fpr[i].wr.d);
- if (err < 0) {
- DPRINTF("%s: Failed to put VEC%u (%d)\n", __func__, i, err);
- ret = err;
- }
- }
- }
-
- return ret;
-}
-
-static int kvm_mips_get_fpu_registers(CPUState *cs)
-{
- CPUMIPSState *env = cpu_env(cs);
- int err, ret = 0;
- unsigned int i;
-
- /* Only get FPU state if we're emulating a CPU with an FPU */
- if (env->CP0_Config1 & (1 << CP0C1_FP)) {
- /* FPU Control Registers */
- err = kvm_mips_get_one_ureg(cs, KVM_REG_MIPS_FCR_IR,
- &env->active_fpu.fcr0);
- if (err < 0) {
- DPRINTF("%s: Failed to get FCR_IR (%d)\n", __func__, err);
- ret = err;
- }
- err = kvm_mips_get_one_ureg(cs, KVM_REG_MIPS_FCR_CSR,
- &env->active_fpu.fcr31);
- if (err < 0) {
- DPRINTF("%s: Failed to get FCR_CSR (%d)\n", __func__, err);
- ret = err;
- } else {
- restore_fp_status(env);
- }
-
- /*
- * FPU register state is a subset of MSA vector state, so don't save FPU
- * registers if we're emulating a CPU with MSA.
- */
- if (!ase_msa_available(env)) {
- /* Floating point registers */
- for (i = 0; i < 32; ++i) {
- if (env->CP0_Status & (1 << CP0St_FR)) {
- err = kvm_mips_get_one_ureg64(cs, KVM_REG_MIPS_FPR_64(i),
- &env->active_fpu.fpr[i].d);
- } else {
- err = kvm_mips_get_one_ureg(cs, KVM_REG_MIPS_FPR_32(i),
- &env->active_fpu.fpr[i].w[FP_ENDIAN_IDX]);
- }
- if (err < 0) {
- DPRINTF("%s: Failed to get FPR%u (%d)\n", __func__, i, err);
- ret = err;
- }
- }
- }
- }
-
- /* Only get MSA state if we're emulating a CPU with MSA */
- if (ase_msa_available(env)) {
- /* MSA Control Registers */
- err = kvm_mips_get_one_reg(cs, KVM_REG_MIPS_MSA_IR,
- &env->msair);
- if (err < 0) {
- DPRINTF("%s: Failed to get MSA_IR (%d)\n", __func__, err);
- ret = err;
- }
- err = kvm_mips_get_one_reg(cs, KVM_REG_MIPS_MSA_CSR,
- &env->active_tc.msacsr);
- if (err < 0) {
- DPRINTF("%s: Failed to get MSA_CSR (%d)\n", __func__, err);
- ret = err;
- } else {
- restore_msa_fp_status(env);
- }
-
- /* Vector registers (includes FP registers) */
- for (i = 0; i < 32; ++i) {
- /* Big endian MSA not supported by QEMU yet anyway */
- err = kvm_mips_get_one_reg64(cs, KVM_REG_MIPS_VEC_128(i),
- env->active_fpu.fpr[i].wr.d);
- if (err < 0) {
- DPRINTF("%s: Failed to get VEC%u (%d)\n", __func__, i, err);
- ret = err;
- }
- }
- }
-
- return ret;
-}
-
-
-static int kvm_mips_put_cp0_registers(CPUState *cs, KvmPutState level)
-{
- CPUMIPSState *env = cpu_env(cs);
- int err, ret = 0;
-
- (void)level;
-
- err = kvm_mips_put_one_reg(cs, KVM_REG_MIPS_CP0_INDEX, &env->CP0_Index);
- if (err < 0) {
- DPRINTF("%s: Failed to put CP0_INDEX (%d)\n", __func__, err);
- ret = err;
- }
- err = kvm_mips_put_one_reg(cs, KVM_REG_MIPS_CP0_RANDOM, &env->CP0_Random);
- if (err < 0) {
- DPRINTF("%s: Failed to put CP0_RANDOM (%d)\n", __func__, err);
- ret = err;
- }
- err = kvm_mips_put_one_ulreg(cs, KVM_REG_MIPS_CP0_CONTEXT,
- &env->CP0_Context);
- if (err < 0) {
- DPRINTF("%s: Failed to put CP0_CONTEXT (%d)\n", __func__, err);
- ret = err;
- }
- err = kvm_mips_put_one_ulreg(cs, KVM_REG_MIPS_CP0_USERLOCAL,
- &env->active_tc.CP0_UserLocal);
- if (err < 0) {
- DPRINTF("%s: Failed to put CP0_USERLOCAL (%d)\n", __func__, err);
- ret = err;
- }
- err = kvm_mips_put_one_reg(cs, KVM_REG_MIPS_CP0_PAGEMASK,
- &env->CP0_PageMask);
- if (err < 0) {
- DPRINTF("%s: Failed to put CP0_PAGEMASK (%d)\n", __func__, err);
- ret = err;
- }
- err = kvm_mips_put_one_reg(cs, KVM_REG_MIPS_CP0_PAGEGRAIN,
- &env->CP0_PageGrain);
- if (err < 0) {
- DPRINTF("%s: Failed to put CP0_PAGEGRAIN (%d)\n", __func__, err);
- ret = err;
- }
- err = kvm_mips_put_one_ulreg(cs, KVM_REG_MIPS_CP0_PWBASE,
- &env->CP0_PWBase);
- if (err < 0) {
- DPRINTF("%s: Failed to put CP0_PWBASE (%d)\n", __func__, err);
- ret = err;
- }
- err = kvm_mips_put_one_ulreg(cs, KVM_REG_MIPS_CP0_PWFIELD,
- &env->CP0_PWField);
- if (err < 0) {
- DPRINTF("%s: Failed to put CP0_PWField (%d)\n", __func__, err);
- ret = err;
- }
- err = kvm_mips_put_one_ulreg(cs, KVM_REG_MIPS_CP0_PWSIZE,
- &env->CP0_PWSize);
- if (err < 0) {
- DPRINTF("%s: Failed to put CP0_PWSIZE (%d)\n", __func__, err);
- ret = err;
- }
- err = kvm_mips_put_one_reg(cs, KVM_REG_MIPS_CP0_WIRED, &env->CP0_Wired);
- if (err < 0) {
- DPRINTF("%s: Failed to put CP0_WIRED (%d)\n", __func__, err);
- ret = err;
- }
- err = kvm_mips_put_one_reg(cs, KVM_REG_MIPS_CP0_PWCTL, &env->CP0_PWCtl);
- if (err < 0) {
- DPRINTF("%s: Failed to put CP0_PWCTL (%d)\n", __func__, err);
- ret = err;
- }
- err = kvm_mips_put_one_reg(cs, KVM_REG_MIPS_CP0_HWRENA, &env->CP0_HWREna);
- if (err < 0) {
- DPRINTF("%s: Failed to put CP0_HWRENA (%d)\n", __func__, err);
- ret = err;
- }
- err = kvm_mips_put_one_ulreg(cs, KVM_REG_MIPS_CP0_BADVADDR,
- &env->CP0_BadVAddr);
- if (err < 0) {
- DPRINTF("%s: Failed to put CP0_BADVADDR (%d)\n", __func__, err);
- ret = err;
- }
-
- /* If VM clock stopped then state will be restored when it is restarted */
- if (runstate_is_running()) {
- err = kvm_mips_restore_count(cs);
- if (err < 0) {
- ret = err;
- }
- }
-
- err = kvm_mips_put_one_ulreg(cs, KVM_REG_MIPS_CP0_ENTRYHI,
- &env->CP0_EntryHi);
- if (err < 0) {
- DPRINTF("%s: Failed to put CP0_ENTRYHI (%d)\n", __func__, err);
- ret = err;
- }
- err = kvm_mips_put_one_reg(cs, KVM_REG_MIPS_CP0_COMPARE,
- &env->CP0_Compare);
- if (err < 0) {
- DPRINTF("%s: Failed to put CP0_COMPARE (%d)\n", __func__, err);
- ret = err;
- }
- err = kvm_mips_put_one_reg(cs, KVM_REG_MIPS_CP0_STATUS, &env->CP0_Status);
- if (err < 0) {
- DPRINTF("%s: Failed to put CP0_STATUS (%d)\n", __func__, err);
- ret = err;
- }
- err = kvm_mips_put_one_ulreg(cs, KVM_REG_MIPS_CP0_EPC, &env->CP0_EPC);
- if (err < 0) {
- DPRINTF("%s: Failed to put CP0_EPC (%d)\n", __func__, err);
- ret = err;
- }
- err = kvm_mips_put_one_reg(cs, KVM_REG_MIPS_CP0_PRID, &env->CP0_PRid);
- if (err < 0) {
- DPRINTF("%s: Failed to put CP0_PRID (%d)\n", __func__, err);
- ret = err;
- }
- err = kvm_mips_put_one_ulreg(cs, KVM_REG_MIPS_CP0_EBASE, &env->CP0_EBase);
- if (err < 0) {
- DPRINTF("%s: Failed to put CP0_EBASE (%d)\n", __func__, err);
- ret = err;
- }
- err = kvm_mips_change_one_reg(cs, KVM_REG_MIPS_CP0_CONFIG,
- &env->CP0_Config0,
- KVM_REG_MIPS_CP0_CONFIG_MASK);
- if (err < 0) {
- DPRINTF("%s: Failed to change CP0_CONFIG (%d)\n", __func__, err);
- ret = err;
- }
- err = kvm_mips_change_one_reg(cs, KVM_REG_MIPS_CP0_CONFIG1,
- &env->CP0_Config1,
- KVM_REG_MIPS_CP0_CONFIG1_MASK);
- if (err < 0) {
- DPRINTF("%s: Failed to change CP0_CONFIG1 (%d)\n", __func__, err);
- ret = err;
- }
- err = kvm_mips_change_one_reg(cs, KVM_REG_MIPS_CP0_CONFIG2,
- &env->CP0_Config2,
- KVM_REG_MIPS_CP0_CONFIG2_MASK);
- if (err < 0) {
- DPRINTF("%s: Failed to change CP0_CONFIG2 (%d)\n", __func__, err);
- ret = err;
- }
- err = kvm_mips_change_one_reg(cs, KVM_REG_MIPS_CP0_CONFIG3,
- &env->CP0_Config3,
- KVM_REG_MIPS_CP0_CONFIG3_MASK);
- if (err < 0) {
- DPRINTF("%s: Failed to change CP0_CONFIG3 (%d)\n", __func__, err);
- ret = err;
- }
- err = kvm_mips_change_one_reg(cs, KVM_REG_MIPS_CP0_CONFIG4,
- &env->CP0_Config4,
- KVM_REG_MIPS_CP0_CONFIG4_MASK);
- if (err < 0) {
- DPRINTF("%s: Failed to change CP0_CONFIG4 (%d)\n", __func__, err);
- ret = err;
- }
- err = kvm_mips_change_one_reg(cs, KVM_REG_MIPS_CP0_CONFIG5,
- &env->CP0_Config5,
- KVM_REG_MIPS_CP0_CONFIG5_MASK);
- if (err < 0) {
- DPRINTF("%s: Failed to change CP0_CONFIG5 (%d)\n", __func__, err);
- ret = err;
- }
- err = kvm_mips_change_one_reg(cs, KVM_REG_MIPS_CP0_CONFIG6,
- &env->CP0_Config6,
- KVM_REG_MIPS_CP0_CONFIG6_MASK);
- if (err < 0) {
- DPRINTF("%s: Failed to change CP0_CONFIG6 (%d)\n", __func__, err);
- ret = err;
- }
- err = kvm_mips_put_one_ulreg(cs, KVM_REG_MIPS_CP0_XCONTEXT,
- &env->CP0_XContext);
- if (err < 0) {
- DPRINTF("%s: Failed to put CP0_XCONTEXT (%d)\n", __func__, err);
- ret = err;
- }
- err = kvm_mips_put_one_ulreg(cs, KVM_REG_MIPS_CP0_ERROREPC,
- &env->CP0_ErrorEPC);
- if (err < 0) {
- DPRINTF("%s: Failed to put CP0_ERROREPC (%d)\n", __func__, err);
- ret = err;
- }
- err = kvm_mips_put_one_ulreg(cs, KVM_REG_MIPS_CP0_KSCRATCH1,
- &env->CP0_KScratch[0]);
- if (err < 0) {
- DPRINTF("%s: Failed to put CP0_KSCRATCH1 (%d)\n", __func__, err);
- ret = err;
- }
- err = kvm_mips_put_one_ulreg(cs, KVM_REG_MIPS_CP0_KSCRATCH2,
- &env->CP0_KScratch[1]);
- if (err < 0) {
- DPRINTF("%s: Failed to put CP0_KSCRATCH2 (%d)\n", __func__, err);
- ret = err;
- }
- err = kvm_mips_put_one_ulreg(cs, KVM_REG_MIPS_CP0_KSCRATCH3,
- &env->CP0_KScratch[2]);
- if (err < 0) {
- DPRINTF("%s: Failed to put CP0_KSCRATCH3 (%d)\n", __func__, err);
- ret = err;
- }
- err = kvm_mips_put_one_ulreg(cs, KVM_REG_MIPS_CP0_KSCRATCH4,
- &env->CP0_KScratch[3]);
- if (err < 0) {
- DPRINTF("%s: Failed to put CP0_KSCRATCH4 (%d)\n", __func__, err);
- ret = err;
- }
- err = kvm_mips_put_one_ulreg(cs, KVM_REG_MIPS_CP0_KSCRATCH5,
- &env->CP0_KScratch[4]);
- if (err < 0) {
- DPRINTF("%s: Failed to put CP0_KSCRATCH5 (%d)\n", __func__, err);
- ret = err;
- }
- err = kvm_mips_put_one_ulreg(cs, KVM_REG_MIPS_CP0_KSCRATCH6,
- &env->CP0_KScratch[5]);
- if (err < 0) {
- DPRINTF("%s: Failed to put CP0_KSCRATCH6 (%d)\n", __func__, err);
- ret = err;
- }
-
- return ret;
-}
-
-static int kvm_mips_get_cp0_registers(CPUState *cs)
-{
- CPUMIPSState *env = cpu_env(cs);
- int err, ret = 0;
-
- err = kvm_mips_get_one_reg(cs, KVM_REG_MIPS_CP0_INDEX, &env->CP0_Index);
- if (err < 0) {
- DPRINTF("%s: Failed to get CP0_INDEX (%d)\n", __func__, err);
- ret = err;
- }
- err = kvm_mips_get_one_reg(cs, KVM_REG_MIPS_CP0_RANDOM, &env->CP0_Random);
- if (err < 0) {
- DPRINTF("%s: Failed to get CP0_RANDOM (%d)\n", __func__, err);
- ret = err;
- }
- err = kvm_mips_get_one_ulreg(cs, KVM_REG_MIPS_CP0_CONTEXT,
- &env->CP0_Context);
- if (err < 0) {
- DPRINTF("%s: Failed to get CP0_CONTEXT (%d)\n", __func__, err);
- ret = err;
- }
- err = kvm_mips_get_one_ulreg(cs, KVM_REG_MIPS_CP0_USERLOCAL,
- &env->active_tc.CP0_UserLocal);
- if (err < 0) {
- DPRINTF("%s: Failed to get CP0_USERLOCAL (%d)\n", __func__, err);
- ret = err;
- }
- err = kvm_mips_get_one_reg(cs, KVM_REG_MIPS_CP0_PAGEMASK,
- &env->CP0_PageMask);
- if (err < 0) {
- DPRINTF("%s: Failed to get CP0_PAGEMASK (%d)\n", __func__, err);
- ret = err;
- }
- err = kvm_mips_get_one_reg(cs, KVM_REG_MIPS_CP0_PAGEGRAIN,
- &env->CP0_PageGrain);
- if (err < 0) {
- DPRINTF("%s: Failed to get CP0_PAGEGRAIN (%d)\n", __func__, err);
- ret = err;
- }
- err = kvm_mips_get_one_ulreg(cs, KVM_REG_MIPS_CP0_PWBASE,
- &env->CP0_PWBase);
- if (err < 0) {
- DPRINTF("%s: Failed to get CP0_PWBASE (%d)\n", __func__, err);
- ret = err;
- }
- err = kvm_mips_get_one_ulreg(cs, KVM_REG_MIPS_CP0_PWFIELD,
- &env->CP0_PWField);
- if (err < 0) {
- DPRINTF("%s: Failed to get CP0_PWFIELD (%d)\n", __func__, err);
- ret = err;
- }
- err = kvm_mips_get_one_ulreg(cs, KVM_REG_MIPS_CP0_PWSIZE,
- &env->CP0_PWSize);
- if (err < 0) {
- DPRINTF("%s: Failed to get CP0_PWSIZE (%d)\n", __func__, err);
- ret = err;
- }
- err = kvm_mips_get_one_reg(cs, KVM_REG_MIPS_CP0_WIRED, &env->CP0_Wired);
- if (err < 0) {
- DPRINTF("%s: Failed to get CP0_WIRED (%d)\n", __func__, err);
- ret = err;
- }
- err = kvm_mips_get_one_reg(cs, KVM_REG_MIPS_CP0_PWCTL, &env->CP0_PWCtl);
- if (err < 0) {
- DPRINTF("%s: Failed to get CP0_PWCtl (%d)\n", __func__, err);
- ret = err;
- }
- err = kvm_mips_get_one_reg(cs, KVM_REG_MIPS_CP0_HWRENA, &env->CP0_HWREna);
- if (err < 0) {
- DPRINTF("%s: Failed to get CP0_HWRENA (%d)\n", __func__, err);
- ret = err;
- }
- err = kvm_mips_get_one_ulreg(cs, KVM_REG_MIPS_CP0_BADVADDR,
- &env->CP0_BadVAddr);
- if (err < 0) {
- DPRINTF("%s: Failed to get CP0_BADVADDR (%d)\n", __func__, err);
- ret = err;
- }
- err = kvm_mips_get_one_ulreg(cs, KVM_REG_MIPS_CP0_ENTRYHI,
- &env->CP0_EntryHi);
- if (err < 0) {
- DPRINTF("%s: Failed to get CP0_ENTRYHI (%d)\n", __func__, err);
- ret = err;
- }
- err = kvm_mips_get_one_reg(cs, KVM_REG_MIPS_CP0_COMPARE,
- &env->CP0_Compare);
- if (err < 0) {
- DPRINTF("%s: Failed to get CP0_COMPARE (%d)\n", __func__, err);
- ret = err;
- }
- err = kvm_mips_get_one_reg(cs, KVM_REG_MIPS_CP0_STATUS, &env->CP0_Status);
- if (err < 0) {
- DPRINTF("%s: Failed to get CP0_STATUS (%d)\n", __func__, err);
- ret = err;
- }
-
- /* If VM clock stopped then state was already saved when it was stopped */
- if (runstate_is_running()) {
- err = kvm_mips_save_count(cs);
- if (err < 0) {
- ret = err;
- }
- }
-
- err = kvm_mips_get_one_ulreg(cs, KVM_REG_MIPS_CP0_EPC, &env->CP0_EPC);
- if (err < 0) {
- DPRINTF("%s: Failed to get CP0_EPC (%d)\n", __func__, err);
- ret = err;
- }
- err = kvm_mips_get_one_reg(cs, KVM_REG_MIPS_CP0_PRID, &env->CP0_PRid);
- if (err < 0) {
- DPRINTF("%s: Failed to get CP0_PRID (%d)\n", __func__, err);
- ret = err;
- }
- err = kvm_mips_get_one_ulreg(cs, KVM_REG_MIPS_CP0_EBASE, &env->CP0_EBase);
- if (err < 0) {
- DPRINTF("%s: Failed to get CP0_EBASE (%d)\n", __func__, err);
- ret = err;
- }
- err = kvm_mips_get_one_reg(cs, KVM_REG_MIPS_CP0_CONFIG, &env->CP0_Config0);
- if (err < 0) {
- DPRINTF("%s: Failed to get CP0_CONFIG (%d)\n", __func__, err);
- ret = err;
- }
- err = kvm_mips_get_one_reg(cs, KVM_REG_MIPS_CP0_CONFIG1, &env->CP0_Config1);
- if (err < 0) {
- DPRINTF("%s: Failed to get CP0_CONFIG1 (%d)\n", __func__, err);
- ret = err;
- }
- err = kvm_mips_get_one_reg(cs, KVM_REG_MIPS_CP0_CONFIG2, &env->CP0_Config2);
- if (err < 0) {
- DPRINTF("%s: Failed to get CP0_CONFIG2 (%d)\n", __func__, err);
- ret = err;
- }
- err = kvm_mips_get_one_reg(cs, KVM_REG_MIPS_CP0_CONFIG3, &env->CP0_Config3);
- if (err < 0) {
- DPRINTF("%s: Failed to get CP0_CONFIG3 (%d)\n", __func__, err);
- ret = err;
- }
- err = kvm_mips_get_one_reg(cs, KVM_REG_MIPS_CP0_CONFIG4, &env->CP0_Config4);
- if (err < 0) {
- DPRINTF("%s: Failed to get CP0_CONFIG4 (%d)\n", __func__, err);
- ret = err;
- }
- err = kvm_mips_get_one_reg(cs, KVM_REG_MIPS_CP0_CONFIG5, &env->CP0_Config5);
- if (err < 0) {
- DPRINTF("%s: Failed to get CP0_CONFIG5 (%d)\n", __func__, err);
- ret = err;
- }
- err = kvm_mips_get_one_reg(cs, KVM_REG_MIPS_CP0_CONFIG6, &env->CP0_Config6);
- if (err < 0) {
- DPRINTF("%s: Failed to get CP0_CONFIG6 (%d)\n", __func__, err);
- ret = err;
- }
- err = kvm_mips_get_one_ulreg(cs, KVM_REG_MIPS_CP0_XCONTEXT,
- &env->CP0_XContext);
- if (err < 0) {
- DPRINTF("%s: Failed to get CP0_XCONTEXT (%d)\n", __func__, err);
- ret = err;
- }
- err = kvm_mips_get_one_ulreg(cs, KVM_REG_MIPS_CP0_ERROREPC,
- &env->CP0_ErrorEPC);
- if (err < 0) {
- DPRINTF("%s: Failed to get CP0_ERROREPC (%d)\n", __func__, err);
- ret = err;
- }
- err = kvm_mips_get_one_ulreg(cs, KVM_REG_MIPS_CP0_KSCRATCH1,
- &env->CP0_KScratch[0]);
- if (err < 0) {
- DPRINTF("%s: Failed to get CP0_KSCRATCH1 (%d)\n", __func__, err);
- ret = err;
- }
- err = kvm_mips_get_one_ulreg(cs, KVM_REG_MIPS_CP0_KSCRATCH2,
- &env->CP0_KScratch[1]);
- if (err < 0) {
- DPRINTF("%s: Failed to get CP0_KSCRATCH2 (%d)\n", __func__, err);
- ret = err;
- }
- err = kvm_mips_get_one_ulreg(cs, KVM_REG_MIPS_CP0_KSCRATCH3,
- &env->CP0_KScratch[2]);
- if (err < 0) {
- DPRINTF("%s: Failed to get CP0_KSCRATCH3 (%d)\n", __func__, err);
- ret = err;
- }
- err = kvm_mips_get_one_ulreg(cs, KVM_REG_MIPS_CP0_KSCRATCH4,
- &env->CP0_KScratch[3]);
- if (err < 0) {
- DPRINTF("%s: Failed to get CP0_KSCRATCH4 (%d)\n", __func__, err);
- ret = err;
- }
- err = kvm_mips_get_one_ulreg(cs, KVM_REG_MIPS_CP0_KSCRATCH5,
- &env->CP0_KScratch[4]);
- if (err < 0) {
- DPRINTF("%s: Failed to get CP0_KSCRATCH5 (%d)\n", __func__, err);
- ret = err;
- }
- err = kvm_mips_get_one_ulreg(cs, KVM_REG_MIPS_CP0_KSCRATCH6,
- &env->CP0_KScratch[5]);
- if (err < 0) {
- DPRINTF("%s: Failed to get CP0_KSCRATCH6 (%d)\n", __func__, err);
- ret = err;
- }
-
- return ret;
-}
-
-int kvm_arch_put_registers(CPUState *cs, KvmPutState level, Error **errp)
-{
- CPUMIPSState *env = cpu_env(cs);
- struct kvm_regs regs;
- int ret;
- int i;
-
- /* Set the registers based on QEMU's view of things */
- for (i = 0; i < 32; i++) {
- regs.gpr[i] = (int64_t)(target_long)env->active_tc.gpr[i];
- }
-
- regs.hi = (int64_t)(target_long)env->active_tc.HI[0];
- regs.lo = (int64_t)(target_long)env->active_tc.LO[0];
- regs.pc = (int64_t)(target_long)env->active_tc.PC;
-
- ret = kvm_vcpu_ioctl(cs, KVM_SET_REGS, ®s);
-
- if (ret < 0) {
- return ret;
- }
-
- ret = kvm_mips_put_cp0_registers(cs, level);
- if (ret < 0) {
- return ret;
- }
-
- ret = kvm_mips_put_fpu_registers(cs, level);
- if (ret < 0) {
- return ret;
- }
-
- return ret;
-}
-
-int kvm_arch_get_registers(CPUState *cs, Error **errp)
-{
- CPUMIPSState *env = cpu_env(cs);
- int ret = 0;
- struct kvm_regs regs;
- int i;
-
- /* Get the current register set as KVM seems it */
- ret = kvm_vcpu_ioctl(cs, KVM_GET_REGS, ®s);
-
- if (ret < 0) {
- return ret;
- }
-
- for (i = 0; i < 32; i++) {
- env->active_tc.gpr[i] = regs.gpr[i];
- }
-
- env->active_tc.HI[0] = regs.hi;
- env->active_tc.LO[0] = regs.lo;
- env->active_tc.PC = regs.pc;
-
- kvm_mips_get_cp0_registers(cs);
- kvm_mips_get_fpu_registers(cs);
-
- return ret;
-}
-
-int kvm_arch_fixup_msi_route(struct kvm_irq_routing_entry *route,
- uint64_t address, uint32_t data, PCIDevice *dev)
-{
- return 0;
-}
-
-int kvm_arch_add_msi_route_post(struct kvm_irq_routing_entry *route,
- int vector, PCIDevice *dev)
-{
- return 0;
-}
-
-int kvm_arch_release_virq_post(int virq)
-{
- return 0;
-}
-
-int kvm_arch_msi_data_to_gsi(uint32_t data)
-{
- abort();
-}
-
-int kvm_arch_get_default_type(MachineState *machine)
-{
-#if defined(KVM_CAP_MIPS_VZ)
- int r;
- KVMState *s = KVM_STATE(machine->accelerator);
-
- r = kvm_check_extension(s, KVM_CAP_MIPS_VZ);
- if (r > 0) {
- return KVM_VM_MIPS_VZ;
- }
-#endif
-
- error_report("KVM_VM_MIPS_VZ type is not available");
- return -1;
-}
-
-void kvm_arch_accel_class_init(ObjectClass *oc)
-{
-}
diff --git a/target/mips/system/cp0_timer.c b/target/mips/system/cp0_timer.c
index 634c2a66bbd..6aed5d3af24 100644
--- a/target/mips/system/cp0_timer.c
+++ b/target/mips/system/cp0_timer.c
@@ -23,7 +23,6 @@
#include "qemu/osdep.h"
#include "hw/core/irq.h"
#include "qemu/timer.h"
-#include "system/kvm.h"
#include "internal.h"
/* MIPS R4K timer */
@@ -84,8 +83,7 @@ void cpu_mips_store_count(CPUMIPSState *env, uint32_t count)
{
/*
* This gets called from cpu_state_reset(), potentially before timer init.
- * So env->timer may be NULL, which is also the case with KVM enabled so
- * treat timer as disabled in that case.
+ * So env->timer may be NULL, so treat timer as disabled in that case.
*/
MIPSCPU *cpu = env_archcpu(env);
if (env->CP0_Cause & (1 << CP0Ca_DC) || !env->timer) {
@@ -141,11 +139,5 @@ void cpu_mips_clock_init(MIPSCPU *cpu)
{
CPUMIPSState *env = &cpu->env;
- /*
- * If we're in KVM mode, don't create the periodic timer, that is handled in
- * kernel.
- */
- if (!kvm_enabled()) {
- env->timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, &mips_timer_cb, env);
- }
+ env->timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, &mips_timer_cb, env);
}
diff --git a/target/mips/system/physaddr.c b/target/mips/system/physaddr.c
index fbbbcf6e006..746dbf8aa4e 100644
--- a/target/mips/system/physaddr.c
+++ b/target/mips/system/physaddr.c
@@ -126,7 +126,6 @@ int get_physical_address(CPUMIPSState *env, hwaddr *physical,
int KX = (env->CP0_Status & (1 << CP0St_KX)) != 0;
#endif
int ret = TLBRET_MATCH;
- /* effective address (modified for KVM T&E kernel segments) */
target_ulong address = real_address;
if (address <= USEG_LIMIT) {
diff --git a/target/mips/meson.build b/target/mips/meson.build
index abf0ce3e8b9..5acb3a2dcf5 100644
--- a/target/mips/meson.build
+++ b/target/mips/meson.build
@@ -13,11 +13,7 @@ if have_system
subdir('system')
endif
-if 'CONFIG_TCG' in config_all_accel
- subdir('tcg')
-endif
-
-mips_ss.add(when: 'CONFIG_KVM', if_true: files('kvm.c'))
+subdir('tcg')
target_arch += {'mips': mips_ss}
target_system_arch += {'mips': mips_system_ss}
--
2.53.0
^ permalink raw reply related [flat|nested] 35+ messages in thread
* [PULL 07/33] buildsys: Remove MIPS TCG backend
2026-05-20 19:23 [PULL 00/33] MIPS patches for 2026-05-20 Philippe Mathieu-Daudé
` (5 preceding siblings ...)
2026-05-20 19:23 ` [PULL 06/33] buildsys: Remove MIPS KVM Philippe Mathieu-Daudé
@ 2026-05-20 19:23 ` Philippe Mathieu-Daudé
2026-05-20 19:23 ` [PULL 08/33] hw/intc/mips_gic: Avoid Coverity complaint in VP writes Philippe Mathieu-Daudé
` (26 subsequent siblings)
33 siblings, 0 replies; 35+ messages in thread
From: Philippe Mathieu-Daudé @ 2026-05-20 19:23 UTC (permalink / raw)
To: qemu-devel
We removed support for MIPS host. Remove the now unreachable
TCG host code.
Signed-off-by: Philippe Mathieu-Daudé <philmd@linaro.org>
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
Message-Id: <20260511135312.38705-6-philmd@linaro.org>
---
MAINTAINERS | 9 -
include/user/thunk.h | 2 +-
linux-user/include/host/mips64/host-signal.h | 75 -
tcg/mips64/tcg-target-con-set.h | 30 -
tcg/mips64/tcg-target-con-str.h | 20 -
tcg/mips64/tcg-target-has.h | 69 -
tcg/mips64/tcg-target-mo.h | 13 -
tcg/mips64/tcg-target.h | 75 -
tcg/mips64/tcg-target-opc.h.inc | 1 -
linux-user/mmap.c | 2 +-
tcg/mips64/tcg-target.c.inc | 2605 ------------------
common-user/host/mips64/safe-syscall.inc.S | 114 -
12 files changed, 2 insertions(+), 3013 deletions(-)
delete mode 100644 linux-user/include/host/mips64/host-signal.h
delete mode 100644 tcg/mips64/tcg-target-con-set.h
delete mode 100644 tcg/mips64/tcg-target-con-str.h
delete mode 100644 tcg/mips64/tcg-target-has.h
delete mode 100644 tcg/mips64/tcg-target-mo.h
delete mode 100644 tcg/mips64/tcg-target.h
delete mode 100644 tcg/mips64/tcg-target-opc.h.inc
delete mode 100644 tcg/mips64/tcg-target.c.inc
delete mode 100644 common-user/host/mips64/safe-syscall.inc.S
diff --git a/MAINTAINERS b/MAINTAINERS
index bd7ea53f950..7496ace6d5a 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -4148,15 +4148,6 @@ M: WANG Xuerui <git@xen0n.name>
S: Maintained
F: tcg/loongarch64/
-MIPS TCG target
-M: Philippe Mathieu-Daudé <philmd@linaro.org>
-R: Aurelien Jarno <aurelien@aurel32.net>
-R: Huacai Chen <chenhuacai@kernel.org>
-R: Jiaxun Yang <jiaxun.yang@flygoat.com>
-R: Aleksandar Rikalo <arikalo@gmail.com>
-S: Odd Fixes
-F: tcg/mips64/
-
PPC TCG target
M: Richard Henderson <richard.henderson@linaro.org>
S: Odd Fixes
diff --git a/include/user/thunk.h b/include/user/thunk.h
index 2a2104b568f..9af174eaa18 100644
--- a/include/user/thunk.h
+++ b/include/user/thunk.h
@@ -115,7 +115,7 @@ static inline int thunk_type_size(const argtype *type_ptr, int is_host)
if (is_host) {
#if defined(HOST_X86_64)
return 8;
-#elif defined(HOST_MIPS) || defined(HOST_SPARC64)
+#elif defined(HOST_SPARC64)
return 4;
#elif defined(HOST_PPC)
return sizeof(void *);
diff --git a/linux-user/include/host/mips64/host-signal.h b/linux-user/include/host/mips64/host-signal.h
deleted file mode 100644
index 0dbc5cecfde..00000000000
--- a/linux-user/include/host/mips64/host-signal.h
+++ /dev/null
@@ -1,75 +0,0 @@
-/*
- * host-signal.h: signal info dependent on the host architecture
- *
- * Copyright (c) 2003-2005 Fabrice Bellard
- * Copyright (c) 2021 Linaro Limited
- *
- * This work is licensed under the terms of the GNU LGPL, version 2.1 or later.
- * See the COPYING file in the top-level directory.
- */
-
-#ifndef MIPS_HOST_SIGNAL_H
-#define MIPS_HOST_SIGNAL_H
-
-/* The third argument to a SA_SIGINFO handler is ucontext_t. */
-typedef ucontext_t host_sigcontext;
-
-static inline uintptr_t host_signal_pc(host_sigcontext *uc)
-{
- return uc->uc_mcontext.pc;
-}
-
-static inline void host_signal_set_pc(host_sigcontext *uc, uintptr_t pc)
-{
- uc->uc_mcontext.pc = pc;
-}
-
-static inline void *host_signal_mask(host_sigcontext *uc)
-{
- return &uc->uc_sigmask;
-}
-
-#if defined(__misp16) || defined(__mips_micromips)
-#error "Unsupported encoding"
-#endif
-
-static inline bool host_signal_write(siginfo_t *info, host_sigcontext *uc)
-{
- uint32_t insn = *(uint32_t *)host_signal_pc(uc);
-
- /* Detect all store instructions at program counter. */
- switch ((insn >> 26) & 077) {
- case 050: /* SB */
- case 051: /* SH */
- case 052: /* SWL */
- case 053: /* SW */
- case 054: /* SDL */
- case 055: /* SDR */
- case 056: /* SWR */
- case 070: /* SC */
- case 071: /* SWC1 */
- case 074: /* SCD */
- case 075: /* SDC1 */
- case 077: /* SD */
-#if !defined(__mips_isa_rev) || __mips_isa_rev < 6
- case 072: /* SWC2 */
- case 076: /* SDC2 */
-#endif
- return true;
- case 023: /* COP1X */
- /*
- * Required in all versions of MIPS64 since
- * MIPS64r1 and subsequent versions of MIPS32r2.
- */
- switch (insn & 077) {
- case 010: /* SWXC1 */
- case 011: /* SDXC1 */
- case 015: /* SUXC1 */
- return true;
- }
- break;
- }
- return false;
-}
-
-#endif
diff --git a/tcg/mips64/tcg-target-con-set.h b/tcg/mips64/tcg-target-con-set.h
deleted file mode 100644
index 5304691dc18..00000000000
--- a/tcg/mips64/tcg-target-con-set.h
+++ /dev/null
@@ -1,30 +0,0 @@
-/* SPDX-License-Identifier: MIT */
-/*
- * Define MIPS target-specific constraint sets.
- * Copyright (c) 2021 Linaro
- */
-
-/*
- * C_On_Im(...) defines a constraint set with <n> outputs and <m> inputs.
- * Each operand should be a sequence of constraint letters as defined by
- * tcg-target-con-str.h; the constraint combination is inclusive or.
- */
-C_O0_I1(r)
-C_O0_I2(r, rz)
-C_O0_I2(rz, r)
-C_O0_I3(rz, rz, r)
-C_O0_I4(r, r, rz, rz)
-C_O1_I1(r, r)
-C_O1_I2(r, 0, rz)
-C_O1_I2(r, r, r)
-C_O1_I2(r, r, ri)
-C_O1_I2(r, r, rI)
-C_O1_I2(r, r, rIK)
-C_O1_I2(r, r, rJ)
-C_O1_I2(r, r, rz)
-C_O1_I2(r, r, rzW)
-C_O1_I4(r, r, rz, rz, 0)
-C_O1_I4(r, r, rz, rz, rz)
-C_O1_I4(r, r, r, rz, rz)
-C_O2_I1(r, r, r)
-C_O2_I2(r, r, r, r)
diff --git a/tcg/mips64/tcg-target-con-str.h b/tcg/mips64/tcg-target-con-str.h
deleted file mode 100644
index db2b225e4a2..00000000000
--- a/tcg/mips64/tcg-target-con-str.h
+++ /dev/null
@@ -1,20 +0,0 @@
-/* SPDX-License-Identifier: MIT */
-/*
- * Define MIPS target-specific operand constraints.
- * Copyright (c) 2021 Linaro
- */
-
-/*
- * Define constraint letters for register sets:
- * REGS(letter, register_mask)
- */
-REGS('r', ALL_GENERAL_REGS)
-
-/*
- * Define constraint letters for constants:
- * CONST(letter, TCG_CT_CONST_* bit set)
- */
-CONST('I', TCG_CT_CONST_U16)
-CONST('J', TCG_CT_CONST_S16)
-CONST('K', TCG_CT_CONST_P2M1)
-CONST('W', TCG_CT_CONST_WSZ)
diff --git a/tcg/mips64/tcg-target-has.h b/tcg/mips64/tcg-target-has.h
deleted file mode 100644
index 88f0145efba..00000000000
--- a/tcg/mips64/tcg-target-has.h
+++ /dev/null
@@ -1,69 +0,0 @@
-/* SPDX-License-Identifier: MIT */
-/*
- * Define target-specific opcode support
- * Copyright (c) 2008-2009 Arnaud Patard <arnaud.patard@rtp-net.org>
- * Copyright (c) 2009 Aurelien Jarno <aurelien@aurel32.net>
- */
-
-#ifndef TCG_TARGET_HAS_H
-#define TCG_TARGET_HAS_H
-
-/* MOVN/MOVZ instructions detection */
-#if (defined(__mips_isa_rev) && (__mips_isa_rev >= 1)) || \
- defined(_MIPS_ARCH_LOONGSON2E) || defined(_MIPS_ARCH_LOONGSON2F) || \
- defined(_MIPS_ARCH_MIPS4)
-#define use_movnz_instructions 1
-#else
-extern bool use_movnz_instructions;
-#endif
-
-/* MIPS32 instruction set detection */
-#if defined(__mips_isa_rev) && (__mips_isa_rev >= 1)
-#define use_mips32_instructions 1
-#else
-extern bool use_mips32_instructions;
-#endif
-
-/* MIPS32R2 instruction set detection */
-#if defined(__mips_isa_rev) && (__mips_isa_rev >= 2)
-#define use_mips32r2_instructions 1
-#else
-extern bool use_mips32r2_instructions;
-#endif
-
-/* MIPS32R6 instruction set detection */
-#if defined(__mips_isa_rev) && (__mips_isa_rev >= 6)
-#define use_mips32r6_instructions 1
-#else
-#define use_mips32r6_instructions 0
-#endif
-
-/* optional instructions */
-#define TCG_TARGET_HAS_extr_i64_i32 1
-#define TCG_TARGET_HAS_ext32s_i64 1
-#define TCG_TARGET_HAS_ext32u_i64 1
-
-/* optional instructions detected at runtime */
-#define TCG_TARGET_HAS_qemu_ldst_i128 0
-#define TCG_TARGET_HAS_tst 0
-
-#define TCG_TARGET_extract_valid(type, ofs, len) use_mips32r2_instructions
-#define TCG_TARGET_deposit_valid(type, ofs, len) use_mips32r2_instructions
-
-static inline bool
-tcg_target_sextract_valid(TCGType type, unsigned ofs, unsigned len)
-{
- if (ofs == 0) {
- switch (len) {
- case 8:
- case 16:
- return use_mips32r2_instructions;
- case 32:
- return type == TCG_TYPE_I64;
- }
- }
- return false;
-}
-#define TCG_TARGET_sextract_valid tcg_target_sextract_valid
-
-#endif
diff --git a/tcg/mips64/tcg-target-mo.h b/tcg/mips64/tcg-target-mo.h
deleted file mode 100644
index 50cefc222d9..00000000000
--- a/tcg/mips64/tcg-target-mo.h
+++ /dev/null
@@ -1,13 +0,0 @@
-/* SPDX-License-Identifier: MIT */
-/*
- * Define target-specific memory model
- * Copyright (c) 2008-2009 Arnaud Patard <arnaud.patard@rtp-net.org>
- * Copyright (c) 2009 Aurelien Jarno <aurelien@aurel32.net>
- */
-
-#ifndef TCG_TARGET_MO_H
-#define TCG_TARGET_MO_H
-
-#define TCG_TARGET_DEFAULT_MO 0
-
-#endif
diff --git a/tcg/mips64/tcg-target.h b/tcg/mips64/tcg-target.h
deleted file mode 100644
index bd4ca5f852d..00000000000
--- a/tcg/mips64/tcg-target.h
+++ /dev/null
@@ -1,75 +0,0 @@
-/*
- * Tiny Code Generator for QEMU
- *
- * Copyright (c) 2008-2009 Arnaud Patard <arnaud.patard@rtp-net.org>
- * Copyright (c) 2009 Aurelien Jarno <aurelien@aurel32.net>
- * Based on i386/tcg-target.c - Copyright (c) 2008 Fabrice Bellard
- *
- * 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 MIPS_TCG_TARGET_H
-#define MIPS_TCG_TARGET_H
-
-#define TCG_TARGET_INSN_UNIT_SIZE 4
-#define TCG_TARGET_NB_REGS 32
-
-#define MAX_CODE_GEN_BUFFER_SIZE ((size_t)-1)
-
-typedef enum {
- TCG_REG_ZERO = 0,
- TCG_REG_AT,
- TCG_REG_V0,
- TCG_REG_V1,
- TCG_REG_A0,
- TCG_REG_A1,
- TCG_REG_A2,
- TCG_REG_A3,
- TCG_REG_T0,
- TCG_REG_T1,
- TCG_REG_T2,
- TCG_REG_T3,
- TCG_REG_T4,
- TCG_REG_T5,
- TCG_REG_T6,
- TCG_REG_T7,
- TCG_REG_S0,
- TCG_REG_S1,
- TCG_REG_S2,
- TCG_REG_S3,
- TCG_REG_S4,
- TCG_REG_S5,
- TCG_REG_S6,
- TCG_REG_S7,
- TCG_REG_T8,
- TCG_REG_T9,
- TCG_REG_K0,
- TCG_REG_K1,
- TCG_REG_GP,
- TCG_REG_SP,
- TCG_REG_S8,
- TCG_REG_RA,
-
- TCG_REG_CALL_STACK = TCG_REG_SP,
- TCG_AREG0 = TCG_REG_S8,
-} TCGReg;
-
-#define TCG_REG_ZERO TCG_REG_ZERO
-
-#endif
diff --git a/tcg/mips64/tcg-target-opc.h.inc b/tcg/mips64/tcg-target-opc.h.inc
deleted file mode 100644
index 84e777bfe53..00000000000
--- a/tcg/mips64/tcg-target-opc.h.inc
+++ /dev/null
@@ -1 +0,0 @@
-/* No target specific opcodes. */
diff --git a/linux-user/mmap.c b/linux-user/mmap.c
index b635b6a21c4..b4b7b3e5cc9 100644
--- a/linux-user/mmap.c
+++ b/linux-user/mmap.c
@@ -1351,7 +1351,7 @@ static inline abi_ulong target_shmlba(CPUArchState *cpu_env)
}
#endif
-#if defined(__mips__) || defined(__sparc__)
+#if defined(__sparc__)
#define HOST_FORCE_SHMLBA 1
#else
#define HOST_FORCE_SHMLBA 0
diff --git a/tcg/mips64/tcg-target.c.inc b/tcg/mips64/tcg-target.c.inc
deleted file mode 100644
index 60c703a0939..00000000000
--- a/tcg/mips64/tcg-target.c.inc
+++ /dev/null
@@ -1,2605 +0,0 @@
-/*
- * Tiny Code Generator for QEMU
- *
- * Copyright (c) 2008-2009 Arnaud Patard <arnaud.patard@rtp-net.org>
- * Copyright (c) 2009 Aurelien Jarno <aurelien@aurel32.net>
- * Based on i386/tcg-target.c - Copyright (c) 2008 Fabrice Bellard
- *
- * 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.
- */
-
-/* used for function call generation */
-#define TCG_TARGET_STACK_ALIGN 16
-#define TCG_TARGET_CALL_STACK_OFFSET 0
-#define TCG_TARGET_CALL_ARG_I32 TCG_CALL_ARG_NORMAL
-#define TCG_TARGET_CALL_ARG_I64 TCG_CALL_ARG_NORMAL
-#define TCG_TARGET_CALL_RET_I128 TCG_CALL_RET_NORMAL
-#define TCG_TARGET_CALL_ARG_I128 TCG_CALL_ARG_EVEN
-
-#ifdef CONFIG_DEBUG_TCG
-static const char * const tcg_target_reg_names[TCG_TARGET_NB_REGS] = {
- "zero",
- "at",
- "v0",
- "v1",
- "a0",
- "a1",
- "a2",
- "a3",
- "t0",
- "t1",
- "t2",
- "t3",
- "t4",
- "t5",
- "t6",
- "t7",
- "s0",
- "s1",
- "s2",
- "s3",
- "s4",
- "s5",
- "s6",
- "s7",
- "t8",
- "t9",
- "k0",
- "k1",
- "gp",
- "sp",
- "s8",
- "ra",
-};
-#endif
-
-#define TCG_TMP0 TCG_REG_AT
-#define TCG_TMP1 TCG_REG_T9
-#define TCG_TMP2 TCG_REG_T8
-#define TCG_TMP3 TCG_REG_T7
-
-#define TCG_GUEST_BASE_REG TCG_REG_S7
-#define TCG_REG_TB TCG_REG_S6
-
-/* check if we really need so many registers :P */
-static const int tcg_target_reg_alloc_order[] = {
- /* Call saved registers. */
- TCG_REG_S0,
- TCG_REG_S1,
- TCG_REG_S2,
- TCG_REG_S3,
- TCG_REG_S4,
- TCG_REG_S5,
- TCG_REG_S6,
- TCG_REG_S7,
- TCG_REG_S8,
-
- /* Call clobbered registers. */
- TCG_REG_T4,
- TCG_REG_T5,
- TCG_REG_T6,
- TCG_REG_T7,
- TCG_REG_T8,
- TCG_REG_T9,
- TCG_REG_V1,
- TCG_REG_V0,
-
- /* Argument registers, opposite order of allocation. */
- TCG_REG_T3,
- TCG_REG_T2,
- TCG_REG_T1,
- TCG_REG_T0,
- TCG_REG_A3,
- TCG_REG_A2,
- TCG_REG_A1,
- TCG_REG_A0,
-};
-
-static const TCGReg tcg_target_call_iarg_regs[] = {
- TCG_REG_A0,
- TCG_REG_A1,
- TCG_REG_A2,
- TCG_REG_A3,
- TCG_REG_T0,
- TCG_REG_T1,
- TCG_REG_T2,
- TCG_REG_T3,
-};
-
-static TCGReg tcg_target_call_oarg_reg(TCGCallReturnKind kind, int slot)
-{
- tcg_debug_assert(kind == TCG_CALL_RET_NORMAL);
- tcg_debug_assert(slot >= 0 && slot <= 1);
- return TCG_REG_V0 + slot;
-}
-
-static const tcg_insn_unit *tb_ret_addr;
-static const tcg_insn_unit *bswap32_addr;
-static const tcg_insn_unit *bswap32u_addr;
-static const tcg_insn_unit *bswap64_addr;
-
-static bool reloc_pc16(tcg_insn_unit *src_rw, const tcg_insn_unit *target)
-{
- /* Let the compiler perform the right-shift as part of the arithmetic. */
- const tcg_insn_unit *src_rx = tcg_splitwx_to_rx(src_rw);
- ptrdiff_t disp = target - (src_rx + 1);
- if (disp == (int16_t)disp) {
- *src_rw = deposit32(*src_rw, 0, 16, disp);
- return true;
- }
- return false;
-}
-
-static bool patch_reloc(tcg_insn_unit *code_ptr, int type,
- intptr_t value, intptr_t addend)
-{
- value += addend;
- switch (type) {
- case R_MIPS_PC16:
- return reloc_pc16(code_ptr, (const tcg_insn_unit *)value);
- case R_MIPS_16:
- if (value != (int16_t)value) {
- return false;
- }
- *code_ptr = deposit32(*code_ptr, 0, 16, value);
- return true;
- }
- g_assert_not_reached();
-}
-
-#define TCG_CT_CONST_U16 0x100 /* Unsigned 16-bit: 0 - 0xffff. */
-#define TCG_CT_CONST_S16 0x200 /* Signed 16-bit: -32768 - 32767 */
-#define TCG_CT_CONST_P2M1 0x400 /* Power of 2 minus 1. */
-#define TCG_CT_CONST_WSZ 0x800 /* word size */
-
-#define ALL_GENERAL_REGS 0xffffffffu
-
-static bool is_p2m1(tcg_target_long val)
-{
- return val && ((val + 1) & val) == 0;
-}
-
-/* test if a constant matches the constraint */
-static bool tcg_target_const_match(int64_t val, int ct,
- TCGType type, TCGCond cond, int vece)
-{
- if (ct & TCG_CT_CONST) {
- return 1;
- } else if ((ct & TCG_CT_CONST_U16) && val == (uint16_t)val) {
- return 1;
- } else if ((ct & TCG_CT_CONST_S16) && val == (int16_t)val) {
- return 1;
- } else if ((ct & TCG_CT_CONST_P2M1)
- && use_mips32r2_instructions && is_p2m1(val)) {
- return 1;
- } else if ((ct & TCG_CT_CONST_WSZ)
- && val == (type == TCG_TYPE_I32 ? 32 : 64)) {
- return 1;
- }
- return 0;
-}
-
-/* instruction opcodes */
-typedef enum {
- OPC_J = 002 << 26,
- OPC_JAL = 003 << 26,
- OPC_BEQ = 004 << 26,
- OPC_BNE = 005 << 26,
- OPC_BLEZ = 006 << 26,
- OPC_BGTZ = 007 << 26,
- OPC_ADDIU = 011 << 26,
- OPC_SLTI = 012 << 26,
- OPC_SLTIU = 013 << 26,
- OPC_ANDI = 014 << 26,
- OPC_ORI = 015 << 26,
- OPC_XORI = 016 << 26,
- OPC_LUI = 017 << 26,
- OPC_BNEL = 025 << 26,
- OPC_BNEZALC_R6 = 030 << 26,
- OPC_DADDIU = 031 << 26,
- OPC_LDL = 032 << 26,
- OPC_LDR = 033 << 26,
- OPC_LB = 040 << 26,
- OPC_LH = 041 << 26,
- OPC_LWL = 042 << 26,
- OPC_LW = 043 << 26,
- OPC_LBU = 044 << 26,
- OPC_LHU = 045 << 26,
- OPC_LWR = 046 << 26,
- OPC_LWU = 047 << 26,
- OPC_SB = 050 << 26,
- OPC_SH = 051 << 26,
- OPC_SWL = 052 << 26,
- OPC_SW = 053 << 26,
- OPC_SDL = 054 << 26,
- OPC_SDR = 055 << 26,
- OPC_SWR = 056 << 26,
- OPC_LD = 067 << 26,
- OPC_SD = 077 << 26,
-
- OPC_SPECIAL = 000 << 26,
- OPC_SLL = OPC_SPECIAL | 000,
- OPC_SRL = OPC_SPECIAL | 002,
- OPC_ROTR = OPC_SPECIAL | 002 | (1 << 21),
- OPC_SRA = OPC_SPECIAL | 003,
- OPC_SLLV = OPC_SPECIAL | 004,
- OPC_SRLV = OPC_SPECIAL | 006,
- OPC_ROTRV = OPC_SPECIAL | 006 | 0100,
- OPC_SRAV = OPC_SPECIAL | 007,
- OPC_JR_R5 = OPC_SPECIAL | 010,
- OPC_JALR = OPC_SPECIAL | 011,
- OPC_MOVZ = OPC_SPECIAL | 012,
- OPC_MOVN = OPC_SPECIAL | 013,
- OPC_SYNC = OPC_SPECIAL | 017,
- OPC_MFHI = OPC_SPECIAL | 020,
- OPC_MFLO = OPC_SPECIAL | 022,
- OPC_DSLLV = OPC_SPECIAL | 024,
- OPC_DSRLV = OPC_SPECIAL | 026,
- OPC_DROTRV = OPC_SPECIAL | 026 | 0100,
- OPC_DSRAV = OPC_SPECIAL | 027,
- OPC_MULT = OPC_SPECIAL | 030,
- OPC_MUL_R6 = OPC_SPECIAL | 030 | 0200,
- OPC_MUH = OPC_SPECIAL | 030 | 0300,
- OPC_MULTU = OPC_SPECIAL | 031,
- OPC_MULU = OPC_SPECIAL | 031 | 0200,
- OPC_MUHU = OPC_SPECIAL | 031 | 0300,
- OPC_DIV = OPC_SPECIAL | 032,
- OPC_DIV_R6 = OPC_SPECIAL | 032 | 0200,
- OPC_MOD = OPC_SPECIAL | 032 | 0300,
- OPC_DIVU = OPC_SPECIAL | 033,
- OPC_DIVU_R6 = OPC_SPECIAL | 033 | 0200,
- OPC_MODU = OPC_SPECIAL | 033 | 0300,
- OPC_DMULT = OPC_SPECIAL | 034,
- OPC_DMUL = OPC_SPECIAL | 034 | 0200,
- OPC_DMUH = OPC_SPECIAL | 034 | 0300,
- OPC_DMULTU = OPC_SPECIAL | 035,
- OPC_DMULU = OPC_SPECIAL | 035 | 0200,
- OPC_DMUHU = OPC_SPECIAL | 035 | 0300,
- OPC_DDIV = OPC_SPECIAL | 036,
- OPC_DDIV_R6 = OPC_SPECIAL | 036 | 0200,
- OPC_DMOD = OPC_SPECIAL | 036 | 0300,
- OPC_DDIVU = OPC_SPECIAL | 037,
- OPC_DDIVU_R6 = OPC_SPECIAL | 037 | 0200,
- OPC_DMODU = OPC_SPECIAL | 037 | 0300,
- OPC_ADDU = OPC_SPECIAL | 041,
- OPC_SUBU = OPC_SPECIAL | 043,
- OPC_AND = OPC_SPECIAL | 044,
- OPC_OR = OPC_SPECIAL | 045,
- OPC_XOR = OPC_SPECIAL | 046,
- OPC_NOR = OPC_SPECIAL | 047,
- OPC_SLT = OPC_SPECIAL | 052,
- OPC_SLTU = OPC_SPECIAL | 053,
- OPC_DADDU = OPC_SPECIAL | 055,
- OPC_DSUBU = OPC_SPECIAL | 057,
- OPC_SELEQZ = OPC_SPECIAL | 065,
- OPC_SELNEZ = OPC_SPECIAL | 067,
- OPC_DSLL = OPC_SPECIAL | 070,
- OPC_DSRL = OPC_SPECIAL | 072,
- OPC_DROTR = OPC_SPECIAL | 072 | (1 << 21),
- OPC_DSRA = OPC_SPECIAL | 073,
- OPC_DSLL32 = OPC_SPECIAL | 074,
- OPC_DSRL32 = OPC_SPECIAL | 076,
- OPC_DROTR32 = OPC_SPECIAL | 076 | (1 << 21),
- OPC_DSRA32 = OPC_SPECIAL | 077,
- OPC_CLZ_R6 = OPC_SPECIAL | 0120,
- OPC_DCLZ_R6 = OPC_SPECIAL | 0122,
-
- OPC_REGIMM = 001 << 26,
- OPC_BLTZ = OPC_REGIMM | (000 << 16),
- OPC_BGEZ = OPC_REGIMM | (001 << 16),
-
- OPC_SPECIAL2 = 034 << 26,
- OPC_MUL_R5 = OPC_SPECIAL2 | 002,
- OPC_CLZ = OPC_SPECIAL2 | 040,
- OPC_DCLZ = OPC_SPECIAL2 | 044,
-
- OPC_SPECIAL3 = 037 << 26,
- OPC_EXT = OPC_SPECIAL3 | 000,
- OPC_DEXTM = OPC_SPECIAL3 | 001,
- OPC_DEXTU = OPC_SPECIAL3 | 002,
- OPC_DEXT = OPC_SPECIAL3 | 003,
- OPC_INS = OPC_SPECIAL3 | 004,
- OPC_DINSM = OPC_SPECIAL3 | 005,
- OPC_DINSU = OPC_SPECIAL3 | 006,
- OPC_DINS = OPC_SPECIAL3 | 007,
- OPC_WSBH = OPC_SPECIAL3 | 00240,
- OPC_DSBH = OPC_SPECIAL3 | 00244,
- OPC_DSHD = OPC_SPECIAL3 | 00544,
- OPC_SEB = OPC_SPECIAL3 | 02040,
- OPC_SEH = OPC_SPECIAL3 | 03040,
-
- /* MIPS r6 doesn't have JR, JALR should be used instead */
- OPC_JR = use_mips32r6_instructions ? OPC_JALR : OPC_JR_R5,
-
- /*
- * MIPS r6 replaces MUL with an alternative encoding which is
- * backwards-compatible at the assembly level.
- */
- OPC_MUL = use_mips32r6_instructions ? OPC_MUL_R6 : OPC_MUL_R5,
-
- /* MIPS r6 introduced names for weaker variants of SYNC. These are
- backward compatible to previous architecture revisions. */
- OPC_SYNC_WMB = OPC_SYNC | 0x04 << 6,
- OPC_SYNC_MB = OPC_SYNC | 0x10 << 6,
- OPC_SYNC_ACQUIRE = OPC_SYNC | 0x11 << 6,
- OPC_SYNC_RELEASE = OPC_SYNC | 0x12 << 6,
- OPC_SYNC_RMB = OPC_SYNC | 0x13 << 6,
-} MIPSInsn;
-
-/*
- * Type reg
- */
-static void tcg_out_opc_reg(TCGContext *s, MIPSInsn opc,
- TCGReg rd, TCGReg rs, TCGReg rt)
-{
- int32_t inst;
-
- inst = opc;
- inst |= (rs & 0x1F) << 21;
- inst |= (rt & 0x1F) << 16;
- inst |= (rd & 0x1F) << 11;
- tcg_out32(s, inst);
-}
-
-/*
- * Type immediate
- */
-static void tcg_out_opc_imm(TCGContext *s, MIPSInsn opc,
- TCGReg rt, TCGReg rs, TCGArg imm)
-{
- int32_t inst;
-
- inst = opc;
- inst |= (rs & 0x1F) << 21;
- inst |= (rt & 0x1F) << 16;
- inst |= (imm & 0xffff);
- tcg_out32(s, inst);
-}
-
-/*
- * Type bitfield
- */
-static void tcg_out_opc_bf(TCGContext *s, MIPSInsn opc, TCGReg rt,
- TCGReg rs, int msb, int lsb)
-{
- int32_t inst;
-
- inst = opc;
- inst |= (rs & 0x1F) << 21;
- inst |= (rt & 0x1F) << 16;
- inst |= (msb & 0x1F) << 11;
- inst |= (lsb & 0x1F) << 6;
- tcg_out32(s, inst);
-}
-
-static void tcg_out_opc_bf64(TCGContext *s, MIPSInsn opc, MIPSInsn opm,
- MIPSInsn oph, TCGReg rt, TCGReg rs,
- int msb, int lsb)
-{
- if (lsb >= 32) {
- opc = oph;
- msb -= 32;
- lsb -= 32;
- } else if (msb >= 32) {
- opc = opm;
- msb -= 32;
- }
- tcg_out_opc_bf(s, opc, rt, rs, msb, lsb);
-}
-
-/*
- * Type branch
- */
-static void tcg_out_opc_br(TCGContext *s, MIPSInsn opc, TCGReg rt, TCGReg rs)
-{
- tcg_out_opc_imm(s, opc, rt, rs, 0);
-}
-
-/*
- * Type sa
- */
-static void tcg_out_opc_sa(TCGContext *s, MIPSInsn opc,
- TCGReg rd, TCGReg rt, TCGArg sa)
-{
- int32_t inst;
-
- inst = opc;
- inst |= (rt & 0x1F) << 16;
- inst |= (rd & 0x1F) << 11;
- inst |= (sa & 0x1F) << 6;
- tcg_out32(s, inst);
-
-}
-
-static void tcg_out_opc_sa64(TCGContext *s, MIPSInsn opc1, MIPSInsn opc2,
- TCGReg rd, TCGReg rt, TCGArg sa)
-{
- int32_t inst;
-
- inst = (sa & 32 ? opc2 : opc1);
- inst |= (rt & 0x1F) << 16;
- inst |= (rd & 0x1F) << 11;
- inst |= (sa & 0x1F) << 6;
- tcg_out32(s, inst);
-}
-
-/*
- * Type jump.
- * Returns true if the branch was in range and the insn was emitted.
- */
-static bool tcg_out_opc_jmp(TCGContext *s, MIPSInsn opc, const void *target)
-{
- uintptr_t dest = (uintptr_t)target;
- uintptr_t from = (uintptr_t)tcg_splitwx_to_rx(s->code_ptr) + 4;
- int32_t inst;
-
- /* The pc-region branch happens within the 256MB region of
- the delay slot (thus the +4). */
- if ((from ^ dest) & -(1 << 28)) {
- return false;
- }
- tcg_debug_assert((dest & 3) == 0);
-
- inst = opc;
- inst |= (dest >> 2) & 0x3ffffff;
- tcg_out32(s, inst);
- return true;
-}
-
-static void tcg_out_nop(TCGContext *s)
-{
- tcg_out32(s, 0);
-}
-
-static void tcg_out_nop_fill(tcg_insn_unit *p, int count)
-{
- memset(p, 0, count * sizeof(tcg_insn_unit));
-}
-
-static void tcg_out_dsll(TCGContext *s, TCGReg rd, TCGReg rt, TCGArg sa)
-{
- tcg_out_opc_sa64(s, OPC_DSLL, OPC_DSLL32, rd, rt, sa);
-}
-
-static void tcg_out_dsrl(TCGContext *s, TCGReg rd, TCGReg rt, TCGArg sa)
-{
- tcg_out_opc_sa64(s, OPC_DSRL, OPC_DSRL32, rd, rt, sa);
-}
-
-static void tcg_out_dsra(TCGContext *s, TCGReg rd, TCGReg rt, TCGArg sa)
-{
- tcg_out_opc_sa64(s, OPC_DSRA, OPC_DSRA32, rd, rt, sa);
-}
-
-static bool tcg_out_mov(TCGContext *s, TCGType type, TCGReg ret, TCGReg arg)
-{
- /* Simple reg-reg move, optimising out the 'do nothing' case */
- if (ret != arg) {
- tcg_out_opc_reg(s, OPC_OR, ret, arg, TCG_REG_ZERO);
- }
- return true;
-}
-
-static bool tcg_out_movi_one(TCGContext *s, TCGReg ret, tcg_target_long arg)
-{
- if (arg == (int16_t)arg) {
- tcg_out_opc_imm(s, OPC_ADDIU, ret, TCG_REG_ZERO, arg);
- return true;
- }
- if (arg == (uint16_t)arg) {
- tcg_out_opc_imm(s, OPC_ORI, ret, TCG_REG_ZERO, arg);
- return true;
- }
- if (arg == (int32_t)arg && (arg & 0xffff) == 0) {
- tcg_out_opc_imm(s, OPC_LUI, ret, TCG_REG_ZERO, arg >> 16);
- return true;
- }
- return false;
-}
-
-static bool tcg_out_movi_two(TCGContext *s, TCGReg ret, tcg_target_long arg)
-{
- /*
- * All signed 32-bit constants are loadable with two immediates,
- * and everything else requires more work.
- */
- if (arg == (int32_t)arg) {
- if (!tcg_out_movi_one(s, ret, arg)) {
- tcg_out_opc_imm(s, OPC_LUI, ret, TCG_REG_ZERO, arg >> 16);
- tcg_out_opc_imm(s, OPC_ORI, ret, ret, arg & 0xffff);
- }
- return true;
- }
- return false;
-}
-
-static void tcg_out_movi_pool(TCGContext *s, TCGReg ret,
- tcg_target_long arg, TCGReg tbreg)
-{
- new_pool_label(s, arg, R_MIPS_16, s->code_ptr, tcg_tbrel_diff(s, NULL));
- tcg_out_opc_imm(s, OPC_LD, ret, tbreg, 0);
-}
-
-static void tcg_out_movi_int(TCGContext *s, TCGType type, TCGReg ret,
- tcg_target_long arg, TCGReg tbreg)
-{
- tcg_target_long tmp;
- int sh, lo;
-
- if (type == TCG_TYPE_I32) {
- arg = (int32_t)arg;
- }
-
- /* Load all 32-bit constants. */
- if (tcg_out_movi_two(s, ret, arg)) {
- return;
- }
-
- /* Load addresses within 2GB of TB with 1 or 3 insns. */
- tmp = tcg_tbrel_diff(s, (void *)arg);
- if (tmp == (int16_t)tmp) {
- tcg_out_opc_imm(s, OPC_DADDIU, ret, tbreg, tmp);
- return;
- }
- if (tcg_out_movi_two(s, ret, tmp)) {
- tcg_out_opc_reg(s, OPC_DADDU, ret, ret, tbreg);
- return;
- }
-
- /*
- * Load bitmasks with a right-shift. This is good for things
- * like 0x0fff_ffff_ffff_fff0: ADDUI r,0,0xff00 + DSRL r,r,4.
- * or similarly using LUI. For this to work, bit 31 must be set.
- */
- if (arg > 0 && (int32_t)arg < 0) {
- sh = clz64(arg);
- if (tcg_out_movi_one(s, ret, arg << sh)) {
- tcg_out_dsrl(s, ret, ret, sh);
- return;
- }
- }
-
- /*
- * Load slightly larger constants using left-shift.
- * Limit this sequence to 3 insns to avoid too much expansion.
- */
- sh = ctz64(arg);
- if (sh && tcg_out_movi_two(s, ret, arg >> sh)) {
- tcg_out_dsll(s, ret, ret, sh);
- return;
- }
-
- /*
- * Load slightly larger constants using left-shift and add/or.
- * Prefer addi with a negative immediate when that would produce
- * a larger shift. For this to work, bits 15 and 16 must be set.
- */
- lo = arg & 0xffff;
- if (lo) {
- if ((arg & 0x18000) == 0x18000) {
- lo = (int16_t)arg;
- }
- tmp = arg - lo;
- sh = ctz64(tmp);
- tmp >>= sh;
- if (tcg_out_movi_one(s, ret, tmp)) {
- tcg_out_dsll(s, ret, ret, sh);
- tcg_out_opc_imm(s, lo < 0 ? OPC_DADDIU : OPC_ORI, ret, ret, lo);
- return;
- }
- }
-
- /* Otherwise, put 64-bit constants into the constant pool. */
- tcg_out_movi_pool(s, ret, arg, tbreg);
-}
-
-static void tcg_out_movi(TCGContext *s, TCGType type,
- TCGReg ret, tcg_target_long arg)
-{
- tcg_out_movi_int(s, type, ret, arg, TCG_REG_TB);
-}
-
-static void tcg_out_ext8s(TCGContext *s, TCGType type, TCGReg rd, TCGReg rs)
-{
- tcg_debug_assert(use_mips32r2_instructions);
- tcg_out_opc_reg(s, OPC_SEB, rd, TCG_REG_ZERO, rs);
-}
-
-static void tcg_out_ext8u(TCGContext *s, TCGReg rd, TCGReg rs)
-{
- tcg_out_opc_imm(s, OPC_ANDI, rd, rs, 0xff);
-}
-
-static void tcg_out_ext16s(TCGContext *s, TCGType type, TCGReg rd, TCGReg rs)
-{
- tcg_debug_assert(use_mips32r2_instructions);
- tcg_out_opc_reg(s, OPC_SEH, rd, TCG_REG_ZERO, rs);
-}
-
-static void tcg_out_ext16u(TCGContext *s, TCGReg rd, TCGReg rs)
-{
- tcg_out_opc_imm(s, OPC_ANDI, rd, rs, 0xffff);
-}
-
-static void tcg_out_ext32s(TCGContext *s, TCGReg rd, TCGReg rs)
-{
- tcg_out_opc_sa(s, OPC_SLL, rd, rs, 0);
-}
-
-static void tcg_out_exts_i32_i64(TCGContext *s, TCGReg rd, TCGReg rs)
-{
- if (rd != rs) {
- tcg_out_ext32s(s, rd, rs);
- }
-}
-
-static void tcg_out_extu_i32_i64(TCGContext *s, TCGReg rd, TCGReg rs)
-{
- tcg_out_ext32u(s, rd, rs);
-}
-
-static void tcg_out_extrl_i64_i32(TCGContext *s, TCGReg rd, TCGReg rs)
-{
- tcg_out_ext32s(s, rd, rs);
-}
-
-static bool tcg_out_xchg(TCGContext *s, TCGType type, TCGReg r1, TCGReg r2)
-{
- return false;
-}
-
-static void tcg_out_addi_ptr(TCGContext *s, TCGReg rd, TCGReg rs,
- tcg_target_long imm)
-{
- /* This function is only used for passing structs by reference. */
- g_assert_not_reached();
-}
-
-static void tcg_out_bswap_subr(TCGContext *s, const tcg_insn_unit *sub)
-{
- if (!tcg_out_opc_jmp(s, OPC_JAL, sub)) {
- tcg_out_movi(s, TCG_TYPE_PTR, TCG_TMP1, (uintptr_t)sub);
- tcg_out_opc_reg(s, OPC_JALR, TCG_REG_RA, TCG_TMP1, 0);
- }
-}
-
-static void tcg_out_ext32u(TCGContext *s, TCGReg ret, TCGReg arg)
-{
- if (use_mips32r2_instructions) {
- tcg_out_opc_bf(s, OPC_DEXT, ret, arg, 31, 0);
- } else {
- tcg_out_dsll(s, ret, arg, 32);
- tcg_out_dsrl(s, ret, ret, 32);
- }
-}
-
-static void tcg_out_ldst(TCGContext *s, MIPSInsn opc, TCGReg data,
- TCGReg addr, intptr_t ofs)
-{
- int16_t lo = ofs;
- if (ofs != lo) {
- tcg_out_movi(s, TCG_TYPE_PTR, TCG_TMP0, ofs - lo);
- if (addr != TCG_REG_ZERO) {
- tcg_out_opc_reg(s, OPC_DADDU, TCG_TMP0, TCG_TMP0, addr);
- }
- addr = TCG_TMP0;
- }
- tcg_out_opc_imm(s, opc, data, addr, lo);
-}
-
-static void tcg_out_ld(TCGContext *s, TCGType type, TCGReg arg,
- TCGReg arg1, intptr_t arg2)
-{
- MIPSInsn opc = type == TCG_TYPE_I32 ? OPC_LW : OPC_LD;
- tcg_out_ldst(s, opc, arg, arg1, arg2);
-}
-
-static void tcg_out_st(TCGContext *s, TCGType type, TCGReg arg,
- TCGReg arg1, intptr_t arg2)
-{
- MIPSInsn opc = type == TCG_TYPE_I32 ? OPC_SW : OPC_SD;
- tcg_out_ldst(s, opc, arg, arg1, arg2);
-}
-
-static bool tcg_out_sti(TCGContext *s, TCGType type, TCGArg val,
- TCGReg base, intptr_t ofs)
-{
- if (val == 0) {
- tcg_out_st(s, type, TCG_REG_ZERO, base, ofs);
- return true;
- }
- return false;
-}
-
-#define SETCOND_INV TCG_TARGET_NB_REGS
-#define SETCOND_NEZ (SETCOND_INV << 1)
-#define SETCOND_FLAGS (SETCOND_INV | SETCOND_NEZ)
-
-static int tcg_out_setcond_int(TCGContext *s, TCGCond cond, TCGReg ret,
- TCGReg arg1, TCGReg arg2)
-{
- int flags = 0;
-
- switch (cond) {
- case TCG_COND_EQ: /* -> NE */
- case TCG_COND_GE: /* -> LT */
- case TCG_COND_GEU: /* -> LTU */
- case TCG_COND_LE: /* -> GT */
- case TCG_COND_LEU: /* -> GTU */
- cond = tcg_invert_cond(cond);
- flags ^= SETCOND_INV;
- break;
- default:
- break;
- }
-
- switch (cond) {
- case TCG_COND_NE:
- flags |= SETCOND_NEZ;
- if (arg2 == 0) {
- return arg1 | flags;
- }
- tcg_out_opc_reg(s, OPC_XOR, ret, arg1, arg2);
- break;
- case TCG_COND_LT:
- tcg_out_opc_reg(s, OPC_SLT, ret, arg1, arg2);
- break;
- case TCG_COND_LTU:
- tcg_out_opc_reg(s, OPC_SLTU, ret, arg1, arg2);
- break;
- case TCG_COND_GT:
- tcg_out_opc_reg(s, OPC_SLT, ret, arg2, arg1);
- break;
- case TCG_COND_GTU:
- tcg_out_opc_reg(s, OPC_SLTU, ret, arg2, arg1);
- break;
- default:
- g_assert_not_reached();
- }
- return ret | flags;
-}
-
-static void tcg_out_setcond_end(TCGContext *s, TCGReg ret, int tmpflags)
-{
- if (tmpflags != ret) {
- TCGReg tmp = tmpflags & ~SETCOND_FLAGS;
-
- switch (tmpflags & SETCOND_FLAGS) {
- case SETCOND_INV:
- /* Intermediate result is boolean: simply invert. */
- tcg_out_opc_imm(s, OPC_XORI, ret, tmp, 1);
- break;
- case SETCOND_NEZ:
- /* Intermediate result is zero/non-zero: test != 0. */
- tcg_out_opc_reg(s, OPC_SLTU, ret, TCG_REG_ZERO, tmp);
- break;
- case SETCOND_NEZ | SETCOND_INV:
- /* Intermediate result is zero/non-zero: test == 0. */
- tcg_out_opc_imm(s, OPC_SLTIU, ret, tmp, 1);
- break;
- default:
- g_assert_not_reached();
- }
- }
-}
-
-static void tgen_setcond(TCGContext *s, TCGType type, TCGCond cond,
- TCGReg ret, TCGReg arg1, TCGReg arg2)
-{
- int tmpflags = tcg_out_setcond_int(s, cond, ret, arg1, arg2);
- tcg_out_setcond_end(s, ret, tmpflags);
-}
-
-static const TCGOutOpSetcond outop_setcond = {
- .base.static_constraint = C_O1_I2(r, r, rz),
- .out_rrr = tgen_setcond,
-};
-
-static void tgen_negsetcond(TCGContext *s, TCGType type, TCGCond cond,
- TCGReg ret, TCGReg arg1, TCGReg arg2)
-{
- int tmpflags = tcg_out_setcond_int(s, cond, ret, arg1, arg2);
- TCGReg tmp = tmpflags & ~SETCOND_FLAGS;
-
- /* If intermediate result is zero/non-zero: test != 0. */
- if (tmpflags & SETCOND_NEZ) {
- tcg_out_opc_reg(s, OPC_SLTU, ret, TCG_REG_ZERO, tmp);
- tmp = ret;
- }
- /* Produce the 0/-1 result. */
- if (tmpflags & SETCOND_INV) {
- tcg_out_opc_imm(s, OPC_ADDIU, ret, tmp, -1);
- } else {
- tcg_out_opc_reg(s, OPC_SUBU, ret, TCG_REG_ZERO, tmp);
- }
-}
-
-static const TCGOutOpSetcond outop_negsetcond = {
- .base.static_constraint = C_O1_I2(r, r, rz),
- .out_rrr = tgen_negsetcond,
-};
-
-static void tgen_brcond(TCGContext *s, TCGType type, TCGCond cond,
- TCGReg arg1, TCGReg arg2, TCGLabel *l)
-{
- static const MIPSInsn b_zero[16] = {
- [TCG_COND_LT] = OPC_BLTZ,
- [TCG_COND_GT] = OPC_BGTZ,
- [TCG_COND_LE] = OPC_BLEZ,
- [TCG_COND_GE] = OPC_BGEZ,
- };
-
- MIPSInsn b_opc = 0;
-
- switch (cond) {
- case TCG_COND_EQ:
- b_opc = OPC_BEQ;
- break;
- case TCG_COND_NE:
- b_opc = OPC_BNE;
- break;
- case TCG_COND_LT:
- case TCG_COND_GT:
- case TCG_COND_LE:
- case TCG_COND_GE:
- if (arg2 == 0) {
- b_opc = b_zero[cond];
- arg2 = arg1;
- arg1 = 0;
- }
- break;
- default:
- break;
- }
-
- if (b_opc == 0) {
- int tmpflags = tcg_out_setcond_int(s, cond, TCG_TMP0, arg1, arg2);
-
- arg2 = TCG_REG_ZERO;
- arg1 = tmpflags & ~SETCOND_FLAGS;
- b_opc = tmpflags & SETCOND_INV ? OPC_BEQ : OPC_BNE;
- }
-
- tcg_out_reloc(s, s->code_ptr, R_MIPS_PC16, l, 0);
- tcg_out_opc_br(s, b_opc, arg1, arg2);
- tcg_out_nop(s);
-}
-
-static const TCGOutOpBrcond outop_brcond = {
- .base.static_constraint = C_O0_I2(r, rz),
- .out_rr = tgen_brcond,
-};
-
-void tcg_out_br(TCGContext *s, TCGLabel *l)
-{
- tgen_brcond(s, TCG_TYPE_I32, TCG_COND_EQ, TCG_REG_ZERO, TCG_REG_ZERO, l);
-}
-
-static void tgen_movcond(TCGContext *s, TCGType type, TCGCond cond,
- TCGReg ret, TCGReg c1, TCGArg c2, bool const_c2,
- TCGArg v1, bool const_v1, TCGArg v2, bool const_v2)
-{
- int tmpflags;
- bool eqz;
-
- /* If one of the values is zero, put it last to match SEL*Z instructions */
- if (use_mips32r6_instructions && v1 == 0) {
- v1 = v2;
- v2 = 0;
- cond = tcg_invert_cond(cond);
- }
-
- tmpflags = tcg_out_setcond_int(s, cond, TCG_TMP0, c1, c2);
- c1 = tmpflags & ~SETCOND_FLAGS;
- eqz = tmpflags & SETCOND_INV;
-
- if (use_mips32r6_instructions) {
- MIPSInsn m_opc_t = eqz ? OPC_SELEQZ : OPC_SELNEZ;
- MIPSInsn m_opc_f = eqz ? OPC_SELNEZ : OPC_SELEQZ;
-
- if (v2 != 0) {
- tcg_out_opc_reg(s, m_opc_f, TCG_TMP1, v2, c1);
- }
- tcg_out_opc_reg(s, m_opc_t, ret, v1, c1);
- if (v2 != 0) {
- tcg_out_opc_reg(s, OPC_OR, ret, ret, TCG_TMP1);
- }
- return;
- }
-
- /* This should be guaranteed via constraints */
- tcg_debug_assert(v2 == ret);
-
- if (use_movnz_instructions) {
- MIPSInsn m_opc = eqz ? OPC_MOVZ : OPC_MOVN;
- tcg_out_opc_reg(s, m_opc, ret, v1, c1);
- } else {
- /* Invert the condition in order to branch over the move. */
- MIPSInsn b_opc = eqz ? OPC_BNE : OPC_BEQ;
- tcg_out_opc_imm(s, b_opc, c1, TCG_REG_ZERO, 2);
- tcg_out_nop(s);
- /* Open-code tcg_out_mov, without the nop-move check. */
- tcg_out_opc_reg(s, OPC_OR, ret, v1, TCG_REG_ZERO);
- }
-}
-
-static const TCGOutOpMovcond outop_movcond = {
- .base.static_constraint = (use_mips32r6_instructions
- ? C_O1_I4(r, r, rz, rz, rz)
- : C_O1_I4(r, r, rz, rz, 0)),
- .out = tgen_movcond,
-};
-
-static void tcg_out_call_int(TCGContext *s, const tcg_insn_unit *arg, bool tail)
-{
- /*
- * Note that __mips_abicalls requires the called function's address
- * to be loaded into $25 (t9), even if a direct branch is in range.
- *
- * We can re-use helper addresses often; always drop the pointer
- * into the constant pool.
- */
- tcg_out_movi_pool(s, TCG_REG_T9, (uintptr_t)arg, TCG_REG_TB);
-
- if (tail) {
- if (!tcg_out_opc_jmp(s, OPC_J, arg)) {
- tcg_out_opc_reg(s, OPC_JR, 0, TCG_REG_T9, 0);
- }
- } else {
- if (!tcg_out_opc_jmp(s, OPC_JAL, arg)) {
- tcg_out_opc_reg(s, OPC_JALR, TCG_REG_RA, TCG_REG_T9, 0);
- }
- }
-}
-
-static void tcg_out_call(TCGContext *s, const tcg_insn_unit *arg,
- const TCGHelperInfo *info)
-{
- tcg_out_call_int(s, arg, false);
- tcg_out_nop(s);
-}
-
-/* We have four temps, we might as well expose three of them. */
-static const TCGLdstHelperParam ldst_helper_param = {
- .ntmp = 3, .tmp = { TCG_TMP0, TCG_TMP1, TCG_TMP2 }
-};
-
-static bool tcg_out_qemu_ld_slow_path(TCGContext *s, TCGLabelQemuLdst *l)
-{
- const tcg_insn_unit *tgt_rx = tcg_splitwx_to_rx(s->code_ptr);
- MemOp opc = get_memop(l->oi);
-
- /* resolve label address */
- if (!reloc_pc16(l->label_ptr[0], tgt_rx)
- || (l->label_ptr[1] && !reloc_pc16(l->label_ptr[1], tgt_rx))) {
- return false;
- }
-
- tcg_out_ld_helper_args(s, l, &ldst_helper_param);
-
- tcg_out_call_int(s, qemu_ld_helpers[opc & MO_SSIZE], false);
- /* delay slot */
- tcg_out_nop(s);
-
- tcg_out_ld_helper_ret(s, l, true, &ldst_helper_param);
-
- tcg_out_opc_br(s, OPC_BEQ, TCG_REG_ZERO, TCG_REG_ZERO);
- if (!reloc_pc16(s->code_ptr - 1, l->raddr)) {
- return false;
- }
-
- /* delay slot */
- tcg_out_nop(s);
- return true;
-}
-
-static bool tcg_out_qemu_st_slow_path(TCGContext *s, TCGLabelQemuLdst *l)
-{
- const tcg_insn_unit *tgt_rx = tcg_splitwx_to_rx(s->code_ptr);
- MemOp opc = get_memop(l->oi);
-
- /* resolve label address */
- if (!reloc_pc16(l->label_ptr[0], tgt_rx)
- || (l->label_ptr[1] && !reloc_pc16(l->label_ptr[1], tgt_rx))) {
- return false;
- }
-
- tcg_out_st_helper_args(s, l, &ldst_helper_param);
-
- tcg_out_call_int(s, qemu_st_helpers[opc & MO_SIZE], false);
- /* delay slot */
- tcg_out_nop(s);
-
- tcg_out_opc_br(s, OPC_BEQ, TCG_REG_ZERO, TCG_REG_ZERO);
- if (!reloc_pc16(s->code_ptr - 1, l->raddr)) {
- return false;
- }
-
- /* delay slot */
- tcg_out_nop(s);
- return true;
-}
-
-typedef struct {
- TCGReg base;
- TCGAtomAlign aa;
-} HostAddress;
-
-bool tcg_target_has_memory_bswap(MemOp memop)
-{
- return false;
-}
-
-/* We expect to use a 16-bit negative offset from ENV. */
-#define MIN_TLB_MASK_TABLE_OFS -32768
-
-/*
- * For system-mode, perform the TLB load and compare.
- * For user-mode, perform any required alignment tests.
- * In both cases, return a TCGLabelQemuLdst structure if the slow path
- * is required and fill in @h with the host address for the fast path.
- */
-static TCGLabelQemuLdst *prepare_host_addr(TCGContext *s, HostAddress *h,
- TCGReg addr, MemOpIdx oi, bool is_ld)
-{
- TCGType addr_type = s->addr_type;
- TCGLabelQemuLdst *ldst = NULL;
- MemOp opc = get_memop(oi);
- MemOp a_bits;
- unsigned s_bits = opc & MO_SIZE;
- unsigned a_mask;
- TCGReg base;
-
- h->aa = atom_and_align_for_opc(s, opc, MO_ATOM_IFALIGN, false);
- a_bits = h->aa.align;
- a_mask = (1 << a_bits) - 1;
-
- if (tcg_use_softmmu) {
- unsigned s_mask = (1 << s_bits) - 1;
- int mem_index = get_mmuidx(oi);
- int fast_off = tlb_mask_table_ofs(s, mem_index);
- int mask_off = fast_off + offsetof(CPUTLBDescFast, mask);
- int table_off = fast_off + offsetof(CPUTLBDescFast, table);
- int add_off = offsetof(CPUTLBEntry, addend);
- int cmp_off = is_ld ? offsetof(CPUTLBEntry, addr_read)
- : offsetof(CPUTLBEntry, addr_write);
-
- ldst = new_ldst_label(s);
- ldst->is_ld = is_ld;
- ldst->oi = oi;
- ldst->addr_reg = addr;
-
- /* Load tlb_mask[mmu_idx] and tlb_table[mmu_idx]. */
- tcg_out_ld(s, TCG_TYPE_PTR, TCG_TMP0, TCG_AREG0, mask_off);
- tcg_out_ld(s, TCG_TYPE_PTR, TCG_TMP1, TCG_AREG0, table_off);
-
- /* Extract the TLB index from the address into TMP3. */
- if (addr_type == TCG_TYPE_I32) {
- tcg_out_opc_sa(s, OPC_SRL, TCG_TMP3, addr,
- TARGET_PAGE_BITS - CPU_TLB_ENTRY_BITS);
- } else {
- tcg_out_dsrl(s, TCG_TMP3, addr, TARGET_PAGE_BITS - CPU_TLB_ENTRY_BITS);
- }
- tcg_out_opc_reg(s, OPC_AND, TCG_TMP3, TCG_TMP3, TCG_TMP0);
-
- /* Add the tlb_table pointer, creating the CPUTLBEntry address. */
- tcg_out_opc_reg(s, OPC_DADDU, TCG_TMP3, TCG_TMP3, TCG_TMP1);
-
- /* Load the tlb comparator. */
- if (addr_type == TCG_TYPE_I32) {
- tcg_out_ld(s, TCG_TYPE_I32, TCG_TMP0, TCG_TMP3,
- cmp_off + HOST_BIG_ENDIAN * 4);
- } else {
- tcg_out_ld(s, TCG_TYPE_REG, TCG_TMP0, TCG_TMP3, cmp_off);
- }
-
- /* Load the tlb addend for the fast path. */
- tcg_out_ld(s, TCG_TYPE_PTR, TCG_TMP3, TCG_TMP3, add_off);
-
- /*
- * Mask the page bits, keeping the alignment bits to compare against.
- * For unaligned accesses, compare against the end of the access to
- * verify that it does not cross a page boundary.
- */
- tcg_out_movi(s, addr_type, TCG_TMP1, TARGET_PAGE_MASK | a_mask);
- if (a_mask < s_mask) {
- tcg_out_opc_imm(s, (addr_type == TCG_TYPE_I32
- ? OPC_ADDIU : OPC_DADDIU),
- TCG_TMP2, addr, s_mask - a_mask);
- tcg_out_opc_reg(s, OPC_AND, TCG_TMP1, TCG_TMP1, TCG_TMP2);
- } else {
- tcg_out_opc_reg(s, OPC_AND, TCG_TMP1, TCG_TMP1, addr);
- }
-
- /* Zero extend a 32-bit guest address for a 64-bit host. */
- if (addr_type == TCG_TYPE_I32) {
- tcg_out_ext32u(s, TCG_TMP2, addr);
- addr = TCG_TMP2;
- }
-
- ldst->label_ptr[0] = s->code_ptr;
- tcg_out_opc_br(s, OPC_BNE, TCG_TMP1, TCG_TMP0);
-
- /* delay slot */
- base = TCG_TMP3;
- tcg_out_opc_reg(s, OPC_DADDU, base, TCG_TMP3, addr);
- } else {
- if (a_mask && (use_mips32r6_instructions || a_bits != s_bits)) {
- ldst = new_ldst_label(s);
-
- ldst->is_ld = is_ld;
- ldst->oi = oi;
- ldst->addr_reg = addr;
-
- /* We are expecting a_bits to max out at 7, much lower than ANDI. */
- tcg_debug_assert(a_bits < 16);
- tcg_out_opc_imm(s, OPC_ANDI, TCG_TMP0, addr, a_mask);
-
- ldst->label_ptr[0] = s->code_ptr;
- if (use_mips32r6_instructions) {
- tcg_out_opc_br(s, OPC_BNEZALC_R6, TCG_REG_ZERO, TCG_TMP0);
- } else {
- tcg_out_opc_br(s, OPC_BNEL, TCG_TMP0, TCG_REG_ZERO);
- tcg_out_nop(s);
- }
- }
-
- base = addr;
- if (addr_type == TCG_TYPE_I32) {
- tcg_out_ext32u(s, TCG_REG_A0, base);
- base = TCG_REG_A0;
- }
- if (guest_base) {
- if (guest_base == (int16_t)guest_base) {
- tcg_out_opc_imm(s, OPC_DADDIU, TCG_REG_A0, base, guest_base);
- } else {
- tcg_out_opc_reg(s, OPC_DADDU, TCG_REG_A0, base,
- TCG_GUEST_BASE_REG);
- }
- base = TCG_REG_A0;
- }
- }
-
- h->base = base;
- return ldst;
-}
-
-static void tcg_out_qemu_ld_direct(TCGContext *s, TCGReg lo, TCGReg hi,
- TCGReg base, MemOp opc, TCGType type)
-{
- switch (opc & MO_SSIZE) {
- case MO_UB:
- tcg_out_opc_imm(s, OPC_LBU, lo, base, 0);
- break;
- case MO_SB:
- tcg_out_opc_imm(s, OPC_LB, lo, base, 0);
- break;
- case MO_UW:
- tcg_out_opc_imm(s, OPC_LHU, lo, base, 0);
- break;
- case MO_SW:
- tcg_out_opc_imm(s, OPC_LH, lo, base, 0);
- break;
- case MO_UL:
- if (type == TCG_TYPE_I64) {
- tcg_out_opc_imm(s, OPC_LWU, lo, base, 0);
- break;
- }
- /* FALLTHRU */
- case MO_SL:
- tcg_out_opc_imm(s, OPC_LW, lo, base, 0);
- break;
- case MO_UQ:
- tcg_out_opc_imm(s, OPC_LD, lo, base, 0);
- break;
- default:
- g_assert_not_reached();
- }
-}
-
-static void tcg_out_qemu_ld_unalign(TCGContext *s, TCGReg lo, TCGReg hi,
- TCGReg base, MemOp opc, TCGType type)
-{
- const MIPSInsn lw1 = HOST_BIG_ENDIAN ? OPC_LWL : OPC_LWR;
- const MIPSInsn lw2 = HOST_BIG_ENDIAN ? OPC_LWR : OPC_LWL;
- const MIPSInsn ld1 = HOST_BIG_ENDIAN ? OPC_LDL : OPC_LDR;
- const MIPSInsn ld2 = HOST_BIG_ENDIAN ? OPC_LDR : OPC_LDL;
- bool sgn = opc & MO_SIGN;
-
- switch (opc & MO_SIZE) {
- case MO_16:
- if (HOST_BIG_ENDIAN) {
- tcg_out_opc_imm(s, sgn ? OPC_LB : OPC_LBU, TCG_TMP0, base, 0);
- tcg_out_opc_imm(s, OPC_LBU, lo, base, 1);
- if (use_mips32r2_instructions) {
- tcg_out_opc_bf(s, OPC_INS, lo, TCG_TMP0, 31, 8);
- } else {
- tcg_out_opc_sa(s, OPC_SLL, TCG_TMP0, TCG_TMP0, 8);
- tcg_out_opc_reg(s, OPC_OR, lo, lo, TCG_TMP0);
- }
- } else if (use_mips32r2_instructions && lo != base) {
- tcg_out_opc_imm(s, OPC_LBU, lo, base, 0);
- tcg_out_opc_imm(s, sgn ? OPC_LB : OPC_LBU, TCG_TMP0, base, 1);
- tcg_out_opc_bf(s, OPC_INS, lo, TCG_TMP0, 31, 8);
- } else {
- tcg_out_opc_imm(s, OPC_LBU, TCG_TMP0, base, 0);
- tcg_out_opc_imm(s, sgn ? OPC_LB : OPC_LBU, TCG_TMP1, base, 1);
- tcg_out_opc_sa(s, OPC_SLL, TCG_TMP1, TCG_TMP1, 8);
- tcg_out_opc_reg(s, OPC_OR, lo, TCG_TMP0, TCG_TMP1);
- }
- break;
-
- case MO_32:
- tcg_out_opc_imm(s, lw1, lo, base, 0);
- tcg_out_opc_imm(s, lw2, lo, base, 3);
- if (type == TCG_TYPE_I64 && !sgn) {
- tcg_out_ext32u(s, lo, lo);
- }
- break;
-
- case MO_64:
- tcg_out_opc_imm(s, ld1, lo, base, 0);
- tcg_out_opc_imm(s, ld2, lo, base, 7);
- break;
-
- default:
- g_assert_not_reached();
- }
-}
-
-static void tgen_qemu_ld(TCGContext *s, TCGType type, TCGReg data,
- TCGReg addr, MemOpIdx oi)
-{
- MemOp opc = get_memop(oi);
- TCGLabelQemuLdst *ldst;
- HostAddress h;
-
- ldst = prepare_host_addr(s, &h, addr, oi, true);
-
- if (use_mips32r6_instructions || h.aa.align >= (opc & MO_SIZE)) {
- tcg_out_qemu_ld_direct(s, data, 0, h.base, opc, type);
- } else {
- tcg_out_qemu_ld_unalign(s, data, 0, h.base, opc, type);
- }
-
- if (ldst) {
- ldst->type = type;
- ldst->datalo_reg = data;
- ldst->datahi_reg = 0;
- ldst->raddr = tcg_splitwx_to_rx(s->code_ptr);
- }
-}
-
-static const TCGOutOpQemuLdSt outop_qemu_ld = {
- .base.static_constraint = C_O1_I1(r, r),
- .out = tgen_qemu_ld,
-};
-
-static const TCGOutOpQemuLdSt2 outop_qemu_ld2 = {
- .base.static_constraint = C_NotImplemented,
-};
-
-static void tcg_out_qemu_st_direct(TCGContext *s, TCGReg lo, TCGReg hi,
- TCGReg base, MemOp opc)
-{
- switch (opc & MO_SIZE) {
- case MO_8:
- tcg_out_opc_imm(s, OPC_SB, lo, base, 0);
- break;
- case MO_16:
- tcg_out_opc_imm(s, OPC_SH, lo, base, 0);
- break;
- case MO_32:
- tcg_out_opc_imm(s, OPC_SW, lo, base, 0);
- break;
- case MO_64:
- tcg_out_opc_imm(s, OPC_SD, lo, base, 0);
- break;
- default:
- g_assert_not_reached();
- }
-}
-
-static void tcg_out_qemu_st_unalign(TCGContext *s, TCGReg lo, TCGReg hi,
- TCGReg base, MemOp opc)
-{
- const MIPSInsn sw1 = HOST_BIG_ENDIAN ? OPC_SWL : OPC_SWR;
- const MIPSInsn sw2 = HOST_BIG_ENDIAN ? OPC_SWR : OPC_SWL;
- const MIPSInsn sd1 = HOST_BIG_ENDIAN ? OPC_SDL : OPC_SDR;
- const MIPSInsn sd2 = HOST_BIG_ENDIAN ? OPC_SDR : OPC_SDL;
-
- switch (opc & MO_SIZE) {
- case MO_16:
- tcg_out_opc_sa(s, OPC_SRL, TCG_TMP0, lo, 8);
- tcg_out_opc_imm(s, OPC_SB, HOST_BIG_ENDIAN ? TCG_TMP0 : lo, base, 0);
- tcg_out_opc_imm(s, OPC_SB, HOST_BIG_ENDIAN ? lo : TCG_TMP0, base, 1);
- break;
-
- case MO_32:
- tcg_out_opc_imm(s, sw1, lo, base, 0);
- tcg_out_opc_imm(s, sw2, lo, base, 3);
- break;
-
- case MO_64:
- tcg_out_opc_imm(s, sd1, lo, base, 0);
- tcg_out_opc_imm(s, sd2, lo, base, 7);
- break;
-
- default:
- g_assert_not_reached();
- }
-}
-
-static void tgen_qemu_st(TCGContext *s, TCGType type, TCGReg data,
- TCGReg addr, MemOpIdx oi)
-{
- MemOp opc = get_memop(oi);
- TCGLabelQemuLdst *ldst;
- HostAddress h;
-
- ldst = prepare_host_addr(s, &h, addr, oi, false);
-
- if (use_mips32r6_instructions || h.aa.align >= (opc & MO_SIZE)) {
- tcg_out_qemu_st_direct(s, data, 0, h.base, opc);
- } else {
- tcg_out_qemu_st_unalign(s, data, 0, h.base, opc);
- }
-
- if (ldst) {
- ldst->type = type;
- ldst->datalo_reg = data;
- ldst->datahi_reg = 0;
- ldst->raddr = tcg_splitwx_to_rx(s->code_ptr);
- }
-}
-
-static const TCGOutOpQemuLdSt outop_qemu_st = {
- .base.static_constraint = C_O0_I2(rz, r),
- .out = tgen_qemu_st,
-};
-
-static const TCGOutOpQemuLdSt2 outop_qemu_st2 = {
- .base.static_constraint = C_NotImplemented,
-};
-
-static void tcg_out_mb(TCGContext *s, unsigned a0)
-{
- static const MIPSInsn sync[] = {
- /* Note that SYNC_MB is a slightly weaker than SYNC 0,
- as the former is an ordering barrier and the latter
- is a completion barrier. */
- [0 ... TCG_MO_ALL] = OPC_SYNC_MB,
- [TCG_MO_LD_LD] = OPC_SYNC_RMB,
- [TCG_MO_ST_ST] = OPC_SYNC_WMB,
- [TCG_MO_LD_ST] = OPC_SYNC_RELEASE,
- [TCG_MO_LD_ST | TCG_MO_ST_ST] = OPC_SYNC_RELEASE,
- [TCG_MO_LD_ST | TCG_MO_LD_LD] = OPC_SYNC_ACQUIRE,
- };
- tcg_out32(s, sync[a0 & TCG_MO_ALL]);
-}
-
-static void tcg_out_exit_tb(TCGContext *s, uintptr_t a0)
-{
- TCGReg base = TCG_REG_ZERO;
- int16_t lo = 0;
-
- if (a0) {
- intptr_t ofs = tcg_tbrel_diff(s, (void *)a0);
- lo = ofs;
- if (ofs == lo) {
- base = TCG_REG_TB;
- } else {
- base = TCG_REG_V0;
- tcg_out_movi(s, TCG_TYPE_PTR, base, ofs - lo);
- tcg_out_opc_reg(s, OPC_DADDU, base, base, TCG_REG_TB);
- }
- }
- if (!tcg_out_opc_jmp(s, OPC_J, tb_ret_addr)) {
- tcg_out_movi(s, TCG_TYPE_PTR, TCG_TMP0, (uintptr_t)tb_ret_addr);
- tcg_out_opc_reg(s, OPC_JR, 0, TCG_TMP0, 0);
- }
- /* delay slot */
- tcg_out_opc_imm(s, OPC_DADDIU, TCG_REG_V0, base, lo);
-}
-
-static void tcg_out_goto_tb(TCGContext *s, int which)
-{
- intptr_t ofs = get_jmp_target_addr(s, which);
- TCGReg base, dest;
-
- /* indirect jump method */
- dest = TCG_REG_TB;
- base = TCG_REG_TB;
- ofs = tcg_tbrel_diff(s, (void *)ofs);
- tcg_out_ld(s, TCG_TYPE_PTR, dest, base, ofs);
- tcg_out_opc_reg(s, OPC_JR, 0, dest, 0);
- /* delay slot */
- tcg_out_nop(s);
-
- set_jmp_reset_offset(s, which);
- /* For the unlinked case, need to reset TCG_REG_TB. */
- tcg_out_ldst(s, OPC_DADDIU, TCG_REG_TB, TCG_REG_TB,
- -tcg_current_code_size(s));
-}
-
-static void tcg_out_goto_ptr(TCGContext *s, TCGReg a0)
-{
- tcg_out_opc_reg(s, OPC_JR, 0, a0, 0);
- tcg_out_mov(s, TCG_TYPE_PTR, TCG_REG_TB, a0);
-}
-
-void tb_target_set_jmp_target(const TranslationBlock *tb, int n,
- uintptr_t jmp_rx, uintptr_t jmp_rw)
-{
- /* Always indirect, nothing to do */
-}
-
-
-static void tgen_add(TCGContext *s, TCGType type,
- TCGReg a0, TCGReg a1, TCGReg a2)
-{
- MIPSInsn insn = type == TCG_TYPE_I32 ? OPC_ADDU : OPC_DADDU;
- tcg_out_opc_reg(s, insn, a0, a1, a2);
-}
-
-static void tgen_addi(TCGContext *s, TCGType type,
- TCGReg a0, TCGReg a1, tcg_target_long a2)
-{
- MIPSInsn insn = type == TCG_TYPE_I32 ? OPC_ADDIU : OPC_DADDIU;
- tcg_out_opc_imm(s, insn, a0, a1, a2);
-}
-
-static const TCGOutOpBinary outop_add = {
- .base.static_constraint = C_O1_I2(r, r, rJ),
- .out_rrr = tgen_add,
- .out_rri = tgen_addi,
-};
-
-static const TCGOutOpBinary outop_addco = {
- .base.static_constraint = C_NotImplemented,
-};
-
-static const TCGOutOpAddSubCarry outop_addci = {
- .base.static_constraint = C_NotImplemented,
-};
-
-static const TCGOutOpBinary outop_addcio = {
- .base.static_constraint = C_NotImplemented,
-};
-
-static void tcg_out_set_carry(TCGContext *s)
-{
- g_assert_not_reached();
-}
-
-static void tgen_and(TCGContext *s, TCGType type,
- TCGReg a0, TCGReg a1, TCGReg a2)
-{
- tcg_out_opc_reg(s, OPC_AND, a0, a1, a2);
-}
-
-static void tgen_andi(TCGContext *s, TCGType type,
- TCGReg a0, TCGReg a1, tcg_target_long a2)
-{
- int msb;
-
- if (a2 == (uint16_t)a2) {
- tcg_out_opc_imm(s, OPC_ANDI, a0, a1, a2);
- return;
- }
-
- tcg_debug_assert(use_mips32r2_instructions);
- tcg_debug_assert(is_p2m1(a2));
- msb = ctz64(~a2) - 1;
- if (type == TCG_TYPE_I32) {
- tcg_out_opc_bf(s, OPC_EXT, a0, a1, msb, 0);
- } else {
- tcg_out_opc_bf64(s, OPC_DEXT, OPC_DEXTM, OPC_DEXTU, a0, a1, msb, 0);
- }
-}
-
-static const TCGOutOpBinary outop_and = {
- .base.static_constraint = C_O1_I2(r, r, rIK),
- .out_rrr = tgen_and,
- .out_rri = tgen_andi,
-};
-
-static const TCGOutOpBinary outop_andc = {
- .base.static_constraint = C_NotImplemented,
-};
-
-static void tgen_clz(TCGContext *s, TCGType type,
- TCGReg a0, TCGReg a1, TCGReg a2)
-{
- if (use_mips32r6_instructions) {
- MIPSInsn opcv6 = type == TCG_TYPE_I32 ? OPC_CLZ_R6 : OPC_DCLZ_R6;
- tcg_out_opc_reg(s, opcv6, TCG_TMP0, a1, 0);
- tgen_movcond(s, TCG_TYPE_REG, TCG_COND_EQ, a0, a1, a2, false,
- TCG_TMP0, false, TCG_REG_ZERO, false);
- } else {
- MIPSInsn opcv2 = type == TCG_TYPE_I32 ? OPC_CLZ : OPC_DCLZ;
- if (a0 == a2) {
- tcg_out_opc_reg(s, opcv2, TCG_TMP0, a1, a1);
- tcg_out_opc_reg(s, OPC_MOVN, a0, TCG_TMP0, a1);
- } else if (a0 != a1) {
- tcg_out_opc_reg(s, opcv2, a0, a1, a1);
- tcg_out_opc_reg(s, OPC_MOVZ, a0, a2, a1);
- } else {
- tcg_out_opc_reg(s, opcv2, TCG_TMP0, a1, a1);
- tcg_out_opc_reg(s, OPC_MOVZ, TCG_TMP0, a2, a1);
- tcg_out_mov(s, type, a0, TCG_TMP0);
- }
- }
-}
-
-static void tgen_clzi(TCGContext *s, TCGType type,
- TCGReg a0, TCGReg a1, tcg_target_long a2)
-{
- if (a2 == 0) {
- tgen_clz(s, type, a0, a1, TCG_REG_ZERO);
- } else if (use_mips32r6_instructions) {
- MIPSInsn opcv6 = type == TCG_TYPE_I32 ? OPC_CLZ_R6 : OPC_DCLZ_R6;
- tcg_out_opc_reg(s, opcv6, a0, a1, 0);
- } else {
- MIPSInsn opcv2 = type == TCG_TYPE_I32 ? OPC_CLZ : OPC_DCLZ;
- tcg_out_opc_reg(s, opcv2, a0, a1, a1);
- }
-}
-
-static TCGConstraintSetIndex cset_clz(TCGType type, unsigned flags)
-{
- return use_mips32r2_instructions ? C_O1_I2(r, r, rzW) : C_NotImplemented;
-}
-
-static const TCGOutOpBinary outop_clz = {
- .base.static_constraint = C_Dynamic,
- .base.dynamic_constraint = cset_clz,
- .out_rrr = tgen_clz,
- .out_rri = tgen_clzi,
-};
-
-static const TCGOutOpUnary outop_ctpop = {
- .base.static_constraint = C_NotImplemented,
-};
-
-static const TCGOutOpBinary outop_ctz = {
- .base.static_constraint = C_NotImplemented,
-};
-
-static void tgen_divs(TCGContext *s, TCGType type,
- TCGReg a0, TCGReg a1, TCGReg a2)
-{
- if (use_mips32r6_instructions) {
- if (type == TCG_TYPE_I32) {
- tcg_out_opc_reg(s, OPC_DIV_R6, a0, a1, a2);
- } else {
- tcg_out_opc_reg(s, OPC_DDIV_R6, a0, a1, a2);
- }
- } else {
- MIPSInsn insn = type == TCG_TYPE_I32 ? OPC_DIV : OPC_DDIV;
- tcg_out_opc_reg(s, insn, 0, a1, a2);
- tcg_out_opc_reg(s, OPC_MFLO, a0, 0, 0);
- }
-}
-
-static const TCGOutOpBinary outop_divs = {
- .base.static_constraint = C_O1_I2(r, r, r),
- .out_rrr = tgen_divs,
-};
-
-static const TCGOutOpDivRem outop_divs2 = {
- .base.static_constraint = C_NotImplemented,
-};
-
-static void tgen_divu(TCGContext *s, TCGType type,
- TCGReg a0, TCGReg a1, TCGReg a2)
-{
- if (use_mips32r6_instructions) {
- if (type == TCG_TYPE_I32) {
- tcg_out_opc_reg(s, OPC_DIVU_R6, a0, a1, a2);
- } else {
- tcg_out_opc_reg(s, OPC_DDIVU_R6, a0, a1, a2);
- }
- } else {
- MIPSInsn insn = type == TCG_TYPE_I32 ? OPC_DIVU : OPC_DDIVU;
- tcg_out_opc_reg(s, insn, 0, a1, a2);
- tcg_out_opc_reg(s, OPC_MFLO, a0, 0, 0);
- }
-}
-
-static const TCGOutOpBinary outop_divu = {
- .base.static_constraint = C_O1_I2(r, r, r),
- .out_rrr = tgen_divu,
-};
-
-static const TCGOutOpDivRem outop_divu2 = {
- .base.static_constraint = C_NotImplemented,
-};
-
-static const TCGOutOpBinary outop_eqv = {
- .base.static_constraint = C_NotImplemented,
-};
-
-static void tgen_extrh_i64_i32(TCGContext *s, TCGType t, TCGReg a0, TCGReg a1)
-{
- tcg_out_dsra(s, a0, a1, 32);
-}
-
-static const TCGOutOpUnary outop_extrh_i64_i32 = {
- .base.static_constraint = C_O1_I1(r, r),
- .out_rr = tgen_extrh_i64_i32,
-};
-
-static void tgen_mul(TCGContext *s, TCGType type,
- TCGReg a0, TCGReg a1, TCGReg a2)
-{
- MIPSInsn insn;
-
- if (type == TCG_TYPE_I32) {
- if (use_mips32_instructions) {
- tcg_out_opc_reg(s, OPC_MUL, a0, a1, a2);
- return;
- }
- insn = OPC_MULT;
- } else {
- if (use_mips32r6_instructions) {
- tcg_out_opc_reg(s, OPC_DMUL, a0, a1, a2);
- return;
- }
- insn = OPC_DMULT;
- }
- tcg_out_opc_reg(s, insn, 0, a1, a2);
- tcg_out_opc_reg(s, OPC_MFLO, a0, 0, 0);
-}
-
-static const TCGOutOpBinary outop_mul = {
- .base.static_constraint = C_O1_I2(r, r, r),
- .out_rrr = tgen_mul,
-};
-
-static void tgen_muls2(TCGContext *s, TCGType type,
- TCGReg a0, TCGReg a1, TCGReg a2, TCGReg a3)
-{
- MIPSInsn insn = type == TCG_TYPE_I32 ? OPC_MULT : OPC_DMULT;
- tcg_out_opc_reg(s, insn, 0, a2, a3);
- tcg_out_opc_reg(s, OPC_MFLO, a0, 0, 0);
- tcg_out_opc_reg(s, OPC_MFHI, a1, 0, 0);
-}
-
-static TCGConstraintSetIndex cset_mul2(TCGType type, unsigned flags)
-{
- return use_mips32r6_instructions ? C_NotImplemented : C_O2_I2(r, r, r, r);
-}
-
-static const TCGOutOpMul2 outop_muls2 = {
- .base.static_constraint = C_Dynamic,
- .base.dynamic_constraint = cset_mul2,
- .out_rrrr = tgen_muls2,
-};
-
-static void tgen_mulsh(TCGContext *s, TCGType type,
- TCGReg a0, TCGReg a1, TCGReg a2)
-{
- if (use_mips32r6_instructions) {
- MIPSInsn insn = type == TCG_TYPE_I32 ? OPC_MUH : OPC_DMUH;
- tcg_out_opc_reg(s, insn, a0, a1, a2);
- } else {
- MIPSInsn insn = type == TCG_TYPE_I32 ? OPC_MULT : OPC_DMULT;
- tcg_out_opc_reg(s, insn, 0, a1, a2);
- tcg_out_opc_reg(s, OPC_MFHI, a0, 0, 0);
- }
-}
-
-static const TCGOutOpBinary outop_mulsh = {
- .base.static_constraint = C_O1_I2(r, r, r),
- .out_rrr = tgen_mulsh,
-};
-
-static void tgen_mulu2(TCGContext *s, TCGType type,
- TCGReg a0, TCGReg a1, TCGReg a2, TCGReg a3)
-{
- MIPSInsn insn = type == TCG_TYPE_I32 ? OPC_MULTU : OPC_DMULTU;
- tcg_out_opc_reg(s, insn, 0, a2, a3);
- tcg_out_opc_reg(s, OPC_MFLO, a0, 0, 0);
- tcg_out_opc_reg(s, OPC_MFHI, a1, 0, 0);
-}
-
-static const TCGOutOpMul2 outop_mulu2 = {
- .base.static_constraint = C_Dynamic,
- .base.dynamic_constraint = cset_mul2,
- .out_rrrr = tgen_mulu2,
-};
-
-static void tgen_muluh(TCGContext *s, TCGType type,
- TCGReg a0, TCGReg a1, TCGReg a2)
-{
- if (use_mips32r6_instructions) {
- MIPSInsn insn = type == TCG_TYPE_I32 ? OPC_MUHU : OPC_DMUHU;
- tcg_out_opc_reg(s, insn, a0, a1, a2);
- } else {
- MIPSInsn insn = type == TCG_TYPE_I32 ? OPC_MULTU : OPC_DMULTU;
- tcg_out_opc_reg(s, insn, 0, a1, a2);
- tcg_out_opc_reg(s, OPC_MFHI, a0, 0, 0);
- }
-}
-
-static const TCGOutOpBinary outop_muluh = {
- .base.static_constraint = C_O1_I2(r, r, r),
- .out_rrr = tgen_muluh,
-};
-
-static const TCGOutOpBinary outop_nand = {
- .base.static_constraint = C_NotImplemented,
-};
-
-static void tgen_nor(TCGContext *s, TCGType type,
- TCGReg a0, TCGReg a1, TCGReg a2)
-{
- tcg_out_opc_reg(s, OPC_NOR, a0, a1, a2);
-}
-
-static const TCGOutOpBinary outop_nor = {
- .base.static_constraint = C_O1_I2(r, r, r),
- .out_rrr = tgen_nor,
-};
-
-static void tgen_or(TCGContext *s, TCGType type,
- TCGReg a0, TCGReg a1, TCGReg a2)
-{
- tcg_out_opc_reg(s, OPC_OR, a0, a1, a2);
-}
-
-static void tgen_ori(TCGContext *s, TCGType type,
- TCGReg a0, TCGReg a1, tcg_target_long a2)
-{
- tcg_out_opc_imm(s, OPC_ORI, a0, a1, a2);
-}
-
-static const TCGOutOpBinary outop_or = {
- .base.static_constraint = C_O1_I2(r, r, rI),
- .out_rrr = tgen_or,
- .out_rri = tgen_ori,
-};
-
-static const TCGOutOpBinary outop_orc = {
- .base.static_constraint = C_NotImplemented,
-};
-
-static void tgen_rems(TCGContext *s, TCGType type,
- TCGReg a0, TCGReg a1, TCGReg a2)
-{
- if (use_mips32r6_instructions) {
- if (type == TCG_TYPE_I32) {
- tcg_out_opc_reg(s, OPC_MOD, a0, a1, a2);
- } else {
- tcg_out_opc_reg(s, OPC_DMOD, a0, a1, a2);
- }
- } else {
- MIPSInsn insn = type == TCG_TYPE_I32 ? OPC_DIV : OPC_DDIV;
- tcg_out_opc_reg(s, insn, 0, a1, a2);
- tcg_out_opc_reg(s, OPC_MFHI, a0, 0, 0);
- }
-}
-
-static const TCGOutOpBinary outop_rems = {
- .base.static_constraint = C_O1_I2(r, r, r),
- .out_rrr = tgen_rems,
-};
-
-static void tgen_remu(TCGContext *s, TCGType type,
- TCGReg a0, TCGReg a1, TCGReg a2)
-{
- if (use_mips32r6_instructions) {
- if (type == TCG_TYPE_I32) {
- tcg_out_opc_reg(s, OPC_MODU, a0, a1, a2);
- } else {
- tcg_out_opc_reg(s, OPC_DMODU, a0, a1, a2);
- }
- } else {
- MIPSInsn insn = type == TCG_TYPE_I32 ? OPC_DIVU : OPC_DDIVU;
- tcg_out_opc_reg(s, insn, 0, a1, a2);
- tcg_out_opc_reg(s, OPC_MFHI, a0, 0, 0);
- }
-}
-
-static const TCGOutOpBinary outop_remu = {
- .base.static_constraint = C_O1_I2(r, r, r),
- .out_rrr = tgen_remu,
-};
-
-static const TCGOutOpBinary outop_rotl = {
- .base.static_constraint = C_NotImplemented,
-};
-
-static TCGConstraintSetIndex cset_rotr(TCGType type, unsigned flags)
-{
- return use_mips32r2_instructions ? C_O1_I2(r, r, ri) : C_NotImplemented;
-}
-
-static void tgen_rotr(TCGContext *s, TCGType type,
- TCGReg a0, TCGReg a1, TCGReg a2)
-{
- MIPSInsn insn = type == TCG_TYPE_I32 ? OPC_ROTRV : OPC_DROTRV;
- tcg_out_opc_reg(s, insn, a0, a1, a2);
-}
-
-static void tgen_rotri(TCGContext *s, TCGType type,
- TCGReg a0, TCGReg a1, tcg_target_long a2)
-{
- if (type == TCG_TYPE_I32) {
- tcg_out_opc_sa(s, OPC_ROTR, a0, a1, a2);
- } else {
- tcg_out_opc_sa64(s, OPC_DROTR, OPC_DROTR32, a0, a1, a2);
- }
-}
-
-static const TCGOutOpBinary outop_rotr = {
- .base.static_constraint = C_Dynamic,
- .base.dynamic_constraint = cset_rotr,
- .out_rrr = tgen_rotr,
- .out_rri = tgen_rotri,
-};
-
-static void tgen_sar(TCGContext *s, TCGType type,
- TCGReg a0, TCGReg a1, TCGReg a2)
-{
- MIPSInsn insn = type == TCG_TYPE_I32 ? OPC_SRAV : OPC_DSRAV;
- tcg_out_opc_reg(s, insn, a0, a1, a2);
-}
-
-static void tgen_sari(TCGContext *s, TCGType type,
- TCGReg a0, TCGReg a1, tcg_target_long a2)
-{
- if (type == TCG_TYPE_I32) {
- tcg_out_opc_sa(s, OPC_SRA, a0, a1, a2);
- } else {
- tcg_out_dsra(s, a0, a1, a2);
- }
-}
-
-static const TCGOutOpBinary outop_sar = {
- .base.static_constraint = C_O1_I2(r, r, ri),
- .out_rrr = tgen_sar,
- .out_rri = tgen_sari,
-};
-
-static void tgen_shl(TCGContext *s, TCGType type,
- TCGReg a0, TCGReg a1, TCGReg a2)
-{
- MIPSInsn insn = type == TCG_TYPE_I32 ? OPC_SLLV : OPC_DSLLV;
- tcg_out_opc_reg(s, insn, a0, a1, a2);
-}
-
-static void tgen_shli(TCGContext *s, TCGType type,
- TCGReg a0, TCGReg a1, tcg_target_long a2)
-{
- if (type == TCG_TYPE_I32) {
- tcg_out_opc_sa(s, OPC_SLL, a0, a1, a2);
- } else {
- tcg_out_dsll(s, a0, a1, a2);
- }
-}
-
-static const TCGOutOpBinary outop_shl = {
- .base.static_constraint = C_O1_I2(r, r, ri),
- .out_rrr = tgen_shl,
- .out_rri = tgen_shli,
-};
-
-static void tgen_shr(TCGContext *s, TCGType type,
- TCGReg a0, TCGReg a1, TCGReg a2)
-{
- MIPSInsn insn = type == TCG_TYPE_I32 ? OPC_SRLV : OPC_DSRLV;
- tcg_out_opc_reg(s, insn, a0, a1, a2);
-}
-
-static void tgen_shri(TCGContext *s, TCGType type,
- TCGReg a0, TCGReg a1, tcg_target_long a2)
-{
- if (type == TCG_TYPE_I32) {
- tcg_out_opc_sa(s, OPC_SRL, a0, a1, a2);
- } else {
- tcg_out_dsrl(s, a0, a1, a2);
- }
-}
-
-static const TCGOutOpBinary outop_shr = {
- .base.static_constraint = C_O1_I2(r, r, ri),
- .out_rrr = tgen_shr,
- .out_rri = tgen_shri,
-};
-
-static void tgen_sub(TCGContext *s, TCGType type,
- TCGReg a0, TCGReg a1, TCGReg a2)
-{
- MIPSInsn insn = type == TCG_TYPE_I32 ? OPC_SUBU : OPC_DSUBU;
- tcg_out_opc_reg(s, insn, a0, a1, a2);
-}
-
-static const TCGOutOpSubtract outop_sub = {
- .base.static_constraint = C_O1_I2(r, r, r),
- .out_rrr = tgen_sub,
-};
-
-static const TCGOutOpAddSubCarry outop_subbo = {
- .base.static_constraint = C_NotImplemented,
-};
-
-static const TCGOutOpAddSubCarry outop_subbi = {
- .base.static_constraint = C_NotImplemented,
-};
-
-static const TCGOutOpAddSubCarry outop_subbio = {
- .base.static_constraint = C_NotImplemented,
-};
-
-static void tcg_out_set_borrow(TCGContext *s)
-{
- g_assert_not_reached();
-}
-
-static void tgen_xor(TCGContext *s, TCGType type,
- TCGReg a0, TCGReg a1, TCGReg a2)
-{
- tcg_out_opc_reg(s, OPC_XOR, a0, a1, a2);
-}
-
-static void tgen_xori(TCGContext *s, TCGType type,
- TCGReg a0, TCGReg a1, tcg_target_long a2)
-{
- tcg_out_opc_imm(s, OPC_XORI, a0, a1, a2);
-}
-
-static const TCGOutOpBinary outop_xor = {
- .base.static_constraint = C_O1_I2(r, r, rI),
- .out_rrr = tgen_xor,
- .out_rri = tgen_xori,
-};
-
-static void tgen_bswap16(TCGContext *s, TCGType type,
- TCGReg ret, TCGReg arg, unsigned flags)
-{
- /* With arg = abcd: */
- if (use_mips32r2_instructions) {
- tcg_out_opc_reg(s, OPC_WSBH, ret, 0, arg); /* badc */
- if (flags & TCG_BSWAP_OS) {
- tcg_out_opc_reg(s, OPC_SEH, ret, 0, ret); /* ssdc */
- } else if ((flags & (TCG_BSWAP_IZ | TCG_BSWAP_OZ)) == TCG_BSWAP_OZ) {
- tcg_out_opc_imm(s, OPC_ANDI, ret, ret, 0xffff); /* 00dc */
- }
- return;
- }
-
- tcg_out_opc_sa(s, OPC_SRL, TCG_TMP0, arg, 8); /* 0abc */
- if (!(flags & TCG_BSWAP_IZ)) {
- tcg_out_opc_imm(s, OPC_ANDI, TCG_TMP0, TCG_TMP0, 0x00ff); /* 000c */
- }
- if (flags & TCG_BSWAP_OS) {
- tcg_out_opc_sa(s, OPC_SLL, ret, arg, 24); /* d000 */
- tcg_out_opc_sa(s, OPC_SRA, ret, ret, 16); /* ssd0 */
- } else {
- tcg_out_opc_sa(s, OPC_SLL, ret, arg, 8); /* bcd0 */
- if (flags & TCG_BSWAP_OZ) {
- tcg_out_opc_imm(s, OPC_ANDI, ret, ret, 0xff00); /* 00d0 */
- }
- }
- tcg_out_opc_reg(s, OPC_OR, ret, ret, TCG_TMP0); /* ssdc */
-}
-
-static const TCGOutOpBswap outop_bswap16 = {
- .base.static_constraint = C_O1_I1(r, r),
- .out_rr = tgen_bswap16,
-};
-
-static void tgen_bswap32(TCGContext *s, TCGType type,
- TCGReg ret, TCGReg arg, unsigned flags)
-{
- if (use_mips32r2_instructions) {
- tcg_out_opc_reg(s, OPC_WSBH, ret, 0, arg);
- tcg_out_opc_sa(s, OPC_ROTR, ret, ret, 16);
- if (flags & TCG_BSWAP_OZ) {
- tcg_out_opc_bf(s, OPC_DEXT, ret, ret, 31, 0);
- }
- } else {
- if (flags & TCG_BSWAP_OZ) {
- tcg_out_bswap_subr(s, bswap32u_addr);
- } else {
- tcg_out_bswap_subr(s, bswap32_addr);
- }
- /* delay slot -- never omit the insn, like tcg_out_mov might. */
- tcg_out_opc_reg(s, OPC_OR, TCG_TMP0, arg, TCG_REG_ZERO);
- tcg_out_mov(s, TCG_TYPE_I32, ret, TCG_TMP3);
- }
-}
-
-static const TCGOutOpBswap outop_bswap32 = {
- .base.static_constraint = C_O1_I1(r, r),
- .out_rr = tgen_bswap32,
-};
-
-static void tgen_bswap64(TCGContext *s, TCGType type, TCGReg ret, TCGReg arg)
-{
- if (use_mips32r2_instructions) {
- tcg_out_opc_reg(s, OPC_DSBH, ret, 0, arg);
- tcg_out_opc_reg(s, OPC_DSHD, ret, 0, ret);
- } else {
- tcg_out_bswap_subr(s, bswap64_addr);
- /* delay slot -- never omit the insn, like tcg_out_mov might. */
- tcg_out_opc_reg(s, OPC_OR, TCG_TMP0, arg, TCG_REG_ZERO);
- tcg_out_mov(s, TCG_TYPE_I32, ret, TCG_TMP3);
- }
-}
-
-static const TCGOutOpUnary outop_bswap64 = {
- .base.static_constraint = C_O1_I1(r, r),
- .out_rr = tgen_bswap64,
-};
-
-static void tgen_neg(TCGContext *s, TCGType type, TCGReg a0, TCGReg a1)
-{
- tgen_sub(s, type, a0, TCG_REG_ZERO, a1);
-}
-
-static const TCGOutOpUnary outop_neg = {
- .base.static_constraint = C_O1_I1(r, r),
- .out_rr = tgen_neg,
-};
-
-static void tgen_not(TCGContext *s, TCGType type, TCGReg a0, TCGReg a1)
-{
- tgen_nor(s, type, a0, TCG_REG_ZERO, a1);
-}
-
-static const TCGOutOpUnary outop_not = {
- .base.static_constraint = C_O1_I1(r, r),
- .out_rr = tgen_not,
-};
-
-static void tgen_deposit(TCGContext *s, TCGType type, TCGReg a0, TCGReg a1,
- TCGReg a2, unsigned ofs, unsigned len)
-{
- if (type == TCG_TYPE_I32) {
- tcg_out_opc_bf(s, OPC_INS, a0, a2, ofs + len - 1, ofs);
- } else {
- tcg_out_opc_bf64(s, OPC_DINS, OPC_DINSM, OPC_DINSU, a0, a2,
- ofs + len - 1, ofs);
- }
-}
-
-static const TCGOutOpDeposit outop_deposit = {
- .base.static_constraint = C_O1_I2(r, 0, rz),
- .out_rrr = tgen_deposit,
-};
-
-static void tgen_extract(TCGContext *s, TCGType type, TCGReg a0, TCGReg a1,
- unsigned ofs, unsigned len)
-{
- if (ofs == 0 && len <= 16) {
- tcg_out_opc_imm(s, OPC_ANDI, a0, a1, (1 << len) - 1);
- } else if (type == TCG_TYPE_I32) {
- tcg_out_opc_bf(s, OPC_EXT, a0, a1, len - 1, ofs);
- } else {
- tcg_out_opc_bf64(s, OPC_DEXT, OPC_DEXTM, OPC_DEXTU,
- a0, a1, len - 1, ofs);
- }
-}
-
-static const TCGOutOpExtract outop_extract = {
- .base.static_constraint = C_O1_I1(r, r),
- .out_rr = tgen_extract,
-};
-
-static void tgen_sextract(TCGContext *s, TCGType type, TCGReg a0, TCGReg a1,
- unsigned ofs, unsigned len)
-{
- if (ofs == 0) {
- switch (len) {
- case 8:
- tcg_out_ext8s(s, type, a0, a1);
- return;
- case 16:
- tcg_out_ext16s(s, type, a0, a1);
- return;
- case 32:
- tcg_out_ext32s(s, a0, a1);
- return;
- }
- }
- g_assert_not_reached();
-}
-
-static const TCGOutOpExtract outop_sextract = {
- .base.static_constraint = C_O1_I1(r, r),
- .out_rr = tgen_sextract,
-};
-
-static const TCGOutOpExtract2 outop_extract2 = {
- .base.static_constraint = C_NotImplemented,
-};
-
-static void tgen_ld8u(TCGContext *s, TCGType type, TCGReg dest,
- TCGReg base, ptrdiff_t offset)
-{
- tcg_out_ldst(s, OPC_LBU, dest, base, offset);
-}
-
-static const TCGOutOpLoad outop_ld8u = {
- .base.static_constraint = C_O1_I1(r, r),
- .out = tgen_ld8u,
-};
-
-static void tgen_ld8s(TCGContext *s, TCGType type, TCGReg dest,
- TCGReg base, ptrdiff_t offset)
-{
- tcg_out_ldst(s, OPC_LB, dest, base, offset);
-}
-
-static const TCGOutOpLoad outop_ld8s = {
- .base.static_constraint = C_O1_I1(r, r),
- .out = tgen_ld8s,
-};
-
-static void tgen_ld16u(TCGContext *s, TCGType type, TCGReg dest,
- TCGReg base, ptrdiff_t offset)
-{
- tcg_out_ldst(s, OPC_LHU, dest, base, offset);
-}
-
-static const TCGOutOpLoad outop_ld16u = {
- .base.static_constraint = C_O1_I1(r, r),
- .out = tgen_ld16u,
-};
-
-static void tgen_ld16s(TCGContext *s, TCGType type, TCGReg dest,
- TCGReg base, ptrdiff_t offset)
-{
- tcg_out_ldst(s, OPC_LH, dest, base, offset);
-}
-
-static const TCGOutOpLoad outop_ld16s = {
- .base.static_constraint = C_O1_I1(r, r),
- .out = tgen_ld16s,
-};
-
-static void tgen_ld32u(TCGContext *s, TCGType type, TCGReg dest,
- TCGReg base, ptrdiff_t offset)
-{
- tcg_out_ldst(s, OPC_LWU, dest, base, offset);
-}
-
-static const TCGOutOpLoad outop_ld32u = {
- .base.static_constraint = C_O1_I1(r, r),
- .out = tgen_ld32u,
-};
-
-static void tgen_ld32s(TCGContext *s, TCGType type, TCGReg dest,
- TCGReg base, ptrdiff_t offset)
-{
- tcg_out_ldst(s, OPC_LW, dest, base, offset);
-}
-
-static const TCGOutOpLoad outop_ld32s = {
- .base.static_constraint = C_O1_I1(r, r),
- .out = tgen_ld32s,
-};
-
-static void tgen_st8_r(TCGContext *s, TCGType type, TCGReg data,
- TCGReg base, ptrdiff_t offset)
-{
- tcg_out_ldst(s, OPC_SB, data, base, offset);
-}
-
-static const TCGOutOpStore outop_st8 = {
- .base.static_constraint = C_O0_I2(rz, r),
- .out_r = tgen_st8_r,
-};
-
-static void tgen_st16_r(TCGContext *s, TCGType type, TCGReg data,
- TCGReg base, ptrdiff_t offset)
-{
- tcg_out_ldst(s, OPC_SH, data, base, offset);
-}
-
-static const TCGOutOpStore outop_st16 = {
- .base.static_constraint = C_O0_I2(rz, r),
- .out_r = tgen_st16_r,
-};
-
-static const TCGOutOpStore outop_st = {
- .base.static_constraint = C_O0_I2(rz, r),
- .out_r = tcg_out_st,
-};
-
-
-static TCGConstraintSetIndex
-tcg_target_op_def(TCGOpcode op, TCGType type, unsigned flags)
-{
- return C_NotImplemented;
-}
-
-static const int tcg_target_callee_save_regs[] = {
- TCG_REG_S0,
- TCG_REG_S1,
- TCG_REG_S2,
- TCG_REG_S3,
- TCG_REG_S4,
- TCG_REG_S5,
- TCG_REG_S6, /* used for the tb base (TCG_REG_TB) */
- TCG_REG_S7, /* used for guest_base */
- TCG_REG_S8, /* used for the global env (TCG_AREG0) */
- TCG_REG_RA, /* should be last for ABI compliance */
-};
-
-/* The Linux kernel doesn't provide any information about the available
- instruction set. Probe it using a signal handler. */
-
-
-#ifndef use_movnz_instructions
-bool use_movnz_instructions = false;
-#endif
-
-#ifndef use_mips32_instructions
-bool use_mips32_instructions = false;
-#endif
-
-#ifndef use_mips32r2_instructions
-bool use_mips32r2_instructions = false;
-#endif
-
-static volatile sig_atomic_t got_sigill;
-
-static void sigill_handler(int signo, siginfo_t *si, void *data)
-{
- /* Skip the faulty instruction */
- ucontext_t *uc = (ucontext_t *)data;
- uc->uc_mcontext.pc += 4;
-
- got_sigill = 1;
-}
-
-static void tcg_target_detect_isa(void)
-{
- struct sigaction sa_old, sa_new;
-
- memset(&sa_new, 0, sizeof(sa_new));
- sa_new.sa_flags = SA_SIGINFO;
- sa_new.sa_sigaction = sigill_handler;
- sigaction(SIGILL, &sa_new, &sa_old);
-
- /* Probe for movn/movz, necessary to implement movcond. */
-#ifndef use_movnz_instructions
- got_sigill = 0;
- asm volatile(".set push\n"
- ".set mips32\n"
- "movn $zero, $zero, $zero\n"
- "movz $zero, $zero, $zero\n"
- ".set pop\n"
- : : : );
- use_movnz_instructions = !got_sigill;
-#endif
-
- /* Probe for MIPS32 instructions. As no subsetting is allowed
- by the specification, it is only necessary to probe for one
- of the instructions. */
-#ifndef use_mips32_instructions
- got_sigill = 0;
- asm volatile(".set push\n"
- ".set mips32\n"
- "mul $zero, $zero\n"
- ".set pop\n"
- : : : );
- use_mips32_instructions = !got_sigill;
-#endif
-
- /* Probe for MIPS32r2 instructions if MIPS32 instructions are
- available. As no subsetting is allowed by the specification,
- it is only necessary to probe for one of the instructions. */
-#ifndef use_mips32r2_instructions
- if (use_mips32_instructions) {
- got_sigill = 0;
- asm volatile(".set push\n"
- ".set mips32r2\n"
- "seb $zero, $zero\n"
- ".set pop\n"
- : : : );
- use_mips32r2_instructions = !got_sigill;
- }
-#endif
-
- sigaction(SIGILL, &sa_old, NULL);
-}
-
-static tcg_insn_unit *align_code_ptr(TCGContext *s)
-{
- uintptr_t p = (uintptr_t)s->code_ptr;
- if (p & 15) {
- p = (p + 15) & -16;
- s->code_ptr = (void *)p;
- }
- return s->code_ptr;
-}
-
-/* Stack frame parameters. */
-#define REG_SIZE 8
-#define SAVE_SIZE ((int)ARRAY_SIZE(tcg_target_callee_save_regs) * REG_SIZE)
-#define TEMP_SIZE (CPU_TEMP_BUF_NLONGS * (int)sizeof(long))
-
-#define FRAME_SIZE ((TCG_STATIC_CALL_ARGS_SIZE + TEMP_SIZE + SAVE_SIZE \
- + TCG_TARGET_STACK_ALIGN - 1) \
- & -TCG_TARGET_STACK_ALIGN)
-#define SAVE_OFS (TCG_STATIC_CALL_ARGS_SIZE + TEMP_SIZE)
-
-/* We're expecting to be able to use an immediate for frame allocation. */
-QEMU_BUILD_BUG_ON(FRAME_SIZE > 0x7fff);
-
-/* Generate global QEMU prologue and epilogue code */
-static void tcg_target_qemu_prologue(TCGContext *s)
-{
- int i;
-
- tcg_set_frame(s, TCG_REG_SP, TCG_STATIC_CALL_ARGS_SIZE, TEMP_SIZE);
-
- /* TB prologue */
- tcg_out_opc_imm(s, OPC_DADDIU, TCG_REG_SP, TCG_REG_SP, -FRAME_SIZE);
- for (i = 0; i < ARRAY_SIZE(tcg_target_callee_save_regs); i++) {
- tcg_out_st(s, TCG_TYPE_REG, tcg_target_callee_save_regs[i],
- TCG_REG_SP, SAVE_OFS + i * REG_SIZE);
- }
-
- if (!tcg_use_softmmu && guest_base != (int16_t)guest_base) {
- /*
- * The function call abi for n32 and n64 will have loaded $25 (t9)
- * with the address of the prologue, so we can use that instead
- * of TCG_REG_TB.
- */
-#if !defined(__mips_abicalls)
-# error "Unknown mips abi"
-#endif
- tcg_out_movi_int(s, TCG_TYPE_PTR, TCG_GUEST_BASE_REG, guest_base,
- TCG_REG_T9);
- tcg_regset_set_reg(s->reserved_regs, TCG_GUEST_BASE_REG);
- }
-
- tcg_out_mov(s, TCG_TYPE_PTR, TCG_REG_TB, tcg_target_call_iarg_regs[1]);
-
- /* Call generated code */
- tcg_out_opc_reg(s, OPC_JR, 0, tcg_target_call_iarg_regs[1], 0);
- /* delay slot */
- tcg_out_mov(s, TCG_TYPE_PTR, TCG_AREG0, tcg_target_call_iarg_regs[0]);
-
- /*
- * Return path for goto_ptr. Set return value to 0, a-la exit_tb,
- * and fall through to the rest of the epilogue.
- */
- tcg_code_gen_epilogue = tcg_splitwx_to_rx(s->code_ptr);
- tcg_out_mov(s, TCG_TYPE_REG, TCG_REG_V0, TCG_REG_ZERO);
-
- /* TB epilogue */
- tb_ret_addr = tcg_splitwx_to_rx(s->code_ptr);
- for (i = 0; i < ARRAY_SIZE(tcg_target_callee_save_regs); i++) {
- tcg_out_ld(s, TCG_TYPE_REG, tcg_target_callee_save_regs[i],
- TCG_REG_SP, SAVE_OFS + i * REG_SIZE);
- }
-
- tcg_out_opc_reg(s, OPC_JR, 0, TCG_REG_RA, 0);
- /* delay slot */
- tcg_out_opc_imm(s, OPC_DADDIU, TCG_REG_SP, TCG_REG_SP, FRAME_SIZE);
-
- if (use_mips32r2_instructions) {
- return;
- }
-
- /* Bswap subroutines: Input in TCG_TMP0, output in TCG_TMP3;
- clobbers TCG_TMP1, TCG_TMP2. */
-
- /*
- * bswap32 -- 32-bit swap (signed result for mips64). a0 = abcd.
- */
- bswap32_addr = tcg_splitwx_to_rx(align_code_ptr(s));
- /* t3 = (ssss)d000 */
- tcg_out_opc_sa(s, OPC_SLL, TCG_TMP3, TCG_TMP0, 24);
- /* t1 = 000a */
- tcg_out_opc_sa(s, OPC_SRL, TCG_TMP1, TCG_TMP0, 24);
- /* t2 = 00c0 */
- tcg_out_opc_imm(s, OPC_ANDI, TCG_TMP2, TCG_TMP0, 0xff00);
- /* t3 = d00a */
- tcg_out_opc_reg(s, OPC_OR, TCG_TMP3, TCG_TMP3, TCG_TMP1);
- /* t1 = 0abc */
- tcg_out_opc_sa(s, OPC_SRL, TCG_TMP1, TCG_TMP0, 8);
- /* t2 = 0c00 */
- tcg_out_opc_sa(s, OPC_SLL, TCG_TMP2, TCG_TMP2, 8);
- /* t1 = 00b0 */
- tcg_out_opc_imm(s, OPC_ANDI, TCG_TMP1, TCG_TMP1, 0xff00);
- /* t3 = dc0a */
- tcg_out_opc_reg(s, OPC_OR, TCG_TMP3, TCG_TMP3, TCG_TMP2);
- tcg_out_opc_reg(s, OPC_JR, 0, TCG_REG_RA, 0);
- /* t3 = dcba -- delay slot */
- tcg_out_opc_reg(s, OPC_OR, TCG_TMP3, TCG_TMP3, TCG_TMP1);
-
- /*
- * bswap32u -- unsigned 32-bit swap. a0 = ....abcd.
- */
- bswap32u_addr = tcg_splitwx_to_rx(align_code_ptr(s));
- /* t1 = (0000)000d */
- tcg_out_opc_imm(s, OPC_ANDI, TCG_TMP1, TCG_TMP0, 0xff);
- /* t3 = 000a */
- tcg_out_opc_sa(s, OPC_SRL, TCG_TMP3, TCG_TMP0, 24);
- /* t1 = (0000)d000 */
- tcg_out_dsll(s, TCG_TMP1, TCG_TMP1, 24);
- /* t2 = 00c0 */
- tcg_out_opc_imm(s, OPC_ANDI, TCG_TMP2, TCG_TMP0, 0xff00);
- /* t3 = d00a */
- tcg_out_opc_reg(s, OPC_OR, TCG_TMP3, TCG_TMP3, TCG_TMP1);
- /* t1 = 0abc */
- tcg_out_opc_sa(s, OPC_SRL, TCG_TMP1, TCG_TMP0, 8);
- /* t2 = 0c00 */
- tcg_out_opc_sa(s, OPC_SLL, TCG_TMP2, TCG_TMP2, 8);
- /* t1 = 00b0 */
- tcg_out_opc_imm(s, OPC_ANDI, TCG_TMP1, TCG_TMP1, 0xff00);
- /* t3 = dc0a */
- tcg_out_opc_reg(s, OPC_OR, TCG_TMP3, TCG_TMP3, TCG_TMP2);
- tcg_out_opc_reg(s, OPC_JR, 0, TCG_REG_RA, 0);
- /* t3 = dcba -- delay slot */
- tcg_out_opc_reg(s, OPC_OR, TCG_TMP3, TCG_TMP3, TCG_TMP1);
-
- /*
- * bswap64 -- 64-bit swap. a0 = abcdefgh
- */
- bswap64_addr = tcg_splitwx_to_rx(align_code_ptr(s));
- /* t3 = h0000000 */
- tcg_out_dsll(s, TCG_TMP3, TCG_TMP0, 56);
- /* t1 = 0000000a */
- tcg_out_dsrl(s, TCG_TMP1, TCG_TMP0, 56);
-
- /* t2 = 000000g0 */
- tcg_out_opc_imm(s, OPC_ANDI, TCG_TMP2, TCG_TMP0, 0xff00);
- /* t3 = h000000a */
- tcg_out_opc_reg(s, OPC_OR, TCG_TMP3, TCG_TMP3, TCG_TMP1);
- /* t1 = 00000abc */
- tcg_out_dsrl(s, TCG_TMP1, TCG_TMP0, 40);
- /* t2 = 0g000000 */
- tcg_out_dsll(s, TCG_TMP2, TCG_TMP2, 40);
- /* t1 = 000000b0 */
- tcg_out_opc_imm(s, OPC_ANDI, TCG_TMP1, TCG_TMP1, 0xff00);
-
- /* t3 = hg00000a */
- tcg_out_opc_reg(s, OPC_OR, TCG_TMP3, TCG_TMP3, TCG_TMP2);
- /* t2 = 0000abcd */
- tcg_out_dsrl(s, TCG_TMP2, TCG_TMP0, 32);
- /* t3 = hg0000ba */
- tcg_out_opc_reg(s, OPC_OR, TCG_TMP3, TCG_TMP3, TCG_TMP1);
-
- /* t1 = 000000c0 */
- tcg_out_opc_imm(s, OPC_ANDI, TCG_TMP1, TCG_TMP2, 0xff00);
- /* t2 = 0000000d */
- tcg_out_opc_imm(s, OPC_ANDI, TCG_TMP2, TCG_TMP2, 0x00ff);
- /* t1 = 00000c00 */
- tcg_out_dsll(s, TCG_TMP1, TCG_TMP1, 8);
- /* t2 = 0000d000 */
- tcg_out_dsll(s, TCG_TMP2, TCG_TMP2, 24);
-
- /* t3 = hg000cba */
- tcg_out_opc_reg(s, OPC_OR, TCG_TMP3, TCG_TMP3, TCG_TMP1);
- /* t1 = 00abcdef */
- tcg_out_dsrl(s, TCG_TMP1, TCG_TMP0, 16);
- /* t3 = hg00dcba */
- tcg_out_opc_reg(s, OPC_OR, TCG_TMP3, TCG_TMP3, TCG_TMP2);
-
- /* t2 = 0000000f */
- tcg_out_opc_imm(s, OPC_ANDI, TCG_TMP2, TCG_TMP1, 0x00ff);
- /* t1 = 000000e0 */
- tcg_out_opc_imm(s, OPC_ANDI, TCG_TMP1, TCG_TMP1, 0xff00);
- /* t2 = 00f00000 */
- tcg_out_dsll(s, TCG_TMP2, TCG_TMP2, 40);
- /* t1 = 000e0000 */
- tcg_out_dsll(s, TCG_TMP1, TCG_TMP1, 24);
-
- /* t3 = hgf0dcba */
- tcg_out_opc_reg(s, OPC_OR, TCG_TMP3, TCG_TMP3, TCG_TMP2);
- tcg_out_opc_reg(s, OPC_JR, 0, TCG_REG_RA, 0);
- /* t3 = hgfedcba -- delay slot */
- tcg_out_opc_reg(s, OPC_OR, TCG_TMP3, TCG_TMP3, TCG_TMP1);
-}
-
-static void tcg_out_tb_start(TCGContext *s)
-{
- /* nothing to do */
-}
-
-static void tcg_target_init(TCGContext *s)
-{
- tcg_target_detect_isa();
- tcg_target_available_regs[TCG_TYPE_I32] = 0xffffffff;
- tcg_target_available_regs[TCG_TYPE_I64] = 0xffffffff;
-
- tcg_target_call_clobber_regs = 0;
- tcg_regset_set_reg(tcg_target_call_clobber_regs, TCG_REG_V0);
- tcg_regset_set_reg(tcg_target_call_clobber_regs, TCG_REG_V1);
- tcg_regset_set_reg(tcg_target_call_clobber_regs, TCG_REG_A0);
- tcg_regset_set_reg(tcg_target_call_clobber_regs, TCG_REG_A1);
- tcg_regset_set_reg(tcg_target_call_clobber_regs, TCG_REG_A2);
- tcg_regset_set_reg(tcg_target_call_clobber_regs, TCG_REG_A3);
- tcg_regset_set_reg(tcg_target_call_clobber_regs, TCG_REG_T0);
- tcg_regset_set_reg(tcg_target_call_clobber_regs, TCG_REG_T1);
- tcg_regset_set_reg(tcg_target_call_clobber_regs, TCG_REG_T2);
- tcg_regset_set_reg(tcg_target_call_clobber_regs, TCG_REG_T3);
- tcg_regset_set_reg(tcg_target_call_clobber_regs, TCG_REG_T4);
- tcg_regset_set_reg(tcg_target_call_clobber_regs, TCG_REG_T5);
- tcg_regset_set_reg(tcg_target_call_clobber_regs, TCG_REG_T6);
- tcg_regset_set_reg(tcg_target_call_clobber_regs, TCG_REG_T7);
- tcg_regset_set_reg(tcg_target_call_clobber_regs, TCG_REG_T8);
- tcg_regset_set_reg(tcg_target_call_clobber_regs, TCG_REG_T9);
-
- s->reserved_regs = 0;
- tcg_regset_set_reg(s->reserved_regs, TCG_REG_ZERO); /* zero register */
- tcg_regset_set_reg(s->reserved_regs, TCG_REG_K0); /* kernel use only */
- tcg_regset_set_reg(s->reserved_regs, TCG_REG_K1); /* kernel use only */
- tcg_regset_set_reg(s->reserved_regs, TCG_TMP0); /* internal use */
- tcg_regset_set_reg(s->reserved_regs, TCG_TMP1); /* internal use */
- tcg_regset_set_reg(s->reserved_regs, TCG_TMP2); /* internal use */
- tcg_regset_set_reg(s->reserved_regs, TCG_TMP3); /* internal use */
- tcg_regset_set_reg(s->reserved_regs, TCG_REG_RA); /* return address */
- tcg_regset_set_reg(s->reserved_regs, TCG_REG_SP); /* stack pointer */
- tcg_regset_set_reg(s->reserved_regs, TCG_REG_GP); /* global pointer */
- tcg_regset_set_reg(s->reserved_regs, TCG_REG_TB); /* tc->tc_ptr */
-}
-
-typedef struct {
- DebugFrameHeader h;
- uint8_t fde_def_cfa[4];
- uint8_t fde_reg_ofs[ARRAY_SIZE(tcg_target_callee_save_regs) * 2];
-} DebugFrame;
-
-#define ELF_HOST_MACHINE EM_MIPS
-/* GDB doesn't appear to require proper setting of ELF_HOST_FLAGS,
- which is good because they're really quite complicated for MIPS. */
-
-static const DebugFrame debug_frame = {
- .h.cie.len = sizeof(DebugFrameCIE) - 4, /* length after .len member */
- .h.cie.id = -1,
- .h.cie.version = 1,
- .h.cie.code_align = 1,
- .h.cie.data_align = -REG_SIZE & 0x7f, /* sleb128 */
- .h.cie.return_column = TCG_REG_RA,
-
- /* Total FDE size does not include the "len" member. */
- .h.fde.len = sizeof(DebugFrame) - offsetof(DebugFrame, h.fde.cie_offset),
-
- .fde_def_cfa = {
- 12, TCG_REG_SP, /* DW_CFA_def_cfa sp, ... */
- (FRAME_SIZE & 0x7f) | 0x80, /* ... uleb128 FRAME_SIZE */
- (FRAME_SIZE >> 7)
- },
- .fde_reg_ofs = {
- 0x80 + 16, 9, /* DW_CFA_offset, s0, -72 */
- 0x80 + 17, 8, /* DW_CFA_offset, s2, -64 */
- 0x80 + 18, 7, /* DW_CFA_offset, s3, -56 */
- 0x80 + 19, 6, /* DW_CFA_offset, s4, -48 */
- 0x80 + 20, 5, /* DW_CFA_offset, s5, -40 */
- 0x80 + 21, 4, /* DW_CFA_offset, s6, -32 */
- 0x80 + 22, 3, /* DW_CFA_offset, s7, -24 */
- 0x80 + 30, 2, /* DW_CFA_offset, s8, -16 */
- 0x80 + 31, 1, /* DW_CFA_offset, ra, -8 */
- }
-};
-
-void tcg_register_jit(const void *buf, size_t buf_size)
-{
- tcg_register_jit_int(buf, buf_size, &debug_frame, sizeof(debug_frame));
-}
diff --git a/common-user/host/mips64/safe-syscall.inc.S b/common-user/host/mips64/safe-syscall.inc.S
deleted file mode 100644
index 3b196cc634c..00000000000
--- a/common-user/host/mips64/safe-syscall.inc.S
+++ /dev/null
@@ -1,114 +0,0 @@
-/*
- * safe-syscall.inc.S : host-specific assembly fragment
- * to handle signals occurring at the same time as system calls.
- * This is intended to be included by common-user/safe-syscall.S
- *
- * Written by Richard Henderson <richard.henderson@linaro.org>
- * Copyright (C) 2021 Linaro, 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 "sys/regdef.h"
-#include "sys/asm.h"
-
- .text
- .set nomips16
- .set reorder
-
- .global safe_syscall_start
- .global safe_syscall_end
- .type safe_syscall_start, @function
- .type safe_syscall_end, @function
-
- /*
- * This is the entry point for making a system call. The calling
- * convention here is that of a C varargs function with the
- * first argument an 'int *' to the signal_pending flag, the
- * second one the system call number (as a 'long'), and all further
- * arguments being syscall arguments (also 'long').
- */
-
-/* 1 * 8 for s0 save; 1 * 8 for align. */
-#define FRAME 16
-#define OFS_S0 0
-
-
-NESTED(safe_syscall_base, FRAME, ra)
- .cfi_startproc
- PTR_ADDIU sp, sp, -FRAME
- .cfi_adjust_cfa_offset FRAME
- REG_S s0, OFS_S0(sp)
- .cfi_rel_offset s0, OFS_S0
- /*
- * The syscall calling convention is nearly the same as C:
- * we enter with a0 == &signal_pending
- * a1 == syscall number
- * a2 ... a7 == syscall arguments
- * and return the result in a0
- * and the syscall instruction needs
- * v0 == syscall number
- * a0 ... a5 == syscall arguments
- * and returns the result in v0
- * Shuffle everything around appropriately.
- */
- move s0, a0 /* signal_pending pointer */
- move v0, a1 /* syscall number */
- move a0, a2 /* syscall arguments */
- move a1, a3
- move a2, a4
- move a3, a5
- move a4, a6
- move a5, a7
-
- /*
- * This next sequence of code works in conjunction with the
- * rewind_if_safe_syscall_function(). If a signal is taken
- * and the interrupted PC is anywhere between 'safe_syscall_start'
- * and 'safe_syscall_end' then we rewind it to 'safe_syscall_start'.
- * The code sequence must therefore be able to cope with this, and
- * the syscall instruction must be the final one in the sequence.
- */
-safe_syscall_start:
- /* If signal_pending is non-zero, don't do the call */
- lw t1, 0(s0)
- bnez t1, 2f
- syscall
-safe_syscall_end:
-
- /* code path for having successfully executed the syscall */
- REG_L s0, OFS_S0(sp)
- PTR_ADDIU sp, sp, FRAME
- .cfi_remember_state
- .cfi_adjust_cfa_offset -FRAME
- .cfi_restore s0
- bnez a3, 1f
- jr ra
- .cfi_restore_state
-
- /* code path when we didn't execute the syscall */
-2: REG_L s0, OFS_S0(sp)
- PTR_ADDIU sp, sp, FRAME
- .cfi_adjust_cfa_offset -FRAME
- .cfi_restore s0
- li v0, QEMU_ERESTARTSYS
-
- /* code path setting errno */
- /*
- * We didn't setup GP on entry, optimistic of the syscall success.
- * We must do so now to load the address of the helper, as required
- * by the ABI, into t9.
- *
- * Note that SETUP_GPX and SETUP_GPX64 are themselves conditional,
- * so we can simply let the one that's not empty succeed.
- */
-1: USE_ALT_CP(t0)
- SETUP_GPX(t1)
- SETUP_GPX64(t0, t1)
- move a0, v0
- PTR_LA t9, safe_syscall_set_errno_tail
- jr t9
-
- .cfi_endproc
-END(safe_syscall_base)
--
2.53.0
^ permalink raw reply related [flat|nested] 35+ messages in thread
* [PULL 08/33] hw/intc/mips_gic: Avoid Coverity complaint in VP writes
2026-05-20 19:23 [PULL 00/33] MIPS patches for 2026-05-20 Philippe Mathieu-Daudé
` (6 preceding siblings ...)
2026-05-20 19:23 ` [PULL 07/33] buildsys: Remove MIPS TCG backend Philippe Mathieu-Daudé
@ 2026-05-20 19:23 ` Philippe Mathieu-Daudé
2026-05-20 19:23 ` [PULL 09/33] linux-user/mips: implement sysmips(MIPS_FLUSH_CACHE) Philippe Mathieu-Daudé
` (25 subsequent siblings)
33 siblings, 0 replies; 35+ messages in thread
From: Philippe Mathieu-Daudé @ 2026-05-20 19:23 UTC (permalink / raw)
To: qemu-devel
From: Peter Maydell <peter.maydell@linaro.org>
The MIPS GIC does a check for a guest error in the write path for the
SH_MAP*_VP registers which triggers a Coverity complaint because it
assigns -1 to a uint64_t. The code doesn't misbehave because the -1
case will be caught by the following OFFSET_CHECK(), but the code
could be improved:
* there is no need to special case to avoid passing 0 to ctz64(),
because (unlike the compiler builtins) QEMU defines that this
has a specific behaviour, returning 64
* the OFFSET_CHECK() macro will go to the "bad_offset" label and
print an error implying that the guest wrote to an invalid
register offset. This is misleading about the actual problem,
which is that the guest wrote a bogus value to a valid register
offset
Make the error check print a better log message, and avoid the
special casing on ctz64(); in passing, this should also make
Coverity happier.
CID: 1547545
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
Message-ID: <20260512111536.3437645-1-peter.maydell@linaro.org>
Signed-off-by: Philippe Mathieu-Daudé <philmd@linaro.org>
---
hw/intc/mips_gic.c | 10 +++++++---
1 file changed, 7 insertions(+), 3 deletions(-)
diff --git a/hw/intc/mips_gic.c b/hw/intc/mips_gic.c
index 23478df4b46..4777c70d6b4 100644
--- a/hw/intc/mips_gic.c
+++ b/hw/intc/mips_gic.c
@@ -317,9 +317,13 @@ static void gic_write(void *opaque, hwaddr addr, uint64_t data, unsigned size)
/* up to 32 bytes per a pin */
irq_src = (addr - GIC_SH_MAP0_VP_OFS) / 32;
OFFSET_CHECK(irq_src < gic->num_irq);
- data = data ? ctz64(data) : -1;
- OFFSET_CHECK(data < gic->num_vps);
- gic->irq_state[irq_src].map_vp = data;
+ if (ctz64(data) >= gic->num_vps) {
+ qemu_log_mask(LOG_GUEST_ERROR, "Bad data value 0x%" PRIx64
+ " at MAP VP register offset 0x%" PRIx64 "\n",
+ data, addr);
+ break;
+ }
+ gic->irq_state[irq_src].map_vp = ctz64(data);
break;
case VP_LOCAL_SECTION_OFS ... (VP_LOCAL_SECTION_OFS + GIC_VL_BRK_GROUP):
gic_write_vp(gic, vp_index, addr - VP_LOCAL_SECTION_OFS, data, size);
--
2.53.0
^ permalink raw reply related [flat|nested] 35+ messages in thread
* [PULL 09/33] linux-user/mips: implement sysmips(MIPS_FLUSH_CACHE)
2026-05-20 19:23 [PULL 00/33] MIPS patches for 2026-05-20 Philippe Mathieu-Daudé
` (7 preceding siblings ...)
2026-05-20 19:23 ` [PULL 08/33] hw/intc/mips_gic: Avoid Coverity complaint in VP writes Philippe Mathieu-Daudé
@ 2026-05-20 19:23 ` Philippe Mathieu-Daudé
2026-05-20 19:23 ` [PULL 10/33] linux-user/mips: implement sysmips(MIPS_ATOMIC_SET) Philippe Mathieu-Daudé
` (24 subsequent siblings)
33 siblings, 0 replies; 35+ messages in thread
From: Philippe Mathieu-Daudé @ 2026-05-20 19:23 UTC (permalink / raw)
To: qemu-devel
From: James Hilliard <james.hilliard1@gmail.com>
Add the target sysmips dispatcher and implement MIPS_FLUSH_CACHE as a
successful no-op for linux-user.
Self-modifying code is handled by QEMU's normal user-mode translation
invalidation machinery, so the target ABI only needs the syscall command
to be accepted.
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
Signed-off-by: James Hilliard <james.hilliard1@gmail.com>
Signed-off-by: Philippe Mathieu-Daudé <philmd@linaro.org>
Message-Id: <20260520172313.23777-2-philmd@linaro.org>
---
linux-user/mips/target_syscall.h | 1 +
linux-user/mips64/target_syscall.h | 1 +
linux-user/syscall.c | 17 +++++++++++++++++
3 files changed, 19 insertions(+)
diff --git a/linux-user/mips/target_syscall.h b/linux-user/mips/target_syscall.h
index dfcdf320b7c..3f36c1695a5 100644
--- a/linux-user/mips/target_syscall.h
+++ b/linux-user/mips/target_syscall.h
@@ -10,6 +10,7 @@
#define TARGET_MCL_ONFAULT 4
#define TARGET_FORCE_SHMLBA
+#define TARGET_SYSMIPS_FLUSH_CACHE 3
static inline abi_ulong target_shmlba(CPUMIPSState *env)
{
diff --git a/linux-user/mips64/target_syscall.h b/linux-user/mips64/target_syscall.h
index 9135bf5e8b6..20ea7c6ab9b 100644
--- a/linux-user/mips64/target_syscall.h
+++ b/linux-user/mips64/target_syscall.h
@@ -10,6 +10,7 @@
#define TARGET_MCL_ONFAULT 4
#define TARGET_FORCE_SHMLBA
+#define TARGET_SYSMIPS_FLUSH_CACHE 3
static inline abi_ulong target_shmlba(CPUMIPSState *env)
{
diff --git a/linux-user/syscall.c b/linux-user/syscall.c
index 2d4a8aa182b..5a8e00337a0 100644
--- a/linux-user/syscall.c
+++ b/linux-user/syscall.c
@@ -6630,6 +6630,19 @@ static abi_long do_prctl_syscall_user_dispatch(CPUArchState *env,
}
}
+#ifdef TARGET_NR_sysmips
+static abi_long do_sysmips(CPUArchState *env, abi_long cmd, abi_long arg1,
+ abi_long arg2)
+{
+ switch (cmd) {
+ case TARGET_SYSMIPS_FLUSH_CACHE:
+ return 0;
+ default:
+ return -TARGET_EINVAL;
+ }
+}
+#endif
+
static abi_long do_prctl(CPUArchState *env, abi_long option, abi_long arg2,
abi_long arg3, abi_long arg4, abi_long arg5)
{
@@ -12110,6 +12123,10 @@ static abi_long do_syscall1(CPUArchState *cpu_env, int num, abi_long arg1,
case TARGET_NR_prctl:
return do_prctl(cpu_env, arg1, arg2, arg3, arg4, arg5);
break;
+#ifdef TARGET_NR_sysmips
+ case TARGET_NR_sysmips:
+ return do_sysmips(cpu_env, arg1, arg2, arg3);
+#endif
#ifdef TARGET_NR_arch_prctl
case TARGET_NR_arch_prctl:
return do_arch_prctl(cpu_env, arg1, arg2);
--
2.53.0
^ permalink raw reply related [flat|nested] 35+ messages in thread
* [PULL 10/33] linux-user/mips: implement sysmips(MIPS_ATOMIC_SET)
2026-05-20 19:23 [PULL 00/33] MIPS patches for 2026-05-20 Philippe Mathieu-Daudé
` (8 preceding siblings ...)
2026-05-20 19:23 ` [PULL 09/33] linux-user/mips: implement sysmips(MIPS_FLUSH_CACHE) Philippe Mathieu-Daudé
@ 2026-05-20 19:23 ` Philippe Mathieu-Daudé
2026-05-20 19:23 ` [PULL 11/33] linux-user/mips, target/mips: honor MIPS_FIXADE for unaligned accesses Philippe Mathieu-Daudé
` (23 subsequent siblings)
33 siblings, 0 replies; 35+ messages in thread
From: Philippe Mathieu-Daudé @ 2026-05-20 19:23 UTC (permalink / raw)
To: qemu-devel
From: James Hilliard <james.hilliard1@gmail.com>
Implement the MIPS_ATOMIC_SET sysmips command as an aligned 32-bit atomic
exchange in target memory.
MIPS reports syscall errors through a separate register, so successful old
values can overlap the errno range. Write the return value and error flag
directly and return -QEMU_ESIGRETURN so the common syscall path leaves the
registers unchanged.
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
Signed-off-by: James Hilliard <james.hilliard1@gmail.com>
Signed-off-by: Philippe Mathieu-Daudé <philmd@linaro.org>
Message-Id: <20260520172313.23777-3-philmd@linaro.org>
---
linux-user/mips/target_syscall.h | 1 +
linux-user/mips64/target_syscall.h | 1 +
linux-user/syscall.c | 31 ++++++++++++++++++++++++++++++
3 files changed, 33 insertions(+)
diff --git a/linux-user/mips/target_syscall.h b/linux-user/mips/target_syscall.h
index 3f36c1695a5..9206694f4fb 100644
--- a/linux-user/mips/target_syscall.h
+++ b/linux-user/mips/target_syscall.h
@@ -11,6 +11,7 @@
#define TARGET_FORCE_SHMLBA
#define TARGET_SYSMIPS_FLUSH_CACHE 3
+#define TARGET_SYSMIPS_ATOMIC_SET 2001
static inline abi_ulong target_shmlba(CPUMIPSState *env)
{
diff --git a/linux-user/mips64/target_syscall.h b/linux-user/mips64/target_syscall.h
index 20ea7c6ab9b..e07687f8ac9 100644
--- a/linux-user/mips64/target_syscall.h
+++ b/linux-user/mips64/target_syscall.h
@@ -11,6 +11,7 @@
#define TARGET_FORCE_SHMLBA
#define TARGET_SYSMIPS_FLUSH_CACHE 3
+#define TARGET_SYSMIPS_ATOMIC_SET 2001
static inline abi_ulong target_shmlba(CPUMIPSState *env)
{
diff --git a/linux-user/syscall.c b/linux-user/syscall.c
index 5a8e00337a0..3df42aa159d 100644
--- a/linux-user/syscall.c
+++ b/linux-user/syscall.c
@@ -6631,10 +6631,41 @@ static abi_long do_prctl_syscall_user_dispatch(CPUArchState *env,
}
#ifdef TARGET_NR_sysmips
+static abi_long do_sysmips_atomic_set(CPUArchState *env, abi_ulong addr,
+ abi_long value)
+{
+ uint32_t *ptr;
+ abi_long old;
+
+ if (addr & 3) {
+ return -TARGET_EINVAL;
+ }
+
+ ptr = lock_user(VERIFY_WRITE, addr, sizeof(*ptr), true);
+ if (!ptr) {
+ return -TARGET_EINVAL;
+ }
+
+ old = tswap32(qatomic_xchg(ptr, tswap32((uint32_t)value)));
+ unlock_user(ptr, addr, sizeof(*ptr));
+
+ /*
+ * MIPS uses a separate error flag, but the common linux-user syscall
+ * path infers that flag from the return value. Successful atomic_set
+ * results can overlap the target errno range, so write the result
+ * registers here and ask the CPU loop to leave them alone.
+ */
+ env->active_tc.gpr[2] = old;
+ env->active_tc.gpr[7] = 0;
+ return -QEMU_ESIGRETURN;
+}
+
static abi_long do_sysmips(CPUArchState *env, abi_long cmd, abi_long arg1,
abi_long arg2)
{
switch (cmd) {
+ case TARGET_SYSMIPS_ATOMIC_SET:
+ return do_sysmips_atomic_set(env, arg1, arg2);
case TARGET_SYSMIPS_FLUSH_CACHE:
return 0;
default:
--
2.53.0
^ permalink raw reply related [flat|nested] 35+ messages in thread
* [PULL 11/33] linux-user/mips, target/mips: honor MIPS_FIXADE for unaligned accesses
2026-05-20 19:23 [PULL 00/33] MIPS patches for 2026-05-20 Philippe Mathieu-Daudé
` (9 preceding siblings ...)
2026-05-20 19:23 ` [PULL 10/33] linux-user/mips: implement sysmips(MIPS_ATOMIC_SET) Philippe Mathieu-Daudé
@ 2026-05-20 19:23 ` Philippe Mathieu-Daudé
2026-05-20 19:23 ` [PULL 12/33] target/mips: expose Octeon68XX floating-point support Philippe Mathieu-Daudé
` (22 subsequent siblings)
33 siblings, 0 replies; 35+ messages in thread
From: Philippe Mathieu-Daudé @ 2026-05-20 19:23 UTC (permalink / raw)
To: qemu-devel
From: James Hilliard <james.hilliard1@gmail.com>
Linux/MIPS enables software fixups for user-mode unaligned scalar
accesses by default through MIPS_FIXADE/TIF_FIXADE. QEMU linux-user did
not model that ABI, so MIPS guests took fatal AdEL/AdES exceptions unless
translation was forced to use unaligned host accesses.
Key MIPS translation blocks on the linux-user unaligned policy, implement
sysmips(MIPS_FIXADE) to toggle that policy, and raise SIGBUS/BUS_ADRALN
when fixups are disabled.
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
Signed-off-by: James Hilliard <james.hilliard1@gmail.com>
Signed-off-by: Philippe Mathieu-Daudé <philmd@linaro.org>
Message-Id: <20260520172313.23777-4-philmd@linaro.org>
---
linux-user/mips/target_syscall.h | 1 +
linux-user/mips64/target_syscall.h | 1 +
target/mips/cpu.h | 4 ++++
linux-user/mips/cpu_loop.c | 5 +++++
linux-user/syscall.c | 8 ++++++++
target/mips/cpu.c | 10 ++++++++--
target/mips/tcg/translate.c | 6 +++++-
7 files changed, 32 insertions(+), 3 deletions(-)
diff --git a/linux-user/mips/target_syscall.h b/linux-user/mips/target_syscall.h
index 9206694f4fb..be6942445a2 100644
--- a/linux-user/mips/target_syscall.h
+++ b/linux-user/mips/target_syscall.h
@@ -11,6 +11,7 @@
#define TARGET_FORCE_SHMLBA
#define TARGET_SYSMIPS_FLUSH_CACHE 3
+#define TARGET_SYSMIPS_FIXADE 7
#define TARGET_SYSMIPS_ATOMIC_SET 2001
static inline abi_ulong target_shmlba(CPUMIPSState *env)
diff --git a/linux-user/mips64/target_syscall.h b/linux-user/mips64/target_syscall.h
index e07687f8ac9..c11d0a08888 100644
--- a/linux-user/mips64/target_syscall.h
+++ b/linux-user/mips64/target_syscall.h
@@ -11,6 +11,7 @@
#define TARGET_FORCE_SHMLBA
#define TARGET_SYSMIPS_FLUSH_CACHE 3
+#define TARGET_SYSMIPS_FIXADE 7
#define TARGET_SYSMIPS_ATOMIC_SET 2001
static inline abi_ulong target_shmlba(CPUMIPSState *env)
diff --git a/target/mips/cpu.h b/target/mips/cpu.h
index cbb9b3e1b1c..b478f834c13 100644
--- a/target/mips/cpu.h
+++ b/target/mips/cpu.h
@@ -1161,6 +1161,10 @@ typedef struct CPUArchState {
#define MIPS_HFLAG_ELPA 0x4000000
#define MIPS_HFLAG_ITC_CACHE 0x8000000 /* CACHE instr. operates on ITC tag */
#define MIPS_HFLAG_ERL 0x10000000 /* error level flag */
+#define MIPS_HFLAG_TB_MASK (MIPS_HFLAG_TMASK | MIPS_HFLAG_BMASK | \
+ MIPS_HFLAG_HWRENA_ULR)
+
+#define TB_FLAG_MIPS_FIXADE 0x40000000
target_ulong btarget; /* Jump / branch target */
target_ulong bcond; /* Branch condition (if needed) */
diff --git a/linux-user/mips/cpu_loop.c b/linux-user/mips/cpu_loop.c
index fa264b27ec5..ff9d293c296 100644
--- a/linux-user/mips/cpu_loop.c
+++ b/linux-user/mips/cpu_loop.c
@@ -161,6 +161,11 @@ done_syscall:
case EXCP_DSPDIS:
force_sig(TARGET_SIGILL);
break;
+ case EXCP_AdEL:
+ case EXCP_AdES:
+ force_sig_fault(TARGET_SIGBUS, TARGET_BUS_ADRALN,
+ env->CP0_BadVAddr);
+ break;
case EXCP_INTERRUPT:
/* just indicate that signals should be handled asap */
break;
diff --git a/linux-user/syscall.c b/linux-user/syscall.c
index 3df42aa159d..7d7a7b489cf 100644
--- a/linux-user/syscall.c
+++ b/linux-user/syscall.c
@@ -6663,9 +6663,17 @@ static abi_long do_sysmips_atomic_set(CPUArchState *env, abi_ulong addr,
static abi_long do_sysmips(CPUArchState *env, abi_long cmd, abi_long arg1,
abi_long arg2)
{
+ CPUState *cs = env_cpu(env);
+
switch (cmd) {
case TARGET_SYSMIPS_ATOMIC_SET:
return do_sysmips_atomic_set(env, arg1, arg2);
+ case TARGET_SYSMIPS_FIXADE:
+ if (arg1 & ~3) {
+ return -TARGET_EINVAL;
+ }
+ cs->prctl_unalign_sigbus = !(arg1 & 1);
+ return 0;
case TARGET_SYSMIPS_FLUSH_CACHE:
return 0;
default:
diff --git a/target/mips/cpu.c b/target/mips/cpu.c
index 99d43613828..fccc7a711d3 100644
--- a/target/mips/cpu.c
+++ b/target/mips/cpu.c
@@ -560,11 +560,17 @@ static int mips_cpu_mmu_index(CPUState *cs, bool ifunc)
static TCGTBCPUState mips_get_tb_cpu_state(CPUState *cs)
{
CPUMIPSState *env = cpu_env(cs);
+ uint32_t flags = env->hflags & MIPS_HFLAG_TB_MASK;
+
+#ifdef CONFIG_USER_ONLY
+ if (!cs->prctl_unalign_sigbus) {
+ flags |= TB_FLAG_MIPS_FIXADE;
+ }
+#endif
return (TCGTBCPUState){
.pc = env->active_tc.PC,
- .flags = env->hflags & (MIPS_HFLAG_TMASK | MIPS_HFLAG_BMASK |
- MIPS_HFLAG_HWRENA_ULR),
+ .flags = flags,
};
}
diff --git a/target/mips/tcg/translate.c b/target/mips/tcg/translate.c
index 54ed253a7d0..dac30aff8d3 100644
--- a/target/mips/tcg/translate.c
+++ b/target/mips/tcg/translate.c
@@ -15070,6 +15070,7 @@ static void mips_tr_init_disas_context(DisasContextBase *dcbase, CPUState *cs)
{
DisasContext *ctx = container_of(dcbase, DisasContext, base);
CPUMIPSState *env = cpu_env(cs);
+ uint32_t tb_flags = ctx->base.tb->flags;
ctx->page_start = ctx->base.pc_first & TARGET_PAGE_MASK;
ctx->saved_pc = -1;
@@ -15092,7 +15093,7 @@ static void mips_tr_init_disas_context(DisasContextBase *dcbase, CPUState *cs)
ctx->CP0_LLAddr_shift = env->CP0_LLAddr_shift;
ctx->cmgcr = (env->CP0_Config3 >> CP0C3_CMGCR) & 1;
/* Restore delay slot state from the tb context. */
- ctx->hflags = (uint32_t)ctx->base.tb->flags; /* FIXME: maybe use 64 bits? */
+ ctx->hflags = tb_flags & MIPS_HFLAG_TB_MASK;
ctx->ulri = (env->CP0_Config3 >> CP0C3_ULRI) & 1;
ctx->ps = ((env->active_fpu.fcr0 >> FCR0_PS) & 1) ||
(env->insn_flags & (INSN_LOONGSON2E | INSN_LOONGSON2F));
@@ -15112,6 +15113,9 @@ static void mips_tr_init_disas_context(DisasContextBase *dcbase, CPUState *cs)
ctx->default_tcg_memop_mask = (!(ctx->insn_flags & ISA_NANOMIPS32) &&
(ctx->insn_flags & (ISA_MIPS_R6 |
INSN_LOONGSON3A))) ? MO_UNALN : MO_ALIGN;
+ if (tb_flags & TB_FLAG_MIPS_FIXADE) {
+ ctx->default_tcg_memop_mask = MO_UNALN;
+ }
/*
* Execute a branch and its delay slot as a single instruction.
--
2.53.0
^ permalink raw reply related [flat|nested] 35+ messages in thread
* [PULL 12/33] target/mips: expose Octeon68XX floating-point support
2026-05-20 19:23 [PULL 00/33] MIPS patches for 2026-05-20 Philippe Mathieu-Daudé
` (10 preceding siblings ...)
2026-05-20 19:23 ` [PULL 11/33] linux-user/mips, target/mips: honor MIPS_FIXADE for unaligned accesses Philippe Mathieu-Daudé
@ 2026-05-20 19:23 ` Philippe Mathieu-Daudé
2026-05-20 19:23 ` [PULL 13/33] tests/tcg/mips: add Octeon instruction smoke test Philippe Mathieu-Daudé
` (21 subsequent siblings)
33 siblings, 0 replies; 35+ messages in thread
From: Philippe Mathieu-Daudé @ 2026-05-20 19:23 UTC (permalink / raw)
To: qemu-devel
From: James Hilliard <james.hilliard1@gmail.com>
Octeon68XX cores implement CP1. Advertise that in the CPU definition by
setting Config1.FP, enabling the writable Status bits, and providing the
FCR0/FCR31 defaults used by this CPU model.
This lets guests observe the expected floating-point feature bits and use
CP1 with -cpu Octeon68XX.
Signed-off-by: James Hilliard <james.hilliard1@gmail.com>
Tested-by: Philippe Mathieu-Daudé <philmd@linaro.org>
Signed-off-by: Philippe Mathieu-Daudé <philmd@linaro.org>
Message-Id: <20260520172313.23777-5-philmd@linaro.org>
---
target/mips/cpu-defs.c.inc | 10 ++++++++--
1 file changed, 8 insertions(+), 2 deletions(-)
diff --git a/target/mips/cpu-defs.c.inc b/target/mips/cpu-defs.c.inc
index faefab04738..cc1916232f5 100644
--- a/target/mips/cpu-defs.c.inc
+++ b/target/mips/cpu-defs.c.inc
@@ -997,7 +997,8 @@ const mips_def_t mips_defs[] =
.CP0_PRid = 0x000D9100,
.CP0_Config0 = MIPS_CONFIG0 | (0x1 << CP0C0_AR) | (0x2 << CP0C0_AT) |
(MMU_TYPE_R4000 << CP0C0_MT),
- .CP0_Config1 = MIPS_CONFIG1 | (0x3F << CP0C1_MMU) |
+ .CP0_Config1 = MIPS_CONFIG1 | (1 << CP0C1_FP) |
+ (0x3F << CP0C1_MMU) |
(1 << CP0C1_IS) | (4 << CP0C1_IL) | (1 << CP0C1_IA) |
(1 << CP0C1_DS) | (4 << CP0C1_DL) | (1 << CP0C1_DA) |
(1 << CP0C1_PC) | (1 << CP0C1_WR) | (1 << CP0C1_EP),
@@ -1011,7 +1012,12 @@ const mips_def_t mips_defs[] =
.CP0_PageGrain = (1 << CP0PG_ELPA),
.SYNCI_Step = 32,
.CCRes = 2,
- .CP0_Status_rw_bitmask = 0x12F8FFFF,
+ .CP0_Status_rw_bitmask = 0x36F8FFFF,
+ .CP1_fcr0 = (1 << FCR0_F64) | (1 << FCR0_3D) | (1 << FCR0_PS) |
+ (1 << FCR0_L) | (1 << FCR0_W) | (1 << FCR0_D) |
+ (1 << FCR0_S) | (0x00 << FCR0_PRID) | (0x0 << FCR0_REV),
+ .CP1_fcr31 = 0,
+ .CP1_fcr31_rw_bitmask = 0xFF83FFFF,
.SEGBITS = 42,
.PABITS = 49,
.insn_flags = CPU_MIPS64R2 | INSN_OCTEON,
--
2.53.0
^ permalink raw reply related [flat|nested] 35+ messages in thread
* [PULL 13/33] tests/tcg/mips: add Octeon instruction smoke test
2026-05-20 19:23 [PULL 00/33] MIPS patches for 2026-05-20 Philippe Mathieu-Daudé
` (11 preceding siblings ...)
2026-05-20 19:23 ` [PULL 12/33] target/mips: expose Octeon68XX floating-point support Philippe Mathieu-Daudé
@ 2026-05-20 19:23 ` Philippe Mathieu-Daudé
2026-05-20 19:23 ` [PULL 14/33] target/mips: fix Octeon arithmetic destination handling Philippe Mathieu-Daudé
` (20 subsequent siblings)
33 siblings, 0 replies; 35+ messages in thread
From: Philippe Mathieu-Daudé @ 2026-05-20 19:23 UTC (permalink / raw)
To: qemu-devel
From: James Hilliard <james.hilliard1@gmail.com>
Add a mips64/mips64el linux-user TCG smoke test for representative
Octeon instruction paths.
Run the test with -cpu Octeon68XX and share the source between the
mips64 and mips64el target directories.
Signed-off-by: James Hilliard <james.hilliard1@gmail.com>
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
Signed-off-by: Philippe Mathieu-Daudé <philmd@linaro.org>
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
Message-Id: <20260520172313.23777-6-philmd@linaro.org>
---
MAINTAINERS | 2 +-
tests/tcg/mips/user/isa/octeon/octeon-insns.c | 13 ++++++++++++
tests/tcg/mips64/Makefile.target | 20 +++++++++++++++++++
tests/tcg/mips64el/Makefile.target | 8 ++++++++
4 files changed, 42 insertions(+), 1 deletion(-)
create mode 100644 tests/tcg/mips/user/isa/octeon/octeon-insns.c
create mode 100644 tests/tcg/mips64/Makefile.target
create mode 100644 tests/tcg/mips64el/Makefile.target
diff --git a/MAINTAINERS b/MAINTAINERS
index 7496ace6d5a..0600d494588 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -310,7 +310,7 @@ S: Odd Fixes
F: target/mips/
F: disas/*mips.c
F: docs/system/cpu-models-mips.rst.inc
-F: tests/tcg/mips/
+F: tests/tcg/mips*/
OpenRISC TCG CPUs
M: Stafford Horne <shorne@gmail.com>
diff --git a/tests/tcg/mips/user/isa/octeon/octeon-insns.c b/tests/tcg/mips/user/isa/octeon/octeon-insns.c
new file mode 100644
index 00000000000..aef23fb9465
--- /dev/null
+++ b/tests/tcg/mips/user/isa/octeon/octeon-insns.c
@@ -0,0 +1,13 @@
+/*
+ * Test Octeon-specific user-mode instructions.
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ */
+
+#include <assert.h>
+#include <stdint.h>
+
+int main(void)
+{
+ return 0;
+}
diff --git a/tests/tcg/mips64/Makefile.target b/tests/tcg/mips64/Makefile.target
new file mode 100644
index 00000000000..042855844a8
--- /dev/null
+++ b/tests/tcg/mips64/Makefile.target
@@ -0,0 +1,20 @@
+# -*- Mode: makefile -*-
+#
+# SPDX-License-Identifier: GPL-2.0-or-later
+#
+# MIPS64 - included from tests/tcg/Makefile.target
+#
+
+MIPS64_SRC=$(SRC_PATH)/tests/tcg/mips64
+MIPS_OCTEON_SRC=$(SRC_PATH)/tests/tcg/mips/user/isa/octeon
+
+# Set search path for all sources
+VPATH += $(MIPS64_SRC) $(MIPS_OCTEON_SRC)
+
+MIPS64_TESTS=octeon-insns
+
+TESTS += $(MIPS64_TESTS)
+
+$(MIPS64_TESTS): CFLAGS+=-mabi=64
+
+run-octeon-insns: QEMU_OPTS+=-cpu Octeon68XX
diff --git a/tests/tcg/mips64el/Makefile.target b/tests/tcg/mips64el/Makefile.target
new file mode 100644
index 00000000000..dbc5f8dc5fe
--- /dev/null
+++ b/tests/tcg/mips64el/Makefile.target
@@ -0,0 +1,8 @@
+# -*- Mode: makefile -*-
+#
+# SPDX-License-Identifier: GPL-2.0-or-later
+#
+# MIPS64 little-endian - included from tests/tcg/Makefile.target
+#
+
+include $(SRC_PATH)/tests/tcg/mips64/Makefile.target
--
2.53.0
^ permalink raw reply related [flat|nested] 35+ messages in thread
* [PULL 14/33] target/mips: fix Octeon arithmetic destination handling
2026-05-20 19:23 [PULL 00/33] MIPS patches for 2026-05-20 Philippe Mathieu-Daudé
` (12 preceding siblings ...)
2026-05-20 19:23 ` [PULL 13/33] tests/tcg/mips: add Octeon instruction smoke test Philippe Mathieu-Daudé
@ 2026-05-20 19:23 ` Philippe Mathieu-Daudé
2026-05-20 19:23 ` [PULL 15/33] target/mips: drop Octeon zero-register fast paths Philippe Mathieu-Daudé
` (19 subsequent siblings)
33 siblings, 0 replies; 35+ messages in thread
From: Philippe Mathieu-Daudé @ 2026-05-20 19:23 UTC (permalink / raw)
To: qemu-devel
From: James Hilliard <james.hilliard1@gmail.com>
BADDU and DMUL write their results to rd, not rt. Route writes through
gen_store_gpr() so rd == $zero is handled consistently.
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
Signed-off-by: James Hilliard <james.hilliard1@gmail.com>
Signed-off-by: Philippe Mathieu-Daudé <philmd@linaro.org>
Message-Id: <20260520172313.23777-7-philmd@linaro.org>
---
target/mips/tcg/octeon_translate.c | 16 +++------
tests/tcg/mips/user/isa/octeon/octeon-insns.c | 35 +++++++++++++++++++
2 files changed, 39 insertions(+), 12 deletions(-)
diff --git a/target/mips/tcg/octeon_translate.c b/target/mips/tcg/octeon_translate.c
index e1f52d444aa..4dd76268350 100644
--- a/target/mips/tcg/octeon_translate.c
+++ b/target/mips/tcg/octeon_translate.c
@@ -45,18 +45,14 @@ static bool trans_BADDU(DisasContext *ctx, arg_BADDU *a)
{
TCGv_i64 t0, t1;
- if (a->rt == 0) {
- /* nop */
- return true;
- }
-
t0 = tcg_temp_new_i64();
t1 = tcg_temp_new_i64();
gen_load_gpr(t0, a->rs);
gen_load_gpr(t1, a->rt);
tcg_gen_add_i64(t0, t0, t1);
- tcg_gen_andi_i64(cpu_gpr[a->rd], t0, 0xff);
+ tcg_gen_andi_i64(t0, t0, 0xff);
+ gen_store_gpr(t0, a->rd);
return true;
}
@@ -64,17 +60,13 @@ static bool trans_DMUL(DisasContext *ctx, arg_DMUL *a)
{
TCGv_i64 t0, t1;
- if (a->rt == 0) {
- /* nop */
- return true;
- }
-
t0 = tcg_temp_new_i64();
t1 = tcg_temp_new_i64();
gen_load_gpr(t0, a->rs);
gen_load_gpr(t1, a->rt);
- tcg_gen_mul_i64(cpu_gpr[a->rd], t0, t1);
+ tcg_gen_mul_i64(t0, t0, t1);
+ gen_store_gpr(t0, a->rd);
return true;
}
diff --git a/tests/tcg/mips/user/isa/octeon/octeon-insns.c b/tests/tcg/mips/user/isa/octeon/octeon-insns.c
index aef23fb9465..b7610db812e 100644
--- a/tests/tcg/mips/user/isa/octeon/octeon-insns.c
+++ b/tests/tcg/mips/user/isa/octeon/octeon-insns.c
@@ -7,7 +7,42 @@
#include <assert.h>
#include <stdint.h>
+static uint64_t octeon_baddu(uint64_t rs, uint64_t rt)
+{
+ uint64_t rd;
+
+ asm volatile(
+ "move $8, %[rs]\n\t"
+ "move $9, %[rt]\n\t"
+ ".word 0x71095028\n\t" /* baddu $10, $8, $9 */
+ "move %[rd], $10\n\t"
+ : [rd] "=r" (rd)
+ : [rs] "r" (rs), [rt] "r" (rt)
+ : "$8", "$9", "$10");
+
+ return rd;
+}
+
+static uint64_t octeon_dmul(uint64_t rs, uint64_t rt)
+{
+ uint64_t rd;
+
+ asm volatile(
+ "move $8, %[rs]\n\t"
+ "move $9, %[rt]\n\t"
+ ".word 0x71095003\n\t" /* dmul $10, $8, $9 */
+ "move %[rd], $10\n\t"
+ : [rd] "=r" (rd)
+ : [rs] "r" (rs), [rt] "r" (rt)
+ : "$8", "$9", "$10");
+
+ return rd;
+}
+
int main(void)
{
+ assert(octeon_baddu(0x123, 0x0f0) == 0x13);
+ assert(octeon_dmul(0x12345678, 0x10) == 0x123456780);
+
return 0;
}
--
2.53.0
^ permalink raw reply related [flat|nested] 35+ messages in thread
* [PULL 15/33] target/mips: drop Octeon zero-register fast paths
2026-05-20 19:23 [PULL 00/33] MIPS patches for 2026-05-20 Philippe Mathieu-Daudé
` (13 preceding siblings ...)
2026-05-20 19:23 ` [PULL 14/33] target/mips: fix Octeon arithmetic destination handling Philippe Mathieu-Daudé
@ 2026-05-20 19:23 ` Philippe Mathieu-Daudé
2026-05-20 19:23 ` [PULL 16/33] target/mips: split Octeon SEQ/SNE decode Philippe Mathieu-Daudé
` (18 subsequent siblings)
33 siblings, 0 replies; 35+ messages in thread
From: Philippe Mathieu-Daudé @ 2026-05-20 19:23 UTC (permalink / raw)
To: qemu-devel
From: James Hilliard <james.hilliard1@gmail.com>
EXTS, CINS, and POP route their destination writes through
gen_store_gpr(), which already discards writes to $zero. Remove the
remaining translator fast paths for destination $zero so these Octeon
instructions follow the same shape as BADDU/DMUL and the generic MIPS
translator helpers.
Add a mips64/mips64el linux-user TCG smoke test for representative
Octeon population count instruction paths.
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
Signed-off-by: James Hilliard <james.hilliard1@gmail.com>
Signed-off-by: Philippe Mathieu-Daudé <philmd@linaro.org>
Message-Id: <20260520172313.23777-8-philmd@linaro.org>
---
target/mips/tcg/octeon_translate.c | 15 ---------------
tests/tcg/mips/user/isa/octeon/octeon-insns.c | 16 ++++++++++++++++
2 files changed, 16 insertions(+), 15 deletions(-)
diff --git a/target/mips/tcg/octeon_translate.c b/target/mips/tcg/octeon_translate.c
index 4dd76268350..b7531653e58 100644
--- a/target/mips/tcg/octeon_translate.c
+++ b/target/mips/tcg/octeon_translate.c
@@ -74,11 +74,6 @@ static bool trans_EXTS(DisasContext *ctx, arg_EXTS *a)
{
TCGv_i64 t0;
- if (a->rt == 0) {
- /* nop */
- return true;
- }
-
t0 = tcg_temp_new_i64();
gen_load_gpr(t0, a->rs);
tcg_gen_sextract_i64(t0, t0, a->p, a->lenm1 + 1);
@@ -90,11 +85,6 @@ static bool trans_CINS(DisasContext *ctx, arg_CINS *a)
{
TCGv_i64 t0;
- if (a->rt == 0) {
- /* nop */
- return true;
- }
-
t0 = tcg_temp_new_i64();
gen_load_gpr(t0, a->rs);
tcg_gen_deposit_z_i64(t0, t0, a->p, a->lenm1 + 1);
@@ -106,11 +96,6 @@ static bool trans_POP(DisasContext *ctx, arg_POP *a)
{
TCGv_i64 t0;
- if (a->rd == 0) {
- /* nop */
- return true;
- }
-
t0 = tcg_temp_new_i64();
gen_load_gpr(t0, a->rs);
if (!a->dw) {
diff --git a/tests/tcg/mips/user/isa/octeon/octeon-insns.c b/tests/tcg/mips/user/isa/octeon/octeon-insns.c
index b7610db812e..f406726fc11 100644
--- a/tests/tcg/mips/user/isa/octeon/octeon-insns.c
+++ b/tests/tcg/mips/user/isa/octeon/octeon-insns.c
@@ -39,10 +39,26 @@ static uint64_t octeon_dmul(uint64_t rs, uint64_t rt)
return rd;
}
+static uint64_t octeon_dpop(uint64_t rs)
+{
+ uint64_t rd;
+
+ asm volatile(
+ "move $8, %[rs]\n\t"
+ ".word 0x7100502d\n\t" /* dpop $10, $8 */
+ "move %[rd], $10\n\t"
+ : [rd] "=r" (rd)
+ : [rs] "r" (rs)
+ : "$8", "$10");
+
+ return rd;
+}
+
int main(void)
{
assert(octeon_baddu(0x123, 0x0f0) == 0x13);
assert(octeon_dmul(0x12345678, 0x10) == 0x123456780);
+ assert(octeon_dpop(0xf0f0f0f0f0f0f0f0ULL) == 32);
return 0;
}
--
2.53.0
^ permalink raw reply related [flat|nested] 35+ messages in thread
* [PULL 16/33] target/mips: split Octeon SEQ/SNE decode
2026-05-20 19:23 [PULL 00/33] MIPS patches for 2026-05-20 Philippe Mathieu-Daudé
` (14 preceding siblings ...)
2026-05-20 19:23 ` [PULL 15/33] target/mips: drop Octeon zero-register fast paths Philippe Mathieu-Daudé
@ 2026-05-20 19:23 ` Philippe Mathieu-Daudé
2026-05-20 19:23 ` [PULL 17/33] target/mips: split Octeon SEQI/SNEI decode Philippe Mathieu-Daudé
` (17 subsequent siblings)
33 siblings, 0 replies; 35+ messages in thread
From: Philippe Mathieu-Daudé @ 2026-05-20 19:23 UTC (permalink / raw)
To: qemu-devel
From: James Hilliard <james.hilliard1@gmail.com>
Decode the equality and inequality forms as explicit SEQ/SNE
instructions rather than using shared generated SEQNE entries.
The explicit decoder names match the architectural mnemonics, which
makes the translator entry points and trace/debug output easier to
correlate with the instruction set.
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
Signed-off-by: James Hilliard <james.hilliard1@gmail.com>
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
[PMD: Split SEQNE (this patch) vs SEQNEI]
Signed-off-by: Philippe Mathieu-Daudé <philmd@linaro.org>
Message-Id: <20260520172313.23777-9-philmd@linaro.org>
---
target/mips/tcg/octeon.decode | 3 +-
target/mips/tcg/octeon_translate.c | 25 +++++++------
tests/tcg/mips/user/isa/octeon/octeon-insns.c | 36 +++++++++++++++++++
3 files changed, 52 insertions(+), 12 deletions(-)
diff --git a/target/mips/tcg/octeon.decode b/target/mips/tcg/octeon.decode
index 102a05860df..2c54901f77e 100644
--- a/target/mips/tcg/octeon.decode
+++ b/target/mips/tcg/octeon.decode
@@ -38,7 +38,8 @@ DMUL 011100 ..... ..... ..... 00000 000011 @r3
EXTS 011100 ..... ..... ..... ..... 11101 . @bitfield
CINS 011100 ..... ..... ..... ..... 11001 . @bitfield
POP 011100 rs:5 00000 rd:5 00000 10110 dw:1
-SEQNE 011100 rs:5 rt:5 rd:5 00000 10101 ne:1
+SEQ 011100 ..... ..... ..... 00000 101010 @r3
+SNE 011100 ..... ..... ..... 00000 101011 @r3
SEQNEI 011100 rs:5 rt:5 imm:s10 10111 ne:1
&lx base index rd
diff --git a/target/mips/tcg/octeon_translate.c b/target/mips/tcg/octeon_translate.c
index b7531653e58..dfbb55e3fc3 100644
--- a/target/mips/tcg/octeon_translate.c
+++ b/target/mips/tcg/octeon_translate.c
@@ -106,29 +106,32 @@ static bool trans_POP(DisasContext *ctx, arg_POP *a)
return true;
}
-static bool trans_SEQNE(DisasContext *ctx, arg_SEQNE *a)
+static bool do_seq_sne(DisasContext *ctx, const arg_decode_ext_octeon1 *a,
+ TCGCond cond)
{
TCGv_i64 t0, t1;
- if (a->rd == 0) {
- /* nop */
- return true;
- }
-
t0 = tcg_temp_new_i64();
t1 = tcg_temp_new_i64();
gen_load_gpr(t0, a->rs);
gen_load_gpr(t1, a->rt);
- if (a->ne) {
- tcg_gen_setcond_i64(TCG_COND_NE, cpu_gpr[a->rd], t1, t0);
- } else {
- tcg_gen_setcond_i64(TCG_COND_EQ, cpu_gpr[a->rd], t1, t0);
- }
+ tcg_gen_setcond_i64(cond, t0, t1, t0);
+ gen_store_gpr(t0, a->rd);
return true;
}
+static bool trans_SEQ(DisasContext *ctx, arg_SEQ *a)
+{
+ return do_seq_sne(ctx, a, TCG_COND_EQ);
+}
+
+static bool trans_SNE(DisasContext *ctx, arg_SNE *a)
+{
+ return do_seq_sne(ctx, a, TCG_COND_NE);
+}
+
static bool trans_SEQNEI(DisasContext *ctx, arg_SEQNEI *a)
{
TCGv_i64 t0;
diff --git a/tests/tcg/mips/user/isa/octeon/octeon-insns.c b/tests/tcg/mips/user/isa/octeon/octeon-insns.c
index f406726fc11..3c3802ebfee 100644
--- a/tests/tcg/mips/user/isa/octeon/octeon-insns.c
+++ b/tests/tcg/mips/user/isa/octeon/octeon-insns.c
@@ -54,11 +54,47 @@ static uint64_t octeon_dpop(uint64_t rs)
return rd;
}
+static uint64_t octeon_seq(uint64_t rs, uint64_t rt)
+{
+ uint64_t rd;
+
+ asm volatile(
+ "move $8, %[rs]\n\t"
+ "move $9, %[rt]\n\t"
+ ".word 0x7109502a\n\t" /* seq $10, $8, $9 */
+ "move %[rd], $10\n\t"
+ : [rd] "=r" (rd)
+ : [rs] "r" (rs), [rt] "r" (rt)
+ : "$8", "$9", "$10");
+
+ return rd;
+}
+
+static uint64_t octeon_sne(uint64_t rs, uint64_t rt)
+{
+ uint64_t rd;
+
+ asm volatile(
+ "move $8, %[rs]\n\t"
+ "move $9, %[rt]\n\t"
+ ".word 0x7109502b\n\t" /* sne $10, $8, $9 */
+ "move %[rd], $10\n\t"
+ : [rd] "=r" (rd)
+ : [rs] "r" (rs), [rt] "r" (rt)
+ : "$8", "$9", "$10");
+
+ return rd;
+}
+
int main(void)
{
assert(octeon_baddu(0x123, 0x0f0) == 0x13);
assert(octeon_dmul(0x12345678, 0x10) == 0x123456780);
assert(octeon_dpop(0xf0f0f0f0f0f0f0f0ULL) == 32);
+ assert(octeon_seq(0xabc, 0xabc) == 1);
+ assert(octeon_seq(0xabc, 0xdef) == 0);
+ assert(octeon_sne(0xabc, 0xabc) == 0);
+ assert(octeon_sne(0xabc, 0xdef) == 1);
return 0;
}
--
2.53.0
^ permalink raw reply related [flat|nested] 35+ messages in thread
* [PULL 17/33] target/mips: split Octeon SEQI/SNEI decode
2026-05-20 19:23 [PULL 00/33] MIPS patches for 2026-05-20 Philippe Mathieu-Daudé
` (15 preceding siblings ...)
2026-05-20 19:23 ` [PULL 16/33] target/mips: split Octeon SEQ/SNE decode Philippe Mathieu-Daudé
@ 2026-05-20 19:23 ` Philippe Mathieu-Daudé
2026-05-20 19:23 ` [PULL 18/33] target/mips: add Octeon LBX instruction Philippe Mathieu-Daudé
` (16 subsequent siblings)
33 siblings, 0 replies; 35+ messages in thread
From: Philippe Mathieu-Daudé @ 2026-05-20 19:23 UTC (permalink / raw)
To: qemu-devel
From: James Hilliard <james.hilliard1@gmail.com>
Decode the equality and inequality forms as explicit SEQI/SNEI
instructions rather than using shared generated SEQNEI entries.
The explicit decoder names match the architectural mnemonics, which
makes the translator entry points and trace/debug output easier to
correlate with the instruction set.
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
Signed-off-by: James Hilliard <james.hilliard1@gmail.com>
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
[PMD: Split SEQNE vs SEQNEI (this patch)]
Signed-off-by: Philippe Mathieu-Daudé <philmd@linaro.org>
Message-Id: <20260520172313.23777-10-philmd@linaro.org>
---
target/mips/tcg/octeon.decode | 4 +++-
target/mips/tcg/octeon_translate.c | 27 +++++++++++++--------------
2 files changed, 16 insertions(+), 15 deletions(-)
diff --git a/target/mips/tcg/octeon.decode b/target/mips/tcg/octeon.decode
index 2c54901f77e..a2bfd0751d3 100644
--- a/target/mips/tcg/octeon.decode
+++ b/target/mips/tcg/octeon.decode
@@ -30,6 +30,7 @@ BBIT 11 set:1 . 10 rs:5 ..... offset:s16 p=%bbit_p
# SNEI rt, rs, immediate
@r3 ...... rs:5 rt:5 rd:5 ..... ......
+&cmpi rs rt imm
%bitfield_p 0:1 6:5
@bitfield ...... rs:5 rt:5 lenm1:5 ..... ..... . p=%bitfield_p
@@ -40,7 +41,8 @@ CINS 011100 ..... ..... ..... ..... 11001 . @bitfield
POP 011100 rs:5 00000 rd:5 00000 10110 dw:1
SEQ 011100 ..... ..... ..... 00000 101010 @r3
SNE 011100 ..... ..... ..... 00000 101011 @r3
-SEQNEI 011100 rs:5 rt:5 imm:s10 10111 ne:1
+SEQI 011100 rs:5 rt:5 imm:s10 101110 &cmpi
+SNEI 011100 rs:5 rt:5 imm:s10 101111 &cmpi
&lx base index rd
@lx ...... base:5 index:5 rd:5 ...... ..... &lx
diff --git a/target/mips/tcg/octeon_translate.c b/target/mips/tcg/octeon_translate.c
index dfbb55e3fc3..5497ddfb108 100644
--- a/target/mips/tcg/octeon_translate.c
+++ b/target/mips/tcg/octeon_translate.c
@@ -132,29 +132,28 @@ static bool trans_SNE(DisasContext *ctx, arg_SNE *a)
return do_seq_sne(ctx, a, TCG_COND_NE);
}
-static bool trans_SEQNEI(DisasContext *ctx, arg_SEQNEI *a)
+static bool do_seqi_snei(DisasContext *ctx, const arg_cmpi *a, TCGCond cond)
{
TCGv_i64 t0;
- if (a->rt == 0) {
- /* nop */
- return true;
- }
-
t0 = tcg_temp_new_i64();
-
gen_load_gpr(t0, a->rs);
- /* Sign-extend to 64 bit value */
- target_ulong imm = a->imm;
- if (a->ne) {
- tcg_gen_setcondi_i64(TCG_COND_NE, cpu_gpr[a->rt], t0, imm);
- } else {
- tcg_gen_setcondi_i64(TCG_COND_EQ, cpu_gpr[a->rt], t0, imm);
- }
+ tcg_gen_setcondi_i64(cond, t0, t0, a->imm);
+ gen_store_gpr(t0, a->rt);
return true;
}
+static bool trans_SEQI(DisasContext *ctx, arg_SEQI *a)
+{
+ return do_seqi_snei(ctx, a, TCG_COND_EQ);
+}
+
+static bool trans_SNEI(DisasContext *ctx, arg_SNEI *a)
+{
+ return do_seqi_snei(ctx, a, TCG_COND_NE);
+}
+
static bool trans_lx(DisasContext *ctx, arg_lx *a, MemOp mop)
{
gen_lx(ctx, a->rd, a->base, a->index, mop);
--
2.53.0
^ permalink raw reply related [flat|nested] 35+ messages in thread
* [PULL 18/33] target/mips: add Octeon LBX instruction
2026-05-20 19:23 [PULL 00/33] MIPS patches for 2026-05-20 Philippe Mathieu-Daudé
` (16 preceding siblings ...)
2026-05-20 19:23 ` [PULL 17/33] target/mips: split Octeon SEQI/SNEI decode Philippe Mathieu-Daudé
@ 2026-05-20 19:23 ` Philippe Mathieu-Daudé
2026-05-20 19:23 ` [PULL 19/33] target/mips: add Octeon LHUX instruction Philippe Mathieu-Daudé
` (15 subsequent siblings)
33 siblings, 0 replies; 35+ messages in thread
From: Philippe Mathieu-Daudé @ 2026-05-20 19:23 UTC (permalink / raw)
To: qemu-devel
From: James Hilliard <james.hilliard1@gmail.com>
LBX performs an indexed signed byte load from base + index and writes the
sign-extended result to rd.
Wire the existing indexed-load helper to MO_SB so Octeon user-mode
binaries can use the signed byte variant alongside the existing LBUX
path.
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
Signed-off-by: James Hilliard <james.hilliard1@gmail.com>
Signed-off-by: Philippe Mathieu-Daudé <philmd@linaro.org>
Message-Id: <20260520172313.23777-11-philmd@linaro.org>
---
target/mips/tcg/octeon.decode | 1 +
target/mips/tcg/octeon_translate.c | 1 +
2 files changed, 2 insertions(+)
diff --git a/target/mips/tcg/octeon.decode b/target/mips/tcg/octeon.decode
index a2bfd0751d3..efb1a48b38a 100644
--- a/target/mips/tcg/octeon.decode
+++ b/target/mips/tcg/octeon.decode
@@ -49,4 +49,5 @@ SNEI 011100 rs:5 rt:5 imm:s10 101111 &cmpi
LWX 011111 ..... ..... ..... 00000 001010 @lx
LHX 011111 ..... ..... ..... 00100 001010 @lx
LBUX 011111 ..... ..... ..... 00110 001010 @lx
+LBX 011111 ..... ..... ..... 10110 001010 @lx
LDX 011111 ..... ..... ..... 01000 001010 @lx
diff --git a/target/mips/tcg/octeon_translate.c b/target/mips/tcg/octeon_translate.c
index 5497ddfb108..451737cda1d 100644
--- a/target/mips/tcg/octeon_translate.c
+++ b/target/mips/tcg/octeon_translate.c
@@ -161,6 +161,7 @@ static bool trans_lx(DisasContext *ctx, arg_lx *a, MemOp mop)
return true;
}
+TRANS(LBX, trans_lx, MO_SB);
TRANS(LBUX, trans_lx, MO_UB);
TRANS(LHX, trans_lx, MO_SW);
TRANS(LWX, trans_lx, MO_SL);
--
2.53.0
^ permalink raw reply related [flat|nested] 35+ messages in thread
* [PULL 19/33] target/mips: add Octeon LHUX instruction
2026-05-20 19:23 [PULL 00/33] MIPS patches for 2026-05-20 Philippe Mathieu-Daudé
` (17 preceding siblings ...)
2026-05-20 19:23 ` [PULL 18/33] target/mips: add Octeon LBX instruction Philippe Mathieu-Daudé
@ 2026-05-20 19:23 ` Philippe Mathieu-Daudé
2026-05-20 19:23 ` [PULL 20/33] target/mips: add Octeon LWUX instruction Philippe Mathieu-Daudé
` (14 subsequent siblings)
33 siblings, 0 replies; 35+ messages in thread
From: Philippe Mathieu-Daudé @ 2026-05-20 19:23 UTC (permalink / raw)
To: qemu-devel
From: James Hilliard <james.hilliard1@gmail.com>
LHUX performs an indexed unsigned halfword load from base + index and
zero-extends the result into rd.
Add the decode entry and reuse the common indexed-load translator with
MO_UW.
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
Signed-off-by: James Hilliard <james.hilliard1@gmail.com>
Signed-off-by: Philippe Mathieu-Daudé <philmd@linaro.org>
Message-Id: <20260520172313.23777-12-philmd@linaro.org>
---
target/mips/tcg/octeon.decode | 1 +
target/mips/tcg/octeon_translate.c | 1 +
2 files changed, 2 insertions(+)
diff --git a/target/mips/tcg/octeon.decode b/target/mips/tcg/octeon.decode
index efb1a48b38a..8a755075e8e 100644
--- a/target/mips/tcg/octeon.decode
+++ b/target/mips/tcg/octeon.decode
@@ -48,6 +48,7 @@ SNEI 011100 rs:5 rt:5 imm:s10 101111 &cmpi
@lx ...... base:5 index:5 rd:5 ...... ..... &lx
LWX 011111 ..... ..... ..... 00000 001010 @lx
LHX 011111 ..... ..... ..... 00100 001010 @lx
+LHUX 011111 ..... ..... ..... 10100 001010 @lx
LBUX 011111 ..... ..... ..... 00110 001010 @lx
LBX 011111 ..... ..... ..... 10110 001010 @lx
LDX 011111 ..... ..... ..... 01000 001010 @lx
diff --git a/target/mips/tcg/octeon_translate.c b/target/mips/tcg/octeon_translate.c
index 451737cda1d..f897b42807b 100644
--- a/target/mips/tcg/octeon_translate.c
+++ b/target/mips/tcg/octeon_translate.c
@@ -164,5 +164,6 @@ static bool trans_lx(DisasContext *ctx, arg_lx *a, MemOp mop)
TRANS(LBX, trans_lx, MO_SB);
TRANS(LBUX, trans_lx, MO_UB);
TRANS(LHX, trans_lx, MO_SW);
+TRANS(LHUX, trans_lx, MO_UW);
TRANS(LWX, trans_lx, MO_SL);
TRANS(LDX, trans_lx, MO_UQ);
--
2.53.0
^ permalink raw reply related [flat|nested] 35+ messages in thread
* [PULL 20/33] target/mips: add Octeon LWUX instruction
2026-05-20 19:23 [PULL 00/33] MIPS patches for 2026-05-20 Philippe Mathieu-Daudé
` (18 preceding siblings ...)
2026-05-20 19:23 ` [PULL 19/33] target/mips: add Octeon LHUX instruction Philippe Mathieu-Daudé
@ 2026-05-20 19:23 ` Philippe Mathieu-Daudé
2026-05-20 19:23 ` [PULL 21/33] target/mips: add Octeon SAA instruction Philippe Mathieu-Daudé
` (13 subsequent siblings)
33 siblings, 0 replies; 35+ messages in thread
From: Philippe Mathieu-Daudé @ 2026-05-20 19:23 UTC (permalink / raw)
To: qemu-devel
From: James Hilliard <james.hilliard1@gmail.com>
LWUX performs an indexed unsigned word load from base + index and
zero-extends the result into rd.
Add the decode entry and route it through the common indexed-load
translator with MO_UL.
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
Signed-off-by: James Hilliard <james.hilliard1@gmail.com>
Signed-off-by: Philippe Mathieu-Daudé <philmd@linaro.org>
Message-Id: <20260520172313.23777-13-philmd@linaro.org>
---
target/mips/tcg/octeon.decode | 1 +
target/mips/tcg/octeon_translate.c | 1 +
2 files changed, 2 insertions(+)
diff --git a/target/mips/tcg/octeon.decode b/target/mips/tcg/octeon.decode
index 8a755075e8e..db7d5f55f0a 100644
--- a/target/mips/tcg/octeon.decode
+++ b/target/mips/tcg/octeon.decode
@@ -50,5 +50,6 @@ LWX 011111 ..... ..... ..... 00000 001010 @lx
LHX 011111 ..... ..... ..... 00100 001010 @lx
LHUX 011111 ..... ..... ..... 10100 001010 @lx
LBUX 011111 ..... ..... ..... 00110 001010 @lx
+LWUX 011111 ..... ..... ..... 10000 001010 @lx
LBX 011111 ..... ..... ..... 10110 001010 @lx
LDX 011111 ..... ..... ..... 01000 001010 @lx
diff --git a/target/mips/tcg/octeon_translate.c b/target/mips/tcg/octeon_translate.c
index f897b42807b..401c4bd14bb 100644
--- a/target/mips/tcg/octeon_translate.c
+++ b/target/mips/tcg/octeon_translate.c
@@ -166,4 +166,5 @@ TRANS(LBUX, trans_lx, MO_UB);
TRANS(LHX, trans_lx, MO_SW);
TRANS(LHUX, trans_lx, MO_UW);
TRANS(LWX, trans_lx, MO_SL);
+TRANS(LWUX, trans_lx, MO_UL);
TRANS(LDX, trans_lx, MO_UQ);
--
2.53.0
^ permalink raw reply related [flat|nested] 35+ messages in thread
* [PULL 21/33] target/mips: add Octeon SAA instruction
2026-05-20 19:23 [PULL 00/33] MIPS patches for 2026-05-20 Philippe Mathieu-Daudé
` (19 preceding siblings ...)
2026-05-20 19:23 ` [PULL 20/33] target/mips: add Octeon LWUX instruction Philippe Mathieu-Daudé
@ 2026-05-20 19:23 ` Philippe Mathieu-Daudé
2026-05-20 19:23 ` [PULL 22/33] target/mips: add Octeon SAAD instruction Philippe Mathieu-Daudé
` (12 subsequent siblings)
33 siblings, 0 replies; 35+ messages in thread
From: Philippe Mathieu-Daudé @ 2026-05-20 19:23 UTC (permalink / raw)
To: qemu-devel
From: James Hilliard <james.hilliard1@gmail.com>
SAA atomically adds rt to the naturally aligned 32-bit word at base and
discards the old memory value.
Implement the common SAA/SAAD translator with TCG atomic_fetch_add_i64.
The MemOp selects the word or doubleword transaction size. QEMU only has
one Octeon CPU model today, so keep SAA/SAAD under the existing Octeon
instruction feature bucket instead of adding a finer-grained Octeon+
feature bit.
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
Signed-off-by: James Hilliard <james.hilliard1@gmail.com>
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
Signed-off-by: Philippe Mathieu-Daudé <philmd@linaro.org>
Message-Id: <20260520172313.23777-14-philmd@linaro.org>
---
target/mips/tcg/octeon.decode | 4 ++++
target/mips/tcg/octeon_translate.c | 15 +++++++++++++++
2 files changed, 19 insertions(+)
diff --git a/target/mips/tcg/octeon.decode b/target/mips/tcg/octeon.decode
index db7d5f55f0a..d6b241de421 100644
--- a/target/mips/tcg/octeon.decode
+++ b/target/mips/tcg/octeon.decode
@@ -44,6 +44,10 @@ SNE 011100 ..... ..... ..... 00000 101011 @r3
SEQI 011100 rs:5 rt:5 imm:s10 101110 &cmpi
SNEI 011100 rs:5 rt:5 imm:s10 101111 &cmpi
+&saa base rt
+@saa ...... base:5 rt:5 ................ &saa
+SAA 011100 ..... ..... 00000 00000 011000 @saa
+
&lx base index rd
@lx ...... base:5 index:5 rd:5 ...... ..... &lx
LWX 011111 ..... ..... ..... 00000 001010 @lx
diff --git a/target/mips/tcg/octeon_translate.c b/target/mips/tcg/octeon_translate.c
index 401c4bd14bb..33b45611f20 100644
--- a/target/mips/tcg/octeon_translate.c
+++ b/target/mips/tcg/octeon_translate.c
@@ -168,3 +168,18 @@ TRANS(LHUX, trans_lx, MO_UW);
TRANS(LWX, trans_lx, MO_SL);
TRANS(LWUX, trans_lx, MO_UL);
TRANS(LDX, trans_lx, MO_UQ);
+
+static bool trans_saa(DisasContext *ctx, arg_saa *a, MemOp mop)
+{
+ TCGv_i64 addr = tcg_temp_new_i64();
+ TCGv_i64 value = tcg_temp_new_i64();
+ TCGv_i64 old = tcg_temp_new_i64();
+ MemOp amo = mo_endian(ctx) | mop | MO_ALIGN;
+
+ gen_base_offset_addr(ctx, addr, a->base, 0);
+ gen_load_gpr(value, a->rt);
+ tcg_gen_atomic_fetch_add_i64(old, addr, value, ctx->mem_idx, amo);
+ return true;
+}
+
+TRANS(SAA, trans_saa, MO_32);
--
2.53.0
^ permalink raw reply related [flat|nested] 35+ messages in thread
* [PULL 22/33] target/mips: add Octeon SAAD instruction
2026-05-20 19:23 [PULL 00/33] MIPS patches for 2026-05-20 Philippe Mathieu-Daudé
` (20 preceding siblings ...)
2026-05-20 19:23 ` [PULL 21/33] target/mips: add Octeon SAA instruction Philippe Mathieu-Daudé
@ 2026-05-20 19:23 ` Philippe Mathieu-Daudé
2026-05-20 19:23 ` [PULL 23/33] tcg: Introduce tcg_zero_i128() Philippe Mathieu-Daudé
` (11 subsequent siblings)
33 siblings, 0 replies; 35+ messages in thread
From: Philippe Mathieu-Daudé @ 2026-05-20 19:23 UTC (permalink / raw)
To: qemu-devel
From: James Hilliard <james.hilliard1@gmail.com>
SAAD is the doubleword form of SAA: it atomically adds rt to the
naturally aligned 64-bit doubleword at base and discards the old memory
value.
Route it through the common SAA/SAAD translator so the MemOp selects the
aligned doubleword transaction size.
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
Signed-off-by: James Hilliard <james.hilliard1@gmail.com>
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
Signed-off-by: Philippe Mathieu-Daudé <philmd@linaro.org>
Message-Id: <20260520172313.23777-15-philmd@linaro.org>
---
target/mips/tcg/octeon.decode | 1 +
target/mips/tcg/octeon_translate.c | 1 +
2 files changed, 2 insertions(+)
diff --git a/target/mips/tcg/octeon.decode b/target/mips/tcg/octeon.decode
index d6b241de421..d77717cd507 100644
--- a/target/mips/tcg/octeon.decode
+++ b/target/mips/tcg/octeon.decode
@@ -47,6 +47,7 @@ SNEI 011100 rs:5 rt:5 imm:s10 101111 &cmpi
&saa base rt
@saa ...... base:5 rt:5 ................ &saa
SAA 011100 ..... ..... 00000 00000 011000 @saa
+SAAD 011100 ..... ..... 00000 00000 011001 @saa
&lx base index rd
@lx ...... base:5 index:5 rd:5 ...... ..... &lx
diff --git a/target/mips/tcg/octeon_translate.c b/target/mips/tcg/octeon_translate.c
index 33b45611f20..23748695a14 100644
--- a/target/mips/tcg/octeon_translate.c
+++ b/target/mips/tcg/octeon_translate.c
@@ -183,3 +183,4 @@ static bool trans_saa(DisasContext *ctx, arg_saa *a, MemOp mop)
}
TRANS(SAA, trans_saa, MO_32);
+TRANS(SAAD, trans_saa, MO_64);
--
2.53.0
^ permalink raw reply related [flat|nested] 35+ messages in thread
* [PULL 23/33] tcg: Introduce tcg_zero_i128()
2026-05-20 19:23 [PULL 00/33] MIPS patches for 2026-05-20 Philippe Mathieu-Daudé
` (21 preceding siblings ...)
2026-05-20 19:23 ` [PULL 22/33] target/mips: add Octeon SAAD instruction Philippe Mathieu-Daudé
@ 2026-05-20 19:23 ` Philippe Mathieu-Daudé
2026-05-20 19:23 ` [PULL 24/33] target/mips: add Octeon ZCB and ZCBT instructions Philippe Mathieu-Daudé
` (10 subsequent siblings)
33 siblings, 0 replies; 35+ messages in thread
From: Philippe Mathieu-Daudé @ 2026-05-20 19:23 UTC (permalink / raw)
To: qemu-devel
Extract tcg_zero_i128() helper for re-use.
Signed-off-by: Philippe Mathieu-Daudé <philmd@linaro.org>
Message-ID: <20260520121644.10835-1-philmd@linaro.org>
[rth: Move the function to tcg-op.c]
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
include/tcg/tcg-op-common.h | 2 ++
target/arm/tcg/translate-a64.c | 5 +----
tcg/tcg-op.c | 10 ++++++++++
3 files changed, 13 insertions(+), 4 deletions(-)
diff --git a/include/tcg/tcg-op-common.h b/include/tcg/tcg-op-common.h
index e02f209c093..aff99754160 100644
--- a/include/tcg/tcg-op-common.h
+++ b/include/tcg/tcg-op-common.h
@@ -18,6 +18,8 @@ TCGv_vaddr tcg_constant_vaddr(uintptr_t val);
TCGv_vec tcg_constant_vec(TCGType type, unsigned vece, int64_t val);
TCGv_vec tcg_constant_vec_matching(TCGv_vec match, unsigned vece, int64_t val);
+TCGv_i128 tcg_zero_i128(void);
+
TCGv_i32 tcg_temp_new_i32(void);
TCGv_i64 tcg_temp_new_i64(void);
TCGv_ptr tcg_temp_new_ptr(void);
diff --git a/target/arm/tcg/translate-a64.c b/target/arm/tcg/translate-a64.c
index 9a27c4c6ec7..3e3971db3fb 100644
--- a/target/arm/tcg/translate-a64.c
+++ b/target/arm/tcg/translate-a64.c
@@ -4804,13 +4804,10 @@ static bool do_STG(DisasContext *s, arg_ldst_tag *a, bool is_zero, bool is_pair)
if (is_zero) {
TCGv_i64 clean_addr = clean_data_tbi(s, addr);
- TCGv_i64 zero64 = tcg_constant_i64(0);
- TCGv_i128 zero128 = tcg_temp_new_i128();
+ TCGv_i128 zero128 = tcg_zero_i128();
int mem_index = get_mem_index(s);
MemOp mop = finalize_memop(s, MO_128 | MO_ALIGN);
- tcg_gen_concat_i64_i128(zero128, zero64, zero64);
-
/* This is 1 or 2 atomic 16-byte operations. */
tcg_gen_qemu_st_i128(zero128, clean_addr, mem_index, mop);
if (is_pair) {
diff --git a/tcg/tcg-op.c b/tcg/tcg-op.c
index d8ae57d6047..971ac2fb359 100644
--- a/tcg/tcg-op.c
+++ b/tcg/tcg-op.c
@@ -2475,6 +2475,16 @@ void tcg_gen_concat_i64_i128(TCGv_i128 ret, TCGv_i64 lo, TCGv_i64 hi)
tcg_gen_mov_i64(TCGV128_HIGH(ret), hi);
}
+TCGv_i128 tcg_zero_i128(void)
+{
+ TCGv_i64 zero64 = tcg_constant_i64(0);
+ TCGv_i128 zero128 = tcg_temp_new_i128();
+
+ tcg_gen_concat_i64_i128(zero128, zero64, zero64);
+
+ return zero128;
+}
+
void tcg_gen_mov_i128(TCGv_i128 dst, TCGv_i128 src)
{
if (dst != src) {
--
2.53.0
^ permalink raw reply related [flat|nested] 35+ messages in thread
* [PULL 24/33] target/mips: add Octeon ZCB and ZCBT instructions
2026-05-20 19:23 [PULL 00/33] MIPS patches for 2026-05-20 Philippe Mathieu-Daudé
` (22 preceding siblings ...)
2026-05-20 19:23 ` [PULL 23/33] tcg: Introduce tcg_zero_i128() Philippe Mathieu-Daudé
@ 2026-05-20 19:23 ` Philippe Mathieu-Daudé
2026-05-20 19:23 ` [PULL 25/33] tcg: Introduce tcg_gen_addN_i64 Philippe Mathieu-Daudé
` (9 subsequent siblings)
33 siblings, 0 replies; 35+ messages in thread
From: Philippe Mathieu-Daudé @ 2026-05-20 19:23 UTC (permalink / raw)
To: qemu-devel
From: James Hilliard <james.hilliard1@gmail.com>
ZCB zeros the 128-byte cache block containing the base address. ZCBT has
the same user-mode-visible memory effect for QEMU purposes.
Model both forms with a single decodetree wildcard entry, align the
address down to a 128-byte line, and store eight zero 128-bit chunks to
guest memory.
Acked-by: Richard Henderson <richard.henderson@linaro.org>
Signed-off-by: James Hilliard <james.hilliard1@gmail.com>
Signed-off-by: Philippe Mathieu-Daudé <philmd@linaro.org>
Message-Id: <20260520172313.23777-16-philmd@linaro.org>
---
target/mips/tcg/octeon.decode | 3 +++
target/mips/tcg/octeon_translate.c | 25 +++++++++++++++++++++++++
2 files changed, 28 insertions(+)
diff --git a/target/mips/tcg/octeon.decode b/target/mips/tcg/octeon.decode
index d77717cd507..01ed3b50beb 100644
--- a/target/mips/tcg/octeon.decode
+++ b/target/mips/tcg/octeon.decode
@@ -49,6 +49,9 @@ SNEI 011100 rs:5 rt:5 imm:s10 101111 &cmpi
SAA 011100 ..... ..... 00000 00000 011000 @saa
SAAD 011100 ..... ..... 00000 00000 011001 @saa
+&zcb base
+ZCB 011100 base:5 00000 00000 1110- 011111 &zcb
+
&lx base index rd
@lx ...... base:5 index:5 rd:5 ...... ..... &lx
LWX 011111 ..... ..... ..... 00000 001010 @lx
diff --git a/target/mips/tcg/octeon_translate.c b/target/mips/tcg/octeon_translate.c
index 23748695a14..5392fed08a8 100644
--- a/target/mips/tcg/octeon_translate.c
+++ b/target/mips/tcg/octeon_translate.c
@@ -184,3 +184,28 @@ static bool trans_saa(DisasContext *ctx, arg_saa *a, MemOp mop)
TRANS(SAA, trans_saa, MO_32);
TRANS(SAAD, trans_saa, MO_64);
+
+static bool trans_ZCB(DisasContext *ctx, arg_ZCB *a)
+{
+ TCGv_i64 addr = tcg_temp_new_i64();
+ TCGv_i64 line = tcg_temp_new_i64();
+ TCGv_i128 zero128 = tcg_zero_i128();
+ const MemOp mop = mo_endian(ctx) | MO_128 | MO_ATOM_NONE;
+
+ gen_base_offset_addr(ctx, addr, a->base, 0);
+
+ /*
+ * QEMU models ZCB/ZCBT as zeroing the containing 128-byte cache line
+ * in guest memory.
+ */
+ tcg_gen_andi_i64(line, addr, ~0x7fULL);
+
+ for (int i = 0; i < 8; i++) {
+ TCGv_i64 slot = tcg_temp_new_i64();
+
+ tcg_gen_addi_i64(slot, line, i * 16);
+ tcg_gen_qemu_st_i128(zero128, slot, ctx->mem_idx, mop);
+ }
+
+ return true;
+}
--
2.53.0
^ permalink raw reply related [flat|nested] 35+ messages in thread
* [PULL 25/33] tcg: Introduce tcg_gen_addN_i64
2026-05-20 19:23 [PULL 00/33] MIPS patches for 2026-05-20 Philippe Mathieu-Daudé
` (23 preceding siblings ...)
2026-05-20 19:23 ` [PULL 24/33] target/mips: add Octeon ZCB and ZCBT instructions Philippe Mathieu-Daudé
@ 2026-05-20 19:23 ` Philippe Mathieu-Daudé
2026-05-20 19:23 ` [PULL 26/33] target/mips: add Octeon multiplier state Philippe Mathieu-Daudé
` (8 subsequent siblings)
33 siblings, 0 replies; 35+ messages in thread
From: Philippe Mathieu-Daudé @ 2026-05-20 19:23 UTC (permalink / raw)
To: qemu-devel
From: Richard Henderson <richard.henderson@linaro.org>
Add a helper for multi-limb 64-bit addition. The helper emits native
carry-chain TCG ops when they are available and falls back to explicit
carry propagation otherwise.
This lets target translators build wider integer accumulators inline
without open-coding the same add-with-carry sequence at each use site.
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
Signed-off-by: James Hilliard <james.hilliard1@gmail.com>
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
Signed-off-by: Philippe Mathieu-Daudé <philmd@linaro.org>
Message-Id: <20260520172313.23777-17-philmd@linaro.org>
---
include/tcg/tcg-op-common.h | 1 +
tcg/tcg-op.c | 42 +++++++++++++++++++++++++++++++++++++
2 files changed, 43 insertions(+)
diff --git a/include/tcg/tcg-op-common.h b/include/tcg/tcg-op-common.h
index aff99754160..1fe342db0d4 100644
--- a/include/tcg/tcg-op-common.h
+++ b/include/tcg/tcg-op-common.h
@@ -253,6 +253,7 @@ void tcg_gen_sub2_i64(TCGv_i64 rl, TCGv_i64 rh, TCGv_i64 al,
TCGv_i64 ah, TCGv_i64 bl, TCGv_i64 bh);
void tcg_gen_addcio_i64(TCGv_i64 r, TCGv_i64 co,
TCGv_i64 a, TCGv_i64 b, TCGv_i64 ci);
+void tcg_gen_addN_i64(int n, TCGv_i64 *r, TCGv_i64 *a, TCGv_i64 *b);
void tcg_gen_mulu2_i64(TCGv_i64 rl, TCGv_i64 rh, TCGv_i64 arg1, TCGv_i64 arg2);
void tcg_gen_muls2_i64(TCGv_i64 rl, TCGv_i64 rh, TCGv_i64 arg1, TCGv_i64 arg2);
void tcg_gen_mulsu2_i64(TCGv_i64 rl, TCGv_i64 rh, TCGv_i64 arg1, TCGv_i64 arg2);
diff --git a/tcg/tcg-op.c b/tcg/tcg-op.c
index 971ac2fb359..bbcb510c764 100644
--- a/tcg/tcg-op.c
+++ b/tcg/tcg-op.c
@@ -2275,6 +2275,48 @@ void tcg_gen_addcio_i64(TCGv_i64 r, TCGv_i64 co,
}
}
+void tcg_gen_addN_i64(int n, TCGv_i64 *r, TCGv_i64 *a, TCGv_i64 *b)
+{
+ tcg_debug_assert(n > 2);
+
+ /* ??? Don't allow overlap for now. */
+ for (int i = 0; i < n - 1; ++i) {
+ for (int j = i + 1; j < n; ++j) {
+ tcg_debug_assert(r[i] != a[j]);
+ tcg_debug_assert(r[i] != b[j]);
+ }
+ }
+
+ if (tcg_op_supported(INDEX_op_addci, TCG_TYPE_I64, 0)) {
+ tcg_gen_op3_i64(INDEX_op_addco, r[0], a[0], b[0]);
+ for (int i = 1; i < n - 1; ++i) {
+ tcg_gen_op3_i64(INDEX_op_addcio, r[i], a[i], b[i]);
+ }
+ tcg_gen_op3_i64(INDEX_op_addci, r[n - 1], a[n - 1], b[n - 1]);
+ } else {
+ TCGv_i64 t = tcg_temp_ebb_new_i64();
+ TCGv_i64 c = tcg_temp_ebb_new_i64();
+
+ tcg_gen_add_i64(t, a[0], b[0]);
+ tcg_gen_setcond_i64(TCG_COND_LTU, c, t, a[0]);
+ tcg_gen_mov_i64(r[0], t);
+
+ for (int i = 1; i < n - 1; ++i) {
+ tcg_gen_add_i64(t, a[i], c);
+ tcg_gen_setcond_i64(TCG_COND_LTU, c, t, c);
+ tcg_gen_add_i64(r[i], b[i], t);
+ tcg_gen_setcond_i64(TCG_COND_LTU, t, r[i], t);
+ tcg_gen_or_i64(c, c, t);
+ }
+
+ tcg_gen_add_i64(r[n - 1], a[n - 1], b[n - 1]);
+ tcg_gen_add_i64(r[n - 1], r[n - 1], c);
+
+ tcg_temp_free_i64(t);
+ tcg_temp_free_i64(c);
+ }
+}
+
void tcg_gen_sub2_i64(TCGv_i64 rl, TCGv_i64 rh, TCGv_i64 al,
TCGv_i64 ah, TCGv_i64 bl, TCGv_i64 bh)
{
--
2.53.0
^ permalink raw reply related [flat|nested] 35+ messages in thread
* [PULL 26/33] target/mips: add Octeon multiplier state
2026-05-20 19:23 [PULL 00/33] MIPS patches for 2026-05-20 Philippe Mathieu-Daudé
` (24 preceding siblings ...)
2026-05-20 19:23 ` [PULL 25/33] tcg: Introduce tcg_gen_addN_i64 Philippe Mathieu-Daudé
@ 2026-05-20 19:23 ` Philippe Mathieu-Daudé
2026-05-20 19:23 ` [PULL 27/33] target/mips: add Octeon MTM instructions Philippe Mathieu-Daudé
` (7 subsequent siblings)
33 siblings, 0 replies; 35+ messages in thread
From: Philippe Mathieu-Daudé @ 2026-05-20 19:23 UTC (permalink / raw)
To: qemu-devel
From: James Hilliard <james.hilliard1@gmail.com>
Add per-thread Octeon multiplier state for the MPL and P limb banks used
by the VMULU/VMM0/V3MULU instruction family.
Octeon3 extends the older MPL0-MPL2/P0-P2 state with high lanes
MPL3-MPL5/P3-P5, programmed by the two-source MTM/MTP forms. Represent
both banks as uint64_t arrays so the TC state matches the architected
64-bit limb layout used by Octeon68XX user-mode code.
Expose MPL/P as global TCG variables so the multiplier translators can
expand inline without helper calls.
Migrate the multiplier registers in an Octeon-only subsection so
non-Octeon CPU models do not grow migration state.
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
Signed-off-by: James Hilliard <james.hilliard1@gmail.com>
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
Signed-off-by: Philippe Mathieu-Daudé <philmd@linaro.org>
Message-Id: <20260520172313.23777-18-philmd@linaro.org>
---
target/mips/cpu.h | 12 ++++++++++++
target/mips/tcg/translate.h | 2 ++
target/mips/system/machine.c | 33 +++++++++++++++++++++++++++++++++
target/mips/tcg/translate.c | 18 ++++++++++++++++++
4 files changed, 65 insertions(+)
diff --git a/target/mips/cpu.h b/target/mips/cpu.h
index b478f834c13..346713705a7 100644
--- a/target/mips/cpu.h
+++ b/target/mips/cpu.h
@@ -459,6 +459,14 @@ typedef struct mips_def_t mips_def_t;
typedef struct TCState TCState;
+
+/*
+ * Octeon3 adds a second bank of multiplier/product limbs used by the
+ * two-source MTM/MTP forms: MPL0..2/P0..2 from rs and MPL3..5/P3..5 from rt.
+ */
+#define OCTEON_MULTIPLIER_LANES 3
+#define OCTEON_MULTIPLIER_REGS (2 * OCTEON_MULTIPLIER_LANES)
+
struct TCState {
target_ulong gpr[32];
#if defined(TARGET_MIPS64)
@@ -497,6 +505,10 @@ struct TCState {
target_ulong CP0_TCScheFBack;
int32_t CP0_Debug_tcstatus;
target_ulong CP0_UserLocal;
+ struct {
+ uint64_t MPL[OCTEON_MULTIPLIER_REGS];
+ uint64_t P[OCTEON_MULTIPLIER_REGS];
+ } octeon;
int32_t msacsr;
diff --git a/target/mips/tcg/translate.h b/target/mips/tcg/translate.h
index 89dde1e7124..ab2e2173674 100644
--- a/target/mips/tcg/translate.h
+++ b/target/mips/tcg/translate.h
@@ -189,6 +189,8 @@ void gen_crc32(DisasContext *ctx, int rd, int rs, int rt, int sz, int crc32c);
extern TCGv cpu_gpr[32], cpu_PC;
#if defined(TARGET_MIPS64)
extern TCGv_i64 cpu_gpr_hi[32];
+extern TCGv_i64 oct_mpl[OCTEON_MULTIPLIER_REGS];
+extern TCGv_i64 oct_p[OCTEON_MULTIPLIER_REGS];
#endif
extern TCGv cpu_HI[MIPS_DSP_ACC], cpu_LO[MIPS_DSP_ACC];
extern TCGv_i32 fpu_fcr0, fpu_fcr31;
diff --git a/target/mips/system/machine.c b/target/mips/system/machine.c
index 5880b401b07..f988b3695bc 100644
--- a/target/mips/system/machine.c
+++ b/target/mips/system/machine.c
@@ -120,6 +120,17 @@ static const VMStateDescription vmstate_inactive_tc = {
.fields = vmstate_tc_fields
};
+static const VMStateDescription vmstate_octeon_multiplier_tc = {
+ .name = "cpu/tc/octeon_multiplier",
+ .version_id = 1,
+ .minimum_version_id = 1,
+ .fields = (const VMStateField[]) {
+ VMSTATE_UINT64_ARRAY(octeon.MPL, TCState, OCTEON_MULTIPLIER_REGS),
+ VMSTATE_UINT64_ARRAY(octeon.P, TCState, OCTEON_MULTIPLIER_REGS),
+ VMSTATE_END_OF_LIST()
+ }
+};
+
/* MVP state */
static const VMStateDescription vmstate_mvp = {
@@ -247,6 +258,27 @@ static const VMStateDescription mips_vmstate_timer = {
}
};
+static bool mips_octeon_needed(void *opaque)
+{
+ MIPSCPU *cpu = opaque;
+
+ return cpu->env.insn_flags & INSN_OCTEON;
+}
+
+static const VMStateDescription mips_vmstate_octeon_multiplier = {
+ .name = "cpu/octeon_multiplier",
+ .version_id = 1,
+ .minimum_version_id = 1,
+ .needed = mips_octeon_needed,
+ .fields = (const VMStateField[]) {
+ VMSTATE_STRUCT(env.active_tc, MIPSCPU, 1,
+ vmstate_octeon_multiplier_tc, TCState),
+ VMSTATE_STRUCT_ARRAY(env.tcs, MIPSCPU, MIPS_SHADOW_SET_MAX, 1,
+ vmstate_octeon_multiplier_tc, TCState),
+ VMSTATE_END_OF_LIST()
+ }
+};
+
const VMStateDescription vmstate_mips_cpu = {
.name = "cpu",
.version_id = 21,
@@ -363,6 +395,7 @@ const VMStateDescription vmstate_mips_cpu = {
},
.subsections = (const VMStateDescription * const []) {
&mips_vmstate_timer,
+ &mips_vmstate_octeon_multiplier,
NULL
}
};
diff --git a/target/mips/tcg/translate.c b/target/mips/tcg/translate.c
index dac30aff8d3..123d2c89c3d 100644
--- a/target/mips/tcg/translate.c
+++ b/target/mips/tcg/translate.c
@@ -1179,6 +1179,8 @@ static TCGv cpu_lladdr, cpu_llval;
static TCGv_i32 hflags;
TCGv_i32 fpu_fcr0, fpu_fcr31;
TCGv_i64 fpu_f64[32];
+TCGv_i64 oct_mpl[OCTEON_MULTIPLIER_REGS];
+TCGv_i64 oct_p[OCTEON_MULTIPLIER_REGS];
static const char regnames_HI[][4] = {
"HI0", "HI1", "HI2", "HI3",
@@ -15276,6 +15278,22 @@ void mips_tcg_init(void)
active_tc.gpr_hi[i]),
rname);
}
+
+ for (unsigned i = 0; i < OCTEON_MULTIPLIER_REGS; ++i) {
+ static const char mpl_names[OCTEON_MULTIPLIER_REGS][5] = {
+ "MPL0", "MPL1", "MPL2", "MPL3", "MPL4", "MPL5",
+ };
+ static const char p_names[OCTEON_MULTIPLIER_REGS][3] = {
+ "P0", "P1", "P2", "P3", "P4", "P5",
+ };
+
+ oct_mpl[i] = tcg_global_mem_new_i64(
+ tcg_env, offsetof(CPUMIPSState, active_tc.octeon.MPL[i]),
+ mpl_names[i]);
+ oct_p[i] = tcg_global_mem_new_i64(
+ tcg_env, offsetof(CPUMIPSState, active_tc.octeon.P[i]),
+ p_names[i]);
+ }
#endif /* !TARGET_MIPS64 */
for (unsigned i = 0; i < 32; i++) {
int off = offsetof(CPUMIPSState, active_fpu.fpr[i].wr.d[0]);
--
2.53.0
^ permalink raw reply related [flat|nested] 35+ messages in thread
* [PULL 27/33] target/mips: add Octeon MTM instructions
2026-05-20 19:23 [PULL 00/33] MIPS patches for 2026-05-20 Philippe Mathieu-Daudé
` (25 preceding siblings ...)
2026-05-20 19:23 ` [PULL 26/33] target/mips: add Octeon multiplier state Philippe Mathieu-Daudé
@ 2026-05-20 19:23 ` Philippe Mathieu-Daudé
2026-05-20 19:23 ` [PULL 28/33] target/mips: add Octeon MTP instructions Philippe Mathieu-Daudé
` (6 subsequent siblings)
33 siblings, 0 replies; 35+ messages in thread
From: Philippe Mathieu-Daudé @ 2026-05-20 19:23 UTC (permalink / raw)
To: qemu-devel
From: James Hilliard <james.hilliard1@gmail.com>
Add the MTM0, MTM1, and MTM2 forms that load the Octeon3 multiplier
operand pair from rs/rt into MPL[x] and MPL[x+3], then clear the partial
products. For MPL0, also set MPL[1] to zero for backward compatibility
with Octeon2 VMULU.
Legacy single-source encodings have rt encoded as $zero, so the same
translator path also preserves the older Octeon behavior.
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
Signed-off-by: James Hilliard <james.hilliard1@gmail.com>
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
Signed-off-by: Philippe Mathieu-Daudé <philmd@linaro.org>
Message-Id: <20260520172313.23777-19-philmd@linaro.org>
---
target/mips/tcg/octeon.decode | 7 +++++++
target/mips/tcg/octeon_translate.c | 32 ++++++++++++++++++++++++++++++
2 files changed, 39 insertions(+)
diff --git a/target/mips/tcg/octeon.decode b/target/mips/tcg/octeon.decode
index 01ed3b50beb..5139543b153 100644
--- a/target/mips/tcg/octeon.decode
+++ b/target/mips/tcg/octeon.decode
@@ -44,6 +44,13 @@ SNE 011100 ..... ..... ..... 00000 101011 @r3
SEQI 011100 rs:5 rt:5 imm:s10 101110 &cmpi
SNEI 011100 rs:5 rt:5 imm:s10 101111 &cmpi
+&r2 rs rt
+@r2 ...... rs:5 rt:5 ..... ..... ...... &r2
+
+MTM0 011100 ..... ..... 00000 00000 001000 @r2
+MTM1 011100 ..... ..... 00000 00000 001100 @r2
+MTM2 011100 ..... ..... 00000 00000 001101 @r2
+
&saa base rt
@saa ...... base:5 rt:5 ................ &saa
SAA 011100 ..... ..... 00000 00000 011000 @saa
diff --git a/target/mips/tcg/octeon_translate.c b/target/mips/tcg/octeon_translate.c
index 5392fed08a8..26b918d649a 100644
--- a/target/mips/tcg/octeon_translate.c
+++ b/target/mips/tcg/octeon_translate.c
@@ -209,3 +209,35 @@ static bool trans_ZCB(DisasContext *ctx, arg_ZCB *a)
return true;
}
+
+static void octeon_zero_partial_product_state(void)
+{
+ for (int i = 0; i < OCTEON_MULTIPLIER_REGS; i++) {
+ tcg_gen_movi_i64(oct_p[i], 0);
+ }
+}
+
+static bool trans_mtm(DisasContext *ctx, arg_r2 *a, unsigned int index)
+{
+ /*
+ * Octeon3 two-source MTM forms load lane index from rs and lane index + 3
+ * from rt. Legacy one-source forms encode rt as $zero.
+ */
+ gen_load_gpr(oct_mpl[index], a->rs);
+ gen_load_gpr(oct_mpl[index + 3], a->rt);
+
+ /*
+ * Octeon3 clears MPL1 with a write to MPL0 so that VMULU sequences remain
+ * backward compatible with Octeon2.
+ */
+ if (index == 0) {
+ tcg_gen_movi_i64(oct_mpl[1], 0);
+ }
+
+ octeon_zero_partial_product_state();
+ return true;
+}
+
+TRANS(MTM0, trans_mtm, 0);
+TRANS(MTM1, trans_mtm, 1);
+TRANS(MTM2, trans_mtm, 2);
--
2.53.0
^ permalink raw reply related [flat|nested] 35+ messages in thread
* [PULL 28/33] target/mips: add Octeon MTP instructions
2026-05-20 19:23 [PULL 00/33] MIPS patches for 2026-05-20 Philippe Mathieu-Daudé
` (26 preceding siblings ...)
2026-05-20 19:23 ` [PULL 27/33] target/mips: add Octeon MTM instructions Philippe Mathieu-Daudé
@ 2026-05-20 19:23 ` Philippe Mathieu-Daudé
2026-05-20 19:23 ` [PULL 29/33] target/mips: add Octeon VMULU instruction Philippe Mathieu-Daudé
` (5 subsequent siblings)
33 siblings, 0 replies; 35+ messages in thread
From: Philippe Mathieu-Daudé @ 2026-05-20 19:23 UTC (permalink / raw)
To: qemu-devel
From: James Hilliard <james.hilliard1@gmail.com>
Add the MTP0, MTP1, and MTP2 forms. MTP0 loads the low Octeon3
partial-product pair from rs/rt into P[0]/P[3], MTP1 loads the middle
pair into P[1]/P[4], and MTP2 loads the high pair into P[2]/P[5].
For MTP0, also set P[1] to zero for backward compatibility with
Octeon2 VMULU.
Legacy single-source encodings have rt encoded as $zero, so the same
translator path also preserves the older Octeon behavior.
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
Signed-off-by: James Hilliard <james.hilliard1@gmail.com>
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
Signed-off-by: Philippe Mathieu-Daudé <philmd@linaro.org>
Message-Id: <20260520172313.23777-20-philmd@linaro.org>
---
target/mips/tcg/octeon.decode | 4 ++++
target/mips/tcg/octeon_translate.c | 23 +++++++++++++++++++++++
2 files changed, 27 insertions(+)
diff --git a/target/mips/tcg/octeon.decode b/target/mips/tcg/octeon.decode
index 5139543b153..bb0a9f1d99a 100644
--- a/target/mips/tcg/octeon.decode
+++ b/target/mips/tcg/octeon.decode
@@ -51,6 +51,10 @@ MTM0 011100 ..... ..... 00000 00000 001000 @r2
MTM1 011100 ..... ..... 00000 00000 001100 @r2
MTM2 011100 ..... ..... 00000 00000 001101 @r2
+MTP0 011100 ..... ..... 00000 00000 001001 @r2
+MTP1 011100 ..... ..... 00000 00000 001010 @r2
+MTP2 011100 ..... ..... 00000 00000 001011 @r2
+
&saa base rt
@saa ...... base:5 rt:5 ................ &saa
SAA 011100 ..... ..... 00000 00000 011000 @saa
diff --git a/target/mips/tcg/octeon_translate.c b/target/mips/tcg/octeon_translate.c
index 26b918d649a..10c7d18ad4f 100644
--- a/target/mips/tcg/octeon_translate.c
+++ b/target/mips/tcg/octeon_translate.c
@@ -241,3 +241,26 @@ static bool trans_mtm(DisasContext *ctx, arg_r2 *a, unsigned int index)
TRANS(MTM0, trans_mtm, 0);
TRANS(MTM1, trans_mtm, 1);
TRANS(MTM2, trans_mtm, 2);
+
+static bool trans_mtp(DisasContext *ctx, arg_r2 *a, unsigned int index)
+{
+ /*
+ * Octeon3 two-source MTP forms load lane index from rs and lane index + 3
+ * from rt. Legacy one-source forms encode rt as $zero.
+ */
+ gen_load_gpr(oct_p[index], a->rs);
+ gen_load_gpr(oct_p[index + 3], a->rt);
+
+ /*
+ * Octeon3 clears P1 with a write to P0 so that VMULU sequences remain
+ * backward compatible with Octeon2.
+ */
+ if (index == 0) {
+ tcg_gen_movi_i64(oct_p[1], 0);
+ }
+ return true;
+}
+
+TRANS(MTP0, trans_mtp, 0);
+TRANS(MTP1, trans_mtp, 1);
+TRANS(MTP2, trans_mtp, 2);
--
2.53.0
^ permalink raw reply related [flat|nested] 35+ messages in thread
* [PULL 29/33] target/mips: add Octeon VMULU instruction
2026-05-20 19:23 [PULL 00/33] MIPS patches for 2026-05-20 Philippe Mathieu-Daudé
` (27 preceding siblings ...)
2026-05-20 19:23 ` [PULL 28/33] target/mips: add Octeon MTP instructions Philippe Mathieu-Daudé
@ 2026-05-20 19:23 ` Philippe Mathieu-Daudé
2026-05-20 19:23 ` [PULL 30/33] target/mips: add Octeon VMM0 instruction Philippe Mathieu-Daudé
` (4 subsequent siblings)
33 siblings, 0 replies; 35+ messages in thread
From: Philippe Mathieu-Daudé @ 2026-05-20 19:23 UTC (permalink / raw)
To: qemu-devel
From: James Hilliard <james.hilliard1@gmail.com>
VMULU multiplies the active Octeon multiplier state by rs, adds rt and
queued partial products, returns the low result, and advances P[0]/P[1]
with carry limbs.
Expand the two-limb accumulator operation inline with TCG so the result
and partial-product state stay visible to the optimizer.
Add a mips64/mips64el linux-user TCG smoke test for representative
Octeon multiplier instruction paths.
Include hardware-backed regression coverage for MTP0 P1 zeroing.
Signed-off-by: James Hilliard <james.hilliard1@gmail.com>
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
Tested-by: Philippe Mathieu-Daudé <philmd@linaro.org>
Signed-off-by: Philippe Mathieu-Daudé <philmd@linaro.org>
Message-Id: <20260520172313.23777-21-philmd@linaro.org>
---
target/mips/tcg/octeon.decode | 2 +
target/mips/tcg/octeon_translate.c | 35 +++++++++++++
tests/tcg/mips/user/isa/octeon/octeon-insns.c | 49 +++++++++++++++++++
3 files changed, 86 insertions(+)
diff --git a/target/mips/tcg/octeon.decode b/target/mips/tcg/octeon.decode
index bb0a9f1d99a..36ced0bb333 100644
--- a/target/mips/tcg/octeon.decode
+++ b/target/mips/tcg/octeon.decode
@@ -55,6 +55,8 @@ MTP0 011100 ..... ..... 00000 00000 001001 @r2
MTP1 011100 ..... ..... 00000 00000 001010 @r2
MTP2 011100 ..... ..... 00000 00000 001011 @r2
+VMULU 011100 ..... ..... ..... 00000 001111 @r3
+
&saa base rt
@saa ...... base:5 rt:5 ................ &saa
SAA 011100 ..... ..... 00000 00000 011000 @saa
diff --git a/target/mips/tcg/octeon_translate.c b/target/mips/tcg/octeon_translate.c
index 10c7d18ad4f..a21f96b5c2a 100644
--- a/target/mips/tcg/octeon_translate.c
+++ b/target/mips/tcg/octeon_translate.c
@@ -264,3 +264,38 @@ static bool trans_mtp(DisasContext *ctx, arg_r2 *a, unsigned int index)
TRANS(MTP0, trans_mtp, 0);
TRANS(MTP1, trans_mtp, 1);
TRANS(MTP2, trans_mtp, 2);
+
+static bool trans_VMULU(DisasContext *ctx, arg_VMULU *a)
+{
+ TCGv_i64 x[3], y[3], z[3];
+ TCGv_i64 tmp = tcg_temp_new_i64();
+ TCGv_i64 zero = tcg_constant_i64(0);
+
+ z[0] = y[0] = tcg_temp_new_i64();
+ z[1] = y[1] = tcg_temp_new_i64();
+ z[2] = y[2] = tcg_temp_new_i64();
+ x[0] = tcg_temp_new_i64();
+ x[1] = tcg_temp_new_i64();
+ x[2] = zero;
+
+ /* Z = rs * (mpl1 : mpl0) + rt */
+ gen_load_gpr(tmp, a->rs);
+ gen_load_gpr(y[0], a->rt);
+ tcg_gen_mulu2_i64(x[0], x[1], tmp, oct_mpl[0]);
+ tcg_gen_mulu2_i64(y[1], y[2], tmp, oct_mpl[1]);
+ tcg_gen_addN_i64(3, z, y, x);
+
+ /* X == (0 : p1 : p0) */
+ x[0] = oct_p[0];
+ x[1] = oct_p[1];
+
+ /* Y == (p1 : p0 : tmp) */
+ y[0] = tmp;
+ y[1] = oct_p[0];
+ y[2] = oct_p[1];
+
+ /* (p1 : p0 : rd) = Z + (0 : p1 : p0) */
+ tcg_gen_addN_i64(3, y, z, x);
+ gen_store_gpr(tmp, a->rd);
+ return true;
+}
diff --git a/tests/tcg/mips/user/isa/octeon/octeon-insns.c b/tests/tcg/mips/user/isa/octeon/octeon-insns.c
index 3c3802ebfee..4647e47f371 100644
--- a/tests/tcg/mips/user/isa/octeon/octeon-insns.c
+++ b/tests/tcg/mips/user/isa/octeon/octeon-insns.c
@@ -86,6 +86,53 @@ static uint64_t octeon_sne(uint64_t rs, uint64_t rt)
return rd;
}
+static uint64_t octeon_vmulu(uint64_t mpl0, uint64_t rs, uint64_t rt)
+{
+ uint64_t rd;
+
+ asm volatile(
+ "move $8, %[mpl0]\n\t"
+ "move $9, $0\n\t"
+ ".word 0x71090008\n\t" /* mtm0 $8, $9 */
+ "move $8, %[rs]\n\t"
+ "move $9, %[rt]\n\t"
+ ".word 0x7109500f\n\t" /* vmulu $10, $8, $9 */
+ "move %[rd], $10\n\t"
+ : [rd] "=r" (rd)
+ : [mpl0] "r" (mpl0), [rs] "r" (rs), [rt] "r" (rt)
+ : "$8", "$9", "$10");
+
+ return rd;
+}
+
+static uint64_t octeon_mtp0_zeroes_p1(void)
+{
+ uint64_t rd;
+
+ asm volatile(
+ "move $8, %[mpl0]\n\t"
+ "move $9, $0\n\t"
+ ".word 0x71090008\n\t" /* mtm0 $8, $9 */
+ "move $8, %[p1]\n\t"
+ "move $9, $0\n\t"
+ ".word 0x7109000a\n\t" /* mtp1 $8, $9 */
+ "move $8, $0\n\t"
+ "move $9, $0\n\t"
+ ".word 0x71090009\n\t" /* mtp0 $8, $9 */
+ "move $8, $0\n\t"
+ "move $9, $0\n\t"
+ ".word 0x7109500f\n\t" /* vmulu $10, $8, $9 */
+ "move $8, $0\n\t"
+ "move $9, $0\n\t"
+ ".word 0x7109500f\n\t" /* vmulu $10, $8, $9 */
+ "move %[rd], $10\n\t"
+ : [rd] "=r" (rd)
+ : [mpl0] "r" (0ULL), [p1] "r" (1ULL)
+ : "$8", "$9", "$10");
+
+ return rd;
+}
+
int main(void)
{
assert(octeon_baddu(0x123, 0x0f0) == 0x13);
@@ -95,6 +142,8 @@ int main(void)
assert(octeon_seq(0xabc, 0xdef) == 0);
assert(octeon_sne(0xabc, 0xabc) == 0);
assert(octeon_sne(0xabc, 0xdef) == 1);
+ assert(octeon_vmulu(5, 7, 11) == 46);
+ assert(octeon_mtp0_zeroes_p1() == 0);
return 0;
}
--
2.53.0
^ permalink raw reply related [flat|nested] 35+ messages in thread
* [PULL 30/33] target/mips: add Octeon VMM0 instruction
2026-05-20 19:23 [PULL 00/33] MIPS patches for 2026-05-20 Philippe Mathieu-Daudé
` (28 preceding siblings ...)
2026-05-20 19:23 ` [PULL 29/33] target/mips: add Octeon VMULU instruction Philippe Mathieu-Daudé
@ 2026-05-20 19:23 ` Philippe Mathieu-Daudé
2026-05-20 19:23 ` [PULL 31/33] target/mips: add Octeon V3MULU instruction Philippe Mathieu-Daudé
` (3 subsequent siblings)
33 siblings, 0 replies; 35+ messages in thread
From: Philippe Mathieu-Daudé @ 2026-05-20 19:23 UTC (permalink / raw)
To: qemu-devel
From: James Hilliard <james.hilliard1@gmail.com>
VMM0 multiplies MPL[0] by rs, adds rt and the queued P[0] partial
product, returns the low result, and feeds that result back into MPL[0].
It sets MPL[1] to zero and clears partial products.
Include hardware-backed regression coverage for VMM0 MPL1 zeroing.
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
Signed-off-by: James Hilliard <james.hilliard1@gmail.com>
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
Tested-by: Philippe Mathieu-Daudé <philmd@linaro.org>
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
Signed-off-by: Philippe Mathieu-Daudé <philmd@linaro.org>
Message-Id: <20260520172313.23777-22-philmd@linaro.org>
---
target/mips/tcg/octeon.decode | 1 +
target/mips/tcg/octeon_translate.c | 16 ++++++
tests/tcg/mips/user/isa/octeon/octeon-insns.c | 55 +++++++++++++++++++
3 files changed, 72 insertions(+)
diff --git a/target/mips/tcg/octeon.decode b/target/mips/tcg/octeon.decode
index 36ced0bb333..f9c32e1dee1 100644
--- a/target/mips/tcg/octeon.decode
+++ b/target/mips/tcg/octeon.decode
@@ -56,6 +56,7 @@ MTP1 011100 ..... ..... 00000 00000 001010 @r2
MTP2 011100 ..... ..... 00000 00000 001011 @r2
VMULU 011100 ..... ..... ..... 00000 001111 @r3
+VMM0 011100 ..... ..... ..... 00000 010000 @r3
&saa base rt
@saa ...... base:5 rt:5 ................ &saa
diff --git a/target/mips/tcg/octeon_translate.c b/target/mips/tcg/octeon_translate.c
index a21f96b5c2a..94f3cf9edd8 100644
--- a/target/mips/tcg/octeon_translate.c
+++ b/target/mips/tcg/octeon_translate.c
@@ -299,3 +299,19 @@ static bool trans_VMULU(DisasContext *ctx, arg_VMULU *a)
gen_store_gpr(tmp, a->rd);
return true;
}
+
+static bool trans_VMM0(DisasContext *ctx, arg_VMM0 *a)
+{
+ TCGv_i64 tmp = tcg_temp_new_i64();
+
+ gen_load_gpr(tmp, a->rs);
+ tcg_gen_mul_i64(oct_mpl[0], oct_mpl[0], tmp);
+ gen_load_gpr(tmp, a->rt);
+ tcg_gen_add_i64(oct_mpl[0], oct_mpl[0], tmp);
+ tcg_gen_add_i64(oct_mpl[0], oct_mpl[0], oct_p[0]);
+ gen_store_gpr(oct_mpl[0], a->rd);
+
+ tcg_gen_movi_i64(oct_mpl[1], 0);
+ octeon_zero_partial_product_state();
+ return true;
+}
diff --git a/tests/tcg/mips/user/isa/octeon/octeon-insns.c b/tests/tcg/mips/user/isa/octeon/octeon-insns.c
index 4647e47f371..9153e37e9e0 100644
--- a/tests/tcg/mips/user/isa/octeon/octeon-insns.c
+++ b/tests/tcg/mips/user/isa/octeon/octeon-insns.c
@@ -105,6 +105,59 @@ static uint64_t octeon_vmulu(uint64_t mpl0, uint64_t rs, uint64_t rt)
return rd;
}
+static uint64_t octeon_vmm0(uint64_t mpl0, uint64_t p0,
+ uint64_t rs, uint64_t rt)
+{
+ uint64_t rd;
+
+ asm volatile(
+ "move $8, %[mpl0]\n\t"
+ "move $9, $0\n\t"
+ ".word 0x71090008\n\t" /* mtm0 $8, $9 */
+ "move $8, %[p0]\n\t"
+ "move $9, $0\n\t"
+ ".word 0x71090009\n\t" /* mtp0 $8, $9 */
+ "move $8, %[rs]\n\t"
+ "move $9, %[rt]\n\t"
+ ".word 0x71095010\n\t" /* vmm0 $10, $8, $9 */
+ "move %[rd], $10\n\t"
+ : [rd] "=r" (rd)
+ : [mpl0] "r" (mpl0), [p0] "r" (p0),
+ [rs] "r" (rs), [rt] "r" (rt)
+ : "$8", "$9", "$10");
+
+ return rd;
+}
+
+static uint64_t octeon_vmm0_zeroes_mpl1(void)
+{
+ uint64_t rd;
+
+ asm volatile(
+ "move $8, %[mpl0]\n\t"
+ "move $9, $0\n\t"
+ ".word 0x71090008\n\t" /* mtm0 $8, $9 */
+ "move $8, %[mpl1]\n\t"
+ "move $9, $0\n\t"
+ ".word 0x7109000c\n\t" /* mtm1 $8, $9 */
+ "move $8, %[vmm0_rs]\n\t"
+ "move $9, $0\n\t"
+ ".word 0x71095010\n\t" /* vmm0 $10, $8, $9 */
+ "move $8, %[vmulu_rs]\n\t"
+ "move $9, $0\n\t"
+ ".word 0x7109500f\n\t" /* vmulu $10, $8, $9 */
+ "move $8, $0\n\t"
+ "move $9, $0\n\t"
+ ".word 0x7109500f\n\t" /* vmulu $10, $8, $9 */
+ "move %[rd], $10\n\t"
+ : [rd] "=r" (rd)
+ : [mpl0] "r" (1ULL), [mpl1] "r" (1ULL),
+ [vmm0_rs] "r" (2ULL), [vmulu_rs] "r" (1ULL)
+ : "$8", "$9", "$10");
+
+ return rd;
+}
+
static uint64_t octeon_mtp0_zeroes_p1(void)
{
uint64_t rd;
@@ -143,6 +196,8 @@ int main(void)
assert(octeon_sne(0xabc, 0xabc) == 0);
assert(octeon_sne(0xabc, 0xdef) == 1);
assert(octeon_vmulu(5, 7, 11) == 46);
+ assert(octeon_vmm0(5, 13, 7, 11) == 59);
+ assert(octeon_vmm0_zeroes_mpl1() == 0);
assert(octeon_mtp0_zeroes_p1() == 0);
return 0;
--
2.53.0
^ permalink raw reply related [flat|nested] 35+ messages in thread
* [PULL 31/33] target/mips: add Octeon V3MULU instruction
2026-05-20 19:23 [PULL 00/33] MIPS patches for 2026-05-20 Philippe Mathieu-Daudé
` (29 preceding siblings ...)
2026-05-20 19:23 ` [PULL 30/33] target/mips: add Octeon VMM0 instruction Philippe Mathieu-Daudé
@ 2026-05-20 19:23 ` Philippe Mathieu-Daudé
2026-05-20 19:23 ` [PULL 32/33] target/mips: add Octeon QMAC instructions Philippe Mathieu-Daudé
` (2 subsequent siblings)
33 siblings, 0 replies; 35+ messages in thread
From: Philippe Mathieu-Daudé @ 2026-05-20 19:23 UTC (permalink / raw)
To: qemu-devel
From: James Hilliard <james.hilliard1@gmail.com>
V3MULU extends VMULU across the full Octeon3 multiplier state, adding rt
and queued partial products.
Return the low result while shifting the remaining accumulated limbs back
into P[0] through P[5].
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
Signed-off-by: James Hilliard <james.hilliard1@gmail.com>
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
Signed-off-by: Philippe Mathieu-Daudé <philmd@linaro.org>
Message-Id: <20260520172313.23777-23-philmd@linaro.org>
---
target/mips/tcg/octeon.decode | 1 +
target/mips/tcg/octeon_translate.c | 40 ++++++++++++++++++++++++++++++
2 files changed, 41 insertions(+)
diff --git a/target/mips/tcg/octeon.decode b/target/mips/tcg/octeon.decode
index f9c32e1dee1..4d0ad058347 100644
--- a/target/mips/tcg/octeon.decode
+++ b/target/mips/tcg/octeon.decode
@@ -57,6 +57,7 @@ MTP2 011100 ..... ..... 00000 00000 001011 @r2
VMULU 011100 ..... ..... ..... 00000 001111 @r3
VMM0 011100 ..... ..... ..... 00000 010000 @r3
+V3MULU 011100 ..... ..... ..... 00000 010001 @r3
&saa base rt
@saa ...... base:5 rt:5 ................ &saa
diff --git a/target/mips/tcg/octeon_translate.c b/target/mips/tcg/octeon_translate.c
index 94f3cf9edd8..7ec942fa347 100644
--- a/target/mips/tcg/octeon_translate.c
+++ b/target/mips/tcg/octeon_translate.c
@@ -315,3 +315,43 @@ static bool trans_VMM0(DisasContext *ctx, arg_VMM0 *a)
octeon_zero_partial_product_state();
return true;
}
+
+static bool trans_V3MULU(DisasContext *ctx, arg_V3MULU *a)
+{
+ TCGv_i64 x[7], y[7], z[7];
+ TCGv_i64 tmp = tcg_temp_new_i64();
+
+ for (int i = 0; i < 7; ++i) {
+ z[i] = tcg_temp_new_i64();
+ y[i] = tcg_temp_new_i64();
+ }
+ memcpy(&x[0], z, 6 * sizeof(TCGv_i64));
+ x[6] = tcg_constant_i64(0);
+
+ /*
+ * Z = rs * mpl -- 64x384->448 bit multiply
+ * Compute even partial products into X and odd partial products into Y.
+ * Include RT into the odd partial products, which are 0 in bits [63:0].
+ */
+ gen_load_gpr(tmp, a->rs);
+ gen_load_gpr(y[0], a->rt);
+ for (int i = 0; i < 6; i += 2) {
+ tcg_gen_mulu2_i64(x[i + 0], x[i + 1], tmp, oct_mpl[i]);
+ tcg_gen_mulu2_i64(y[i + 1], y[i + 2], tmp, oct_mpl[i + 1]);
+ }
+
+ /* Sum even and odd to produce final product, plus rt. */
+ tcg_gen_addN_i64(7, z, x, y);
+
+ /* X == (0 : p5 : p4 : p3 : p2 : p1 : p0) -- x[6] is still 0 */
+ memcpy(&x[0], oct_p, 6 * sizeof(TCGv_i64));
+
+ /* Y == (p5 : p4 : p3 : p2 : p1 : p0 : tmp) */
+ memcpy(&y[1], oct_p, 6 * sizeof(TCGv_i64));
+ y[0] = tmp;
+
+ /* (p* : rd) = (0 : p*) + (rs * mpl + rt) */
+ tcg_gen_addN_i64(7, y, x, z);
+ gen_store_gpr(tmp, a->rd);
+ return true;
+}
--
2.53.0
^ permalink raw reply related [flat|nested] 35+ messages in thread
* [PULL 32/33] target/mips: add Octeon QMAC instructions
2026-05-20 19:23 [PULL 00/33] MIPS patches for 2026-05-20 Philippe Mathieu-Daudé
` (30 preceding siblings ...)
2026-05-20 19:23 ` [PULL 31/33] target/mips: add Octeon V3MULU instruction Philippe Mathieu-Daudé
@ 2026-05-20 19:23 ` Philippe Mathieu-Daudé
2026-05-20 19:23 ` [PULL 33/33] target/mips: add Octeon LA* atomic instructions Philippe Mathieu-Daudé
2026-05-21 19:20 ` [PULL 00/33] MIPS patches for 2026-05-20 Stefan Hajnoczi
33 siblings, 0 replies; 35+ messages in thread
From: Philippe Mathieu-Daudé @ 2026-05-20 19:23 UTC (permalink / raw)
To: qemu-devel
From: James Hilliard <james.hilliard1@gmail.com>
QMAC.0x and QMACS.0x multiply the selected signed Q15 halfword lane from
rs by rt<15:0> and accumulate the Q31 product into the Octeon HI/LO
accumulator state.
QMAC updates the full 64-bit HI/LO accumulator. QMACS saturates the
32-bit Q31 result in LO and keeps HI<0> as the sticky saturation flag.
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
Signed-off-by: James Hilliard <james.hilliard1@gmail.com>
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
[PMD: Add min32/max32 in trans_QMACS()]
Signed-off-by: Philippe Mathieu-Daudé <philmd@linaro.org>
Message-Id: <20260520172313.23777-24-philmd@linaro.org>
---
target/mips/tcg/octeon.decode | 4 ++
target/mips/tcg/octeon_translate.c | 62 ++++++++++++++++++++++++++++++
2 files changed, 66 insertions(+)
diff --git a/target/mips/tcg/octeon.decode b/target/mips/tcg/octeon.decode
index 4d0ad058347..2d02b4e0bc3 100644
--- a/target/mips/tcg/octeon.decode
+++ b/target/mips/tcg/octeon.decode
@@ -28,6 +28,8 @@ BBIT 11 set:1 . 10 rs:5 ..... offset:s16 p=%bbit_p
# SEQI rt, rs, immediate
# SNE rd, rs, rt
# SNEI rt, rs, immediate
+# QMAC.0x rs, rt
+# QMACS.0x rs, rt
@r3 ...... rs:5 rt:5 rd:5 ..... ......
&cmpi rs rt imm
@@ -43,6 +45,8 @@ SEQ 011100 ..... ..... ..... 00000 101010 @r3
SNE 011100 ..... ..... ..... 00000 101011 @r3
SEQI 011100 rs:5 rt:5 imm:s10 101110 &cmpi
SNEI 011100 rs:5 rt:5 imm:s10 101111 &cmpi
+QMACS 011100 rs:5 rt:5 00000 000 lane:2 010010
+QMAC 011100 rs:5 rt:5 00000 100 lane:2 010010
&r2 rs rt
@r2 ...... rs:5 rt:5 ..... ..... ...... &r2
diff --git a/target/mips/tcg/octeon_translate.c b/target/mips/tcg/octeon_translate.c
index 7ec942fa347..90bd68cbf25 100644
--- a/target/mips/tcg/octeon_translate.c
+++ b/target/mips/tcg/octeon_translate.c
@@ -355,3 +355,65 @@ static bool trans_V3MULU(DisasContext *ctx, arg_V3MULU *a)
gen_store_gpr(tmp, a->rd);
return true;
}
+
+static bool trans_QMAC(DisasContext *ctx, arg_QMAC *a)
+{
+ TCGv_i64 t0 = tcg_temp_new_i64();
+ TCGv_i64 t1 = tcg_temp_new_i64();
+
+ gen_load_gpr(t0, a->rt);
+ gen_load_gpr(t1, a->rs);
+
+ /* t0 = rt<0> * rs<lane> * 2 */
+ tcg_gen_ext16s_i64(t0, t0);
+ tcg_gen_sextract_i64(t1, t1, a->lane * 16, 16);
+ tcg_gen_mul_i64(t0, t0, t1);
+ tcg_gen_add_i64(t0, t0, t0);
+
+ /* Saturate -0x8000 * -0x8000 * 2 = 0x80000000 -> 0x7fffffff */
+ tcg_gen_smin_i64(t0, t0, tcg_constant_i64(INT32_MAX));
+
+ /* HI:LO += t0 */
+ tcg_gen_concat32_i64(t1, cpu_LO[0], cpu_HI[0]);
+ tcg_gen_add_i64(t0, t0, t1);
+ tcg_gen_sextract_i64(cpu_LO[0], t0, 0, 32);
+ tcg_gen_sextract_i64(cpu_HI[0], t0, 32, 32);
+ return true;
+}
+
+static bool trans_QMACS(DisasContext *ctx, arg_QMACS *a)
+{
+ TCGv_i64 min32 = tcg_constant_i64(INT32_MIN);
+ TCGv_i64 max32 = tcg_constant_i64(INT32_MAX);
+ TCGv_i64 t0 = tcg_temp_new_i64();
+ TCGv_i64 t1 = tcg_temp_new_i64();
+
+ gen_load_gpr(t0, a->rt);
+ gen_load_gpr(t1, a->rs);
+
+ /* t0 = rt<0> * rs<lane> * 2 */
+ tcg_gen_ext16s_i64(t0, t0);
+ tcg_gen_sextract_i64(t1, t1, a->lane * 16, 16);
+ tcg_gen_mul_i64(t0, t0, t1);
+ tcg_gen_add_i64(t0, t0, t0);
+
+ /*
+ * Saturate -0x8000 * -0x8000 * 2 = 0x80000000 -> 0x7fffffff.
+ * Accumulate overflow in HI[0].
+ */
+ tcg_gen_smin_i64(t1, t0, max32);
+ tcg_gen_setcond_i64(TCG_COND_NE, t0, t0, t1);
+ tcg_gen_or_i64(cpu_HI[0], cpu_HI[0], t0);
+
+ /*
+ * LO = sat32(LO + t0)
+ * Accumulate overflow in HI[0].
+ */
+ tcg_gen_ext32s_i64(t0, cpu_LO[0]);
+ tcg_gen_add_i64(t0, t0, t1);
+ tcg_gen_smin_i64(cpu_LO[0], t0, max32);
+ tcg_gen_smax_i64(cpu_LO[0], cpu_LO[0], min32);
+ tcg_gen_setcond_i64(TCG_COND_NE, t0, t0, cpu_LO[0]);
+ tcg_gen_or_i64(cpu_HI[0], cpu_HI[0], t0);
+ return true;
+}
--
2.53.0
^ permalink raw reply related [flat|nested] 35+ messages in thread
* [PULL 33/33] target/mips: add Octeon LA* atomic instructions
2026-05-20 19:23 [PULL 00/33] MIPS patches for 2026-05-20 Philippe Mathieu-Daudé
` (31 preceding siblings ...)
2026-05-20 19:23 ` [PULL 32/33] target/mips: add Octeon QMAC instructions Philippe Mathieu-Daudé
@ 2026-05-20 19:23 ` Philippe Mathieu-Daudé
2026-05-21 19:20 ` [PULL 00/33] MIPS patches for 2026-05-20 Stefan Hajnoczi
33 siblings, 0 replies; 35+ messages in thread
From: Philippe Mathieu-Daudé @ 2026-05-20 19:23 UTC (permalink / raw)
To: qemu-devel
From: James Hilliard <james.hilliard1@gmail.com>
Implement the Octeon LA* read-modify-write atomic instruction family:
LAI/LAID, LAD/LADD, LAA/LAAD, LAS/LASD, LAC/LACD, and LAW/LAWD.
These operations are architecturally distinct from SAA/SAAD and are used
by existing Octeon user-mode code for atomic counters, bit operations,
and exchange-style updates.
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
Signed-off-by: James Hilliard <james.hilliard1@gmail.com>
Co-developed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
Signed-off-by: Philippe Mathieu-Daudé <philmd@linaro.org>
Message-Id: <bd591571-121c-4eac-8ce6-e1e2234dcf3f@linaro.org>
---
target/mips/tcg/octeon.decode | 17 +++++++++++
target/mips/tcg/octeon_translate.c | 45 ++++++++++++++++++++++++++++++
2 files changed, 62 insertions(+)
diff --git a/target/mips/tcg/octeon.decode b/target/mips/tcg/octeon.decode
index 2d02b4e0bc3..1e44c588dd6 100644
--- a/target/mips/tcg/octeon.decode
+++ b/target/mips/tcg/octeon.decode
@@ -68,6 +68,23 @@ V3MULU 011100 ..... ..... ..... 00000 010001 @r3
SAA 011100 ..... ..... 00000 00000 011000 @saa
SAAD 011100 ..... ..... 00000 00000 011001 @saa
+&la base rd
+&laa base add rd
+@la ...... base:5 ..... rd:5 ........... &la
+@laa ...... base:5 add:5 rd:5 ........... &laa
+LAI 011100 ..... 00000 ..... 00010 011111 @la
+LAID 011100 ..... 00000 ..... 00011 011111 @la
+LAD 011100 ..... 00000 ..... 00110 011111 @la
+LADD 011100 ..... 00000 ..... 00111 011111 @la
+LAA 011100 ..... ..... ..... 10010 011111 @laa
+LAAD 011100 ..... ..... ..... 10011 011111 @laa
+LAS 011100 ..... 00000 ..... 01010 011111 @la
+LASD 011100 ..... 00000 ..... 01011 011111 @la
+LAC 011100 ..... 00000 ..... 01110 011111 @la
+LACD 011100 ..... 00000 ..... 01111 011111 @la
+LAW 011100 ..... ..... ..... 10110 011111 @laa
+LAWD 011100 ..... ..... ..... 10111 011111 @laa
+
&zcb base
ZCB 011100 base:5 00000 00000 1110- 011111 &zcb
diff --git a/target/mips/tcg/octeon_translate.c b/target/mips/tcg/octeon_translate.c
index 90bd68cbf25..b0af2f48382 100644
--- a/target/mips/tcg/octeon_translate.c
+++ b/target/mips/tcg/octeon_translate.c
@@ -185,6 +185,51 @@ static bool trans_saa(DisasContext *ctx, arg_saa *a, MemOp mop)
TRANS(SAA, trans_saa, MO_32);
TRANS(SAAD, trans_saa, MO_64);
+typedef void AtomicThreeOpFn(TCGv_i64, TCGv_va, TCGv_i64, TCGArg, MemOp);
+
+static bool do_atomic_la(DisasContext *ctx, arg_la *a,
+ AtomicThreeOpFn *atomic_fn, int64_t imm, MemOp mop)
+{
+ TCGv_i64 addr = tcg_temp_new_i64();
+ TCGv_i64 old = tcg_temp_new_i64();
+ MemOp amo = mo_endian(ctx) | mop | MO_ALIGN;
+
+ gen_base_offset_addr(ctx, addr, a->base, 0);
+
+ atomic_fn(old, addr, tcg_constant_i64(imm), ctx->mem_idx, amo);
+ gen_store_gpr(old, a->rd);
+ return true;
+}
+
+static bool do_atomic_laa(DisasContext *ctx, arg_laa *a,
+ AtomicThreeOpFn *atomic_fn, MemOp mop)
+{
+ TCGv_i64 addr = tcg_temp_new_i64();
+ TCGv_i64 old = tcg_temp_new_i64();
+ TCGv_i64 value = tcg_temp_new_i64();
+ MemOp amo = mo_endian(ctx) | mop | MO_ALIGN;
+
+ gen_base_offset_addr(ctx, addr, a->base, 0);
+ gen_load_gpr(value, a->add);
+
+ atomic_fn(old, addr, value, ctx->mem_idx, amo);
+ gen_store_gpr(old, a->rd);
+ return true;
+}
+
+TRANS(LAI, do_atomic_la, tcg_gen_atomic_fetch_add_i64, 1, MO_SL);
+TRANS(LAID, do_atomic_la, tcg_gen_atomic_fetch_add_i64, 1, MO_UQ);
+TRANS(LAD, do_atomic_la, tcg_gen_atomic_fetch_add_i64, -1, MO_SL);
+TRANS(LADD, do_atomic_la, tcg_gen_atomic_fetch_add_i64, -1, MO_UQ);
+TRANS(LAA, do_atomic_laa, tcg_gen_atomic_fetch_add_i64, MO_SL);
+TRANS(LAAD, do_atomic_laa, tcg_gen_atomic_fetch_add_i64, MO_UQ);
+TRANS(LAS, do_atomic_la, tcg_gen_atomic_xchg_i64, -1, MO_SL);
+TRANS(LASD, do_atomic_la, tcg_gen_atomic_xchg_i64, -1, MO_UQ);
+TRANS(LAC, do_atomic_la, tcg_gen_atomic_xchg_i64, 0, MO_SL);
+TRANS(LACD, do_atomic_la, tcg_gen_atomic_xchg_i64, 0, MO_UQ);
+TRANS(LAW, do_atomic_laa, tcg_gen_atomic_xchg_i64, MO_SL);
+TRANS(LAWD, do_atomic_laa, tcg_gen_atomic_xchg_i64, MO_UQ);
+
static bool trans_ZCB(DisasContext *ctx, arg_ZCB *a)
{
TCGv_i64 addr = tcg_temp_new_i64();
--
2.53.0
^ permalink raw reply related [flat|nested] 35+ messages in thread
* Re: [PULL 00/33] MIPS patches for 2026-05-20
2026-05-20 19:23 [PULL 00/33] MIPS patches for 2026-05-20 Philippe Mathieu-Daudé
` (32 preceding siblings ...)
2026-05-20 19:23 ` [PULL 33/33] target/mips: add Octeon LA* atomic instructions Philippe Mathieu-Daudé
@ 2026-05-21 19:20 ` Stefan Hajnoczi
33 siblings, 0 replies; 35+ messages in thread
From: Stefan Hajnoczi @ 2026-05-21 19:20 UTC (permalink / raw)
To: Philippe Mathieu-Daudé; +Cc: qemu-devel
[-- Attachment #1: Type: text/plain, Size: 116 bytes --]
Applied, thanks.
Please update the changelog at https://wiki.qemu.org/ChangeLog/11.1 for any user-visible changes.
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 488 bytes --]
^ permalink raw reply [flat|nested] 35+ messages in thread
end of thread, other threads:[~2026-05-21 19:21 UTC | newest]
Thread overview: 35+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-05-20 19:23 [PULL 00/33] MIPS patches for 2026-05-20 Philippe Mathieu-Daudé
2026-05-20 19:23 ` [PULL 01/33] docker: Remove LegacyKeyValueFormat warnings in non-generated files Philippe Mathieu-Daudé
2026-05-20 19:23 ` [PULL 02/33] docker: Remove LegacyKeyValueFormat warnings in generated files Philippe Mathieu-Daudé
2026-05-20 19:23 ` [PULL 03/33] buildsys: Remove MIPS cross containers Philippe Mathieu-Daudé
2026-05-20 19:23 ` [PULL 04/33] buildsys: Remove support for MIPS hosts Philippe Mathieu-Daudé
2026-05-20 19:23 ` [PULL 05/33] hw/mips: Include missing 'cpu.h' header Philippe Mathieu-Daudé
2026-05-20 19:23 ` [PULL 06/33] buildsys: Remove MIPS KVM Philippe Mathieu-Daudé
2026-05-20 19:23 ` [PULL 07/33] buildsys: Remove MIPS TCG backend Philippe Mathieu-Daudé
2026-05-20 19:23 ` [PULL 08/33] hw/intc/mips_gic: Avoid Coverity complaint in VP writes Philippe Mathieu-Daudé
2026-05-20 19:23 ` [PULL 09/33] linux-user/mips: implement sysmips(MIPS_FLUSH_CACHE) Philippe Mathieu-Daudé
2026-05-20 19:23 ` [PULL 10/33] linux-user/mips: implement sysmips(MIPS_ATOMIC_SET) Philippe Mathieu-Daudé
2026-05-20 19:23 ` [PULL 11/33] linux-user/mips, target/mips: honor MIPS_FIXADE for unaligned accesses Philippe Mathieu-Daudé
2026-05-20 19:23 ` [PULL 12/33] target/mips: expose Octeon68XX floating-point support Philippe Mathieu-Daudé
2026-05-20 19:23 ` [PULL 13/33] tests/tcg/mips: add Octeon instruction smoke test Philippe Mathieu-Daudé
2026-05-20 19:23 ` [PULL 14/33] target/mips: fix Octeon arithmetic destination handling Philippe Mathieu-Daudé
2026-05-20 19:23 ` [PULL 15/33] target/mips: drop Octeon zero-register fast paths Philippe Mathieu-Daudé
2026-05-20 19:23 ` [PULL 16/33] target/mips: split Octeon SEQ/SNE decode Philippe Mathieu-Daudé
2026-05-20 19:23 ` [PULL 17/33] target/mips: split Octeon SEQI/SNEI decode Philippe Mathieu-Daudé
2026-05-20 19:23 ` [PULL 18/33] target/mips: add Octeon LBX instruction Philippe Mathieu-Daudé
2026-05-20 19:23 ` [PULL 19/33] target/mips: add Octeon LHUX instruction Philippe Mathieu-Daudé
2026-05-20 19:23 ` [PULL 20/33] target/mips: add Octeon LWUX instruction Philippe Mathieu-Daudé
2026-05-20 19:23 ` [PULL 21/33] target/mips: add Octeon SAA instruction Philippe Mathieu-Daudé
2026-05-20 19:23 ` [PULL 22/33] target/mips: add Octeon SAAD instruction Philippe Mathieu-Daudé
2026-05-20 19:23 ` [PULL 23/33] tcg: Introduce tcg_zero_i128() Philippe Mathieu-Daudé
2026-05-20 19:23 ` [PULL 24/33] target/mips: add Octeon ZCB and ZCBT instructions Philippe Mathieu-Daudé
2026-05-20 19:23 ` [PULL 25/33] tcg: Introduce tcg_gen_addN_i64 Philippe Mathieu-Daudé
2026-05-20 19:23 ` [PULL 26/33] target/mips: add Octeon multiplier state Philippe Mathieu-Daudé
2026-05-20 19:23 ` [PULL 27/33] target/mips: add Octeon MTM instructions Philippe Mathieu-Daudé
2026-05-20 19:23 ` [PULL 28/33] target/mips: add Octeon MTP instructions Philippe Mathieu-Daudé
2026-05-20 19:23 ` [PULL 29/33] target/mips: add Octeon VMULU instruction Philippe Mathieu-Daudé
2026-05-20 19:23 ` [PULL 30/33] target/mips: add Octeon VMM0 instruction Philippe Mathieu-Daudé
2026-05-20 19:23 ` [PULL 31/33] target/mips: add Octeon V3MULU instruction Philippe Mathieu-Daudé
2026-05-20 19:23 ` [PULL 32/33] target/mips: add Octeon QMAC instructions Philippe Mathieu-Daudé
2026-05-20 19:23 ` [PULL 33/33] target/mips: add Octeon LA* atomic instructions Philippe Mathieu-Daudé
2026-05-21 19:20 ` [PULL 00/33] MIPS patches for 2026-05-20 Stefan Hajnoczi
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.