[PATCH 0/5] buildsys: Remove support for MIPS host
During the v10.2 development cycle we deprecated MIPS host support (mostly because Debian which we use to test in our CI dropped the architecture when releasing Debian 13). This series removes host support for MIPS. Philippe Mathieu-Daudé (5): 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 MAINTAINERS | 15 - 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/user/thunk.h | 2 +- linux-user/include/host/mips64/host-signal.h | 75 - target/mips/kvm_mips.h | 28 - 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 - hw/intc/mips_gic.c | 11 +- hw/mips/loongson3_virt.c | 67 +- hw/mips/malta.c | 1 - hw/mips/mips_int.c | 7 +- linux-user/mmap.c | 2 +- target/mips/cpu.c | 5 - target/mips/kvm.c | 1283 -------- target/mips/system/cp0_timer.c | 12 +- target/mips/system/physaddr.c | 1 - util/cacheflush.c | 16 - tcg/mips64/tcg-target.c.inc | 2605 ----------------- .gitlab-ci.d/container-cross.yml | 6 - .gitlab-ci.d/containers.yml | 1 - .gitlab-ci.d/crossbuilds.yml | 22 - target/mips/meson.build | 6 +- tests/docker/Makefile.include | 1 - .../dockerfiles/debian-mips64el-cross.docker | 187 -- .../dockerfiles/debian-mipsel-cross.docker | 187 -- tests/lcitool/refresh | 12 - 35 files changed, 32 insertions(+), 4806 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 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 -- 2.53.0
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> --- configure | 1 - .gitlab-ci.d/container-cross.yml | 6 - .gitlab-ci.d/containers.yml | 1 - .gitlab-ci.d/crossbuilds.yml | 22 --- tests/docker/Makefile.include | 1 - .../dockerfiles/debian-mips64el-cross.docker | 187 ------------------ .../dockerfiles/debian-mipsel-cross.docker | 187 ------------------ tests/lcitool/refresh | 12 -- 8 files changed, 417 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/.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 diff --git a/tests/docker/dockerfiles/debian-mips64el-cross.docker b/tests/docker/dockerfiles/debian-mips64el-cross.docker deleted file mode 100644 index 90a2ef15574..00000000000 --- a/tests/docker/dockerfiles/debian-mips64el-cross.docker +++ /dev/null @@ -1,187 +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 \ - libglusterfs-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 b7e36b3d974..00000000000 --- a/tests/docker/dockerfiles/debian-mipsel-cross.docker +++ /dev/null @@ -1,187 +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 \ - libglusterfs-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/tests/lcitool/refresh b/tests/lcitool/refresh index e4d01d792b7..33cbad2ac29 100755 --- a/tests/lcitool/refresh +++ b/tests/lcitool/refresh @@ -263,18 +263,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-archit... - 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-", -- 2.53.0
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> --- 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 5551bd12ad8..9e889601df1 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 626162022a8..1a30b941d65 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 5fbdc75a0fc..692d0bc0eab 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() @@ -5036,14 +5036,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
"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> --- 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
We removed support for MIPS host. The KVM MIPS code is now unreachable, remove it. Signed-off-by: Philippe Mathieu-Daudé <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 9d3d6459537..978696bbdb5 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -482,12 +482,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 692d0bc0eab..839f56b737b 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 f803d477632..a0e7e6a82a8 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 b8e1a5ac98e..1daf2fa0a28 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
We removed support for MIPS host. Remove the now unreachable TCG host code. Signed-off-by: Philippe Mathieu-Daudé <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 ------------------ 11 files changed, 2 insertions(+), 2899 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 diff --git a/MAINTAINERS b/MAINTAINERS index 978696bbdb5..a47de471fcb 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -4132,15 +4132,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)); -} -- 2.53.0
On 5/11/26 08:53, Philippe Mathieu-Daudé wrote:
We removed support for MIPS host. Remove the now unreachable TCG host code.
Signed-off-by: Philippe Mathieu-Daudé<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 ------------------ 11 files changed, 2 insertions(+), 2899 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
Missed ./common-user/host/mips64. Otherwise, Reviewed-by: Richard Henderson <richard.henderson@linaro.org> r~
On 11/5/26 16:03, Richard Henderson wrote:
On 5/11/26 08:53, Philippe Mathieu-Daudé wrote:
We removed support for MIPS host. Remove the now unreachable TCG host code.
Signed-off-by: Philippe Mathieu-Daudé<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 ------------------ 11 files changed, 2 insertions(+), 2899 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
Missed ./common-user/host/mips64.
Oh, thanks!
Otherwise, Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
r~
On 5/11/26 08:53, Philippe Mathieu-Daudé wrote:
During the v10.2 development cycle we deprecated MIPS host support (mostly because Debian which we use to test in our CI dropped the architecture when releasing Debian 13).
This series removes host support for MIPS.
Philippe Mathieu-Daudé (5): 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
Modulo the note on patch 5, Reviewed-by: Richard Henderson <richard.henderson@linaro.org> r~
On 11/5/26 15:53, Philippe Mathieu-Daudé wrote:
This series removes host support for MIPS.
Philippe Mathieu-Daudé (5): 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
Series queued, thanks.
participants (2)
-
Philippe Mathieu-Daudé -
Richard Henderson