WelcomeWelcome | FAQFAQ | DownloadsDownloads | WikiWiki

Author Topic: Rust i686 assumes SSE2  (Read 842 times)

Offline easyaspi314

  • Newbie
  • *
  • Posts: 2
Rust i686 assumes SSE2
« on: March 03, 2024, 03:56:09 PM »
Tried out tinycore on my old Pentium III and I noticed that the Rust-based librsvg crashes with an illegal instruction. As does rustc itself.

Upon checking the binary, it looks like Rust has been configured to assume SSE2, the default on the rustup i686-linux-gnu target. In order to target earlier processors the entire toolchain must be configured and recompiled manually.

Online Juanito

  • Administrator
  • Hero Member
  • *****
  • Posts: 14561
Re: Rust i686 assumes SSE2
« Reply #1 on: March 03, 2024, 11:17:14 PM »
The trick is getting rust to compile for i486, suggestions welcome..

Offline patrikg

  • Wiki Author
  • Hero Member
  • *****
  • Posts: 674
Re: Rust i686 assumes SSE2
« Reply #2 on: March 04, 2024, 12:40:27 AM »
I think it's can be done with T2sde.

I follow Rene a lot, and his adventure of his "own" distro.

https://t2sde.org/

Online Juanito

  • Administrator
  • Hero Member
  • *****
  • Posts: 14561
Re: Rust i686 assumes SSE2
« Reply #3 on: March 04, 2024, 04:50:34 AM »
The rust file i686_unknown_linux_gnu.rs contains:
Code: [Select]
use crate::spec::{LinkerFlavor, StackProbeType, Target};

pub fn target() -> Target {
    let mut base = super::linux_gnu_base::opts();
    base.cpu = "pentium4".to_string();
    base.max_atomic_width = Some(64);
    base.pre_link_args.entry(LinkerFlavor::Gcc).or_default().push("-m32".to_string());
    // don't use probe-stack=inline-asm until rust#83139 and rust#84667 are resolved
    base.stack_probes = StackProbeType::Call;

    Target {
        llvm_target: "i686-unknown-linux-gnu".to_string(),
        pointer_width: 32,
        data_layout: "e-m:e-p:32:32-p270:32:32-p271:32:32-p272:64:64-\
            f64:32:64-f80:32-n8:16:32-S128"
            .to_string(),
        arch: "x86".to_string(),
        options: base,
    }
}

..which probably expains why your pentium 3 fails.

If I change pentium4 -> pentium2 and/or i686-unknown-linux-gnu -> i486-unknown-linux-gnu the build fails.

If I use RUSTFLAGS="$RUSTFLAGS -Ctarget-cpu=i486 -Clink-args=-lffi" the build also fails.

llvm/clang was compiled with -march=pentium-m -mtune=i686 as using -march=i484 fails


Edit: -Ctarget-cpu=i586 is building so far..
« Last Edit: March 04, 2024, 05:49:27 AM by Juanito »

Online Juanito

  • Administrator
  • Hero Member
  • *****
  • Posts: 14561
Re: Rust i686 assumes SSE2
« Reply #4 on: March 05, 2024, 05:36:44 AM »
rust built with -Ctarget-cpu=i586.

I don't have an i486/i586 to test, maybe you download the rebuilt extension from here and test:

http://tinycorelinux.net/15.x/x86/tcz/src/rust/

Offline patrikg

  • Wiki Author
  • Hero Member
  • *****
  • Posts: 674
Re: Rust i686 assumes SSE2
« Reply #5 on: March 05, 2024, 08:08:36 AM »
Maybe some one can run it in qemu.

Code: [Select]
qemu-system-i386 -machine pc -cpu 486
Code: [Select]
qemu-system-i386 -machine pc -cpu pentium3
« Last Edit: March 05, 2024, 08:12:23 AM by patrikg »

Offline curaga

  • Administrator
  • Hero Member
  • *****
  • Posts: 10965
Re: Rust i686 assumes SSE2
« Reply #6 on: March 05, 2024, 08:18:58 AM »
We found before that Qemu is not accurate, it back then allowed new instructions even when told to be a 486.
The only barriers that can stop you are the ones you create yourself.

Offline easyaspi314

  • Newbie
  • *
  • Posts: 2
Re: Rust i686 assumes SSE2
« Reply #7 on: March 05, 2024, 06:51:32 PM »
There was a SIGILL but it was in libllvm-13.so (llvm-lib) which is marked as a Pentium-M only package. So...can't really change that.

Maybe the issue is just librsvg which needs to be recompiled with -C target-cpu=i586. I just don't know if there are any other Rust-based packages in the database that also don't have the rust target flag properly set.

Online Juanito

  • Administrator
  • Hero Member
  • *****
  • Posts: 14561
Re: Rust i686 assumes SSE2
« Reply #8 on: March 06, 2024, 03:50:39 AM »
I recompiled librsvg with  RUSTFLAGS="$RUSTFLAGS -Ctarget-cpu=i586", though it was already compiled with CC="gcc -march=i486 -mtune=i686 -Os -pipe", so I'm not sure it will have made a difference.

You can find the version to test here:

http://tinycorelinux.net/15.x/x86/tcz/src/librsvg/

Offline linic

  • Newbie
  • *
  • Posts: 18
Re: Rust i686 assumes SSE2
« Reply #9 on: March 08, 2024, 11:36:22 AM »
Is the error similar to this?
Code: [Select]
rustc[3007] trap invalid opcode ip:aff76daa sp:bfe0c170 error:0 in libllvm-13.so[aff30000+1a07000]
Illegal instruction

I have a Pentium II so I searched about which flags to use to compile a version of rustc and cargo to match my CPU.
You'll probably need these
Code: [Select]
export CFLAGS="-march=pentium"
export CXXFLAGS="-march=pentium"
export RUST_BACKTRACE=full
You can look here to see how I use them to compile rust for my Pentium II https://github.com/linic/rust-i586/blob/main/Dockerfile#L15

If it's not enough, maybe you'll need a rust compiler that has been compiled with these flags (and actually more flags than these). I generated a docker image that has a rust compiled this way and which has the various tar.gz files in it. There's one rust-nightly-i586-unknown-linux-gnu.tar.gz which has all the executables (rustc, cargo, etc... + documentation). It's the one I use.
The code to generate the image is here https://github.com/linic/rust-i586/
The images are here https://hub.docker.com/repository/docker/linichotmailca/rust-i586/general
I remember testing the rust 1.75.0 executables from linichotmailca/rust-i586:1.75.0 on my Pentium II (you can docker cp them out of the image) see the usage https://github.com/linic/rust-i586?tab=readme-ov-file#usage. I generated 1.76.0 recently, but I haven't had the time to test it yet on my physical Pentium II. It was generated the same way as 1.75.0 so it should work too probably.

I also have a tcl core image with a rust-1.75.0-i586.tcz ready to use here https://hub.docker.com/repository/docker/linichotmailca/tcl-core-rust-i586/general
The source code to generate that image and the tcz inside of it is here https://github.com/linic/tcl-core-rust-i586. Check the Dockerfile. You can essentially run mostly the same commands (although you'll have to docker cp the resource files from the resource images or compile your own by following what the Dockerfiles for those image do) to generate your own tcz on a real machine.

With the linichotmailca/tcl-core-rust-i586 image, you can docker run it with
Code: [Select]
sudo docker run --name tcl-core-x86-test --interactive <replace-with-your-image-id> /bin/sh (I suggest doing a docker exec -it tcl-core-x86 /bin/sh afterwards in another terminal to get a fully working console you'll see what I mean). Once you have a console, I think you should be able to use that rust version and it should compile programs without the illegal instructions. It's possible to retrieve them from the running container again with docker cp. Maybe you'll still need to set the flags
Code: [Select]
export CFLAGS="-march=pentium"
export CXXFLAGS="-march=pentium"
export RUST_BACKTRACE=full

Offline mocore

  • Hero Member
  • *****
  • Posts: 509
  • ~.~
Re: Rust i686 assumes SSE2
« Reply #10 on: March 10, 2024, 03:42:59 AM »
apparently
We found before that Qemu is not accurate, it back then allowed new instructions even when told to be a 486.

it appears *now* that it might be possible to disable

https://ahelpme.com/software/qemu/qemu-full-virtualization-cpu-emulations-enable-disable-cpu-flags-instruction-sets-of-qemu-8-0/


...ftr apparently
Re: tiny core on 486 : https://forum.tinycorelinux.net/index.php/topic,4908.msg25864.html#msg25864
apparently

Our users found out that the glibc in 2.x includes some 686 code:
http://forum.tinycorelinux.net/index.php?topic=1685.0

Re Qemu, its 486 emulation is not 486-compliant, it allows the 686 code without issue. Bochs is a better test.