Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

MIPS on Linux support #1075

Closed
GTANAdam opened this issue Apr 27, 2020 · 80 comments
Closed

MIPS on Linux support #1075

GTANAdam opened this issue Apr 27, 2020 · 80 comments
Labels
enhancement New feature or request

Comments

@GTANAdam
Copy link

GTANAdam commented Apr 27, 2020

It seems that tinygo doesn't not support MIPS based embedded devices out of the box, although LLVM does support the following:

    mips       - MIPS (32-bit big endian)
    mips64     - MIPS (64-bit big endian)
    mips64el   - MIPS (64-bit little endian)
    mipsel     - MIPS (32-bit little endian)

My intent is to execute the tinygo compiled binary within a mipsel linux box, no bare metal support, so I assume that's feasible considering llvm support.
This would be extremely useful for routers with a limited set of storage and ram.

@niaow
Copy link
Member

niaow commented Apr 27, 2020

As far as I can tell, there are only a few things required to add support for such a target:

  1. a runtime arch file - provides the equivalent GOARCH value, bitness of the cpu, etc. (example here)
  2. a mapping from the LLVM arch name to the GOARCH name here
  3. helper program selection guesses here

I can't think of anywhere else where changes would be necessary. After the appropriate changes are added, you should be able to build for MIPS by supplying an appropriate LLVM target to the -target flag.

@deadprogram
Copy link
Member

Is there specific MIPS hardware you are looking to support?

@niaow niaow changed the title MIPS architecture support MIPS on Linux support Apr 27, 2020
@niaow
Copy link
Member

niaow commented Apr 27, 2020

@deadprogram This issue seems to be regarding a Linux target, rather than baremetal.

@GTANAdam
Copy link
Author

GTANAdam commented Apr 27, 2020

Is there specific MIPS hardware you are looking to support?

Yeah, It would be great to have bare metal support for mips24kc out of the box since that's basically used by most routers.
I'll try tinkering around, might learn something from it.

UPDATE:

It seems that after manually building LLVM as mentioned in Getting Started doesn't contain mips arch as a target

LLVM (http://llvm.org/):
  LLVM version 10.0.1
  Optimized build.
  Default target: x86_64-unknown-linux-gnu
  Host CPU: skylake

  Registered Targets:
    aarch64    - AArch64 (little endian)
    aarch64_32 - AArch64 (little endian ILP32)
    aarch64_be - AArch64 (big endian)
    arm        - ARM
    arm64      - ARM64 (little endian)
    arm64_32   - ARM64 (little endian ILP32)
    armeb      - ARM (big endian)
    avr        - Atmel AVR Microcontroller
    riscv32    - 32-bit RISC-V
    riscv64    - 64-bit RISC-V
    thumb      - Thumb
    thumbeb    - Thumb (big endian)
    wasm32     - WebAssembly 32-bit
    wasm64     - WebAssembly 64-bit
    x86        - 32-bit X86: Pentium-Pro and above
    x86-64     - 64-bit X86: EM64T and AMD64

@aykevl
Copy link
Member

aykevl commented Apr 27, 2020

Yeah, It would be great to have bare metal support for mips24kc out of the box since that's basically used by most routers.

My intent is to execute the tinygo compiled binary within a mipsel linux box, no bare metal support, so I assume that's feasible considering llvm support.

Are you interested in baremetal or Linux support?
The two are quite different. Running under Linux would be relatively easy, needing basically the changes that @jaddr2line mentioned above. Baremetal support will take a lot more work and will usually be very chip specific. To get an idea of what is needed, see this PR (but note that quite a few things changed since then to avoid duplicated code).

It seems that after manually building LLVM as mentioned in Getting Started doesn't contain mips arch as a target

Yes, you need to modify this line to add Mips to the enabled targets:

tinygo/Makefile

Line 157 in a9ba6eb

mkdir -p $(LLVM_BUILDDIR); cd $(LLVM_BUILDDIR); cmake -G Ninja $(TINYGO_SOURCE_DIR)/$(LLVM_PROJECTDIR)/llvm "-DLLVM_TARGETS_TO_BUILD=X86;ARM;AArch64;RISCV;WebAssembly" "-DLLVM_EXPERIMENTAL_TARGETS_TO_BUILD=AVR" -DCMAKE_BUILD_TYPE=Release -DLIBCLANG_BUILD_STATIC=ON -DLLVM_ENABLE_TERMINFO=OFF -DLLVM_ENABLE_ZLIB=OFF -DLLVM_ENABLE_PROJECTS="clang;lld" -DLLVM_TOOL_CLANG_TOOLS_EXTRA_BUILD=OFF $(LLVM_OPTION)

It may be easier to instead use a prebuilt version of LLVM, which you can easily install on MacOS and most Linux distributions. It will have Mips already included as a target (no need to rebuild LLVM).

@GTANAdam
Copy link
Author

GTANAdam commented Apr 28, 2020

Yes, you need to modify this line to add Mips to the enabled targets:

Thank you for the tip, I was already digging inside, getting that little mipsy mips support in LLVM 😄

Are you interested in baremetal or Linux support?

I am honestly interested in having it work in both Linux and bare metal but I do understand that bringing bare metal support is a bit out of my skill scope, but I am very eager to learn and contribute

UPDATE:

Well, after some tinkering around, I was successfully able to compile mipsel targeted binaries (statically linked) and as well as executing them

Here are the file size differences between golang compiled binaries and tinygo:

/opt/home/admin # ls -l
-rwxr-xr-x    1 admin    root        514908 Apr 28 06:33 hello_mipsel_tinygo
-rwxr-xr-x    1 admin    root          5704 Apr 28 06:17 hello_mipsel_tinygo_dynlink
-rwxr-xr-x    1 admin    root        851968 Apr 28 06:14 hello_mipsle_go
package main

func main() {
    print("HELLO\n")
}

Note: the binaries were compiled with omitted DWARF debugging information as well as symbol table generation using -ldflags "-s -w" to achieve the lowest sizes without using upx.

a brief ldd look into the dynamically linked binary:

/opt/home/admin # ldd hello_mipsel_tinygo_dynlink
checking sub-depends for 'not found'
        libc.so.6 => not found (0x00000000)
        /lib/ld.so.1 => /lib/ld.so.1 (0x00000000)

What's interesting here is the produced (by default) dynamically linked binary that is small in size albeit depending on libc.so.6 (glibC) which is missing by default on OpenWRT (muslC), so in order to fix this, an openwrt musl toolchain should be used but this out of the scope of this issue but I will eventually document that as soon as I'm finished.
This should allow the OpenWRT community to adopt tinygo.

@deadprogram deadprogram added the enhancement New feature or request label Apr 28, 2020
@olarriga
Copy link

I'm also interrested on compiling for MTK7628NN with Linux support. With Go I select GOARCH=mipsle GOMIPS=softfloat.
It's possible with TinyGo ? Do you have any documents ?
Thanks

@niaow
Copy link
Member

niaow commented Apr 28, 2020

@olarriga this is not yet implemented, see my first comment on this issue

@niaow niaow added the good first issue Good for newcomers label Apr 28, 2020
@GTANAdam
Copy link
Author

GTANAdam commented Apr 28, 2020

I'm also interrested on compiling for MTK7628NN with Linux support. With Go I select GOARCH=mipsle GOMIPS=softfloat.
It's possible with TinyGo ? Do you have any documents ?
Thanks

Yes, it's possible and beautiful, I'm currently working on it, will have a PR and a documentation published soon.

UPDATE:

Currently the compilation is spewing a warning concerning wrong floating point setting but the binary is functioning properly, yet to figure out where to put the -msoft-float flag in tinygo/llvm given that the musl toolchain already uses -msoft-float

/home/adam/toolchain/toolchain-mips_24kc_gcc-8.4.0_musl/bin/../lib/gcc/mips-openwrt-linux-musl/8.4.0/../../../../mips-openwrt-linux-musl/bin/ld: warning: /tmp/tinygo498244004/main uses -msoft-float (set by /home/adam/toolchain/toolchain-mips_24kc_gcc-8.4.0_musl/bin/../lib/gcc/mips-openwrt-linux-musl/8.4.0/../../../../mips-openwrt-linux-musl/lib/crt1.o), /tmp/tinygo498244004/main.o uses -mhard-float

UPDATE:

Seems like -msoft-float flag is being ignored by llvm/clang, but considering that the binaries are working properly, it isn't critical atm.

UPDATE:

After having configured both the mips and mipsel toolchains, I went ahead and tried to compile a sample golang code using the fmt library, the compiler spewed the following:

../tinygo/tinygo build -target "mipsel-openwrt-linux" -o hello main.go
../../../usr/lib/go-1.13/src/syscall/zsyscall_linux_mipsle.go:310:21: unknown GOOS/GOARCH for syscall: linux/mipsle
../../../usr/lib/go-1.13/src/syscall/zsyscall_linux_mipsle.go:1716:23: unknown GOOS/GOARCH for syscall: linux/mipsle
../../../usr/lib/go-1.13/src/syscall/zsyscall_linux_mipsle.go:1048:21: unknown GOOS/GOARCH for syscall: linux/mipsle
../../../usr/lib/go-1.13/src/syscall/zsyscall_linux_mipsle.go:732:22: unknown GOOS/GOARCH for syscall: linux/mipsle
../../../usr/lib/go-1.13/src/syscall/zsyscall_linux_mipsle.go:1005:22: unknown GOOS/GOARCH for syscall: linux/mipsle

I figured that compiler/syscall.go needs some work as well in order for the go libraries to compile and by the looks of it, it became much more challenging..

UPDATE:

After hours of thorough studying of mips specs and docs, I have found out that the /o32 ABI only has 4 argument registers which is less than syscall6 arg length 🤔... additionally, the syscall manpage mentions that the syscall convention passes arguments 5+ through 8 on the user stack but that requires a different implementation in gollvm(?)..
I am currently limited by my lack of knowledge in this area so any input would be appreciated! 😄

UPDATE:

I had no luck in assembling a working solution so far so it's a roadblock at the moment, basically everything works but syscalls

@aykevl
Copy link
Member

aykevl commented Apr 29, 2020

Currently the compilation is spewing a warning concerning wrong floating point setting but the binary is functioning properly, yet to figure out where to put the -msoft-float flag in tinygo/llvm given that the musl toolchain already uses -msoft-float

/home/adam/toolchain/toolchain-mips_24kc_gcc-8.4.0_musl/bin/../lib/gcc/mips-openwrt-linux-musl/8.4.0/../../../../mips-openwrt-linux-musl/bin/ld: warning: /tmp/tinygo498244004/main uses -msoft-float (set by /home/adam/toolchain/toolchain-mips_24kc_gcc-8.4.0_musl/bin/../lib/gcc/mips-openwrt-linux-musl/8.4.0/../../../../mips-openwrt-linux-musl/lib/crt1.o), /tmp/tinygo498244004/main.o uses -mhard-float

You probably need to set a flag (-soft-float maybe?) in the BuildTags property. This list of flags is for how TinyGo compiles the binary, and is independent of CFlags (which is used to build the C parts). You can figure out the needed flag with the Clang -v flag (look for -target-fetature).
While some programs may work, I do not think programs that have float operations will work without this change. Try running testdata/float.go for example.

After hours of thorough studying of mips specs and docs, I have found out that the /o32 ABI only has 4 argument registers which is less than syscall6 arg length thinking... additionally, the syscall manpage mentions that the syscall convention passes arguments 5+ through 8 on the user stack but that requires a different implementation in gollvm(?)..
I am currently limited by my lack of knowledge in this area so any input would be appreciated! smile

Ah really, they are passing syscall arguments on the stack? That complicates things a bit.
I think the easiest option is to write assembly functions that do the syscall itself. Calling those functions will make sure LLVM puts those values on the stack in the right place. There is a bit of a complication however with the success/error value (in $a3) so the function may need to do a bit more than just call syscall and return.

Source: https://www.linux-mips.org/wiki/Syscall

@deadprogram deadprogram removed the good first issue Good for newcomers label Mar 4, 2021
@ski7777
Copy link

ski7777 commented Mar 19, 2021

Any update on this?

@GTANAdam
Copy link
Author

GTANAdam commented Mar 20, 2021

Any update on this?

Unfortunately not, I have decided that writing code for MIPS based embedded devices is much better done via C/C++.
I haven't had the time to figure it out, if one could provide some examples on passing 5+ arguments via stack for syscalls then I could probably try it out again.

@dosgo
Copy link

dosgo commented Sep 29, 2021

Is there no reference value for the system call of the golang source code Go\src\syscall. Although C/C++ is good, cross-compilation is troublesome, and development efficiency is not good. Rust solves the cross-compilation problem well.

@mutexstream
Copy link

Any update on this? This will really be very beneficial for running go code on routers.

@aykevl
Copy link
Member

aykevl commented May 31, 2022

We could do it, but I haven't seen a lot of demand (except for this issue). I'm somewhat worried about the maintenance burden this will cause, because it would add yet another architecture. We currently support arm, arm64, 386, amd64, avr, xtensa, and wasm. But if there is enough demand or a good use case, this would certainly be interesting to support.

@mutexstream
Copy link

Writing networking and server code for routers with go should be a very interesting use case. The main reason why go isn't even considered is because of the huge binary size, but if tiny go can be made to work with these routers, it will be a very good alternative to C/C++ for many cases.

Example:
https://mender.io/blog/why-did-we-choose-golang-over-c
https://stackoverflow.blog/2022/04/04/comparing-go-vs-c-in-embedded-applications/

@dosgo
Copy link

dosgo commented Sep 21, 2022

We could do it, but I haven't seen a lot of demand (except for this issue). I'm somewhat worried about the maintenance burden this will cause, because it would add yet another architecture. We currently support arm, arm64, 386, amd64, avr, xtensa, and wasm. But if there is enough demand or a good use case, this would certainly be interesting to support.

I think mips is much more important than 386 and amd64. Mips are only embedded devices such as routing. On the contrary, 386 amd64 devices have huge space and can use official compilers.

@vshymanskyy
Copy link

vshymanskyy commented Sep 21, 2022 via email

@aykevl
Copy link
Member

aykevl commented Sep 29, 2022

So if we would add support for MIPS, which would it be? Apparently there are 4 MIPS architecture variants that we could support:

mips       - MIPS (32-bit big endian)
mips64     - MIPS (64-bit big endian)
mips64el   - MIPS (64-bit little endian)
mipsel     - MIPS (32-bit little endian)

I don't think 64-bit MIPS needs TinyGo, so that leaves it with mips and mipsel. I don't know which of the two architectures (big or little endian) is used more widely, but I would expect a little-endian system to be much easier to add support for since all architectures currently supported by TinyGo are little endian.

@dosgo
Copy link

dosgo commented Sep 29, 2022

The mips endian seems to be OS dependent! https://openwrt.org/docs/platforms/start is little endian more.

@mutexstream
Copy link

Was any decision made regarding this issue?

@lePereT
Copy link

lePereT commented Feb 17, 2023

We (Jangala - a charity that makes internet access systems for schools and clinics for marginalised communities around the world) would love to see this added.

We currently use Lua for our codebase but are thinking of using TinyGo on our MCUs and would love to use it on our Arm64 and MIPS based boards that are running OpenWrt/Linux. The Ath79 target (a hugely popular router and AP chipset family) is big endian.

If this became available it could be hugely popular amongst the OpenWrt community (who currently don't see Go as a viable option). For example, the Mender IoT remote package that @mutexstream references generates a 2MB+ binary which is prohibitive on this kind of target.

@lePereT
Copy link

lePereT commented Feb 18, 2023

Wasm seems interesting but by necessity the code we write interacts with system libraries and the kernel directly, which I guess (not knowing a huge amount about it) might be more difficult with Wasm

@aykevl
Copy link
Member

aykevl commented Feb 18, 2023

I can look into adding support for MIPS. But again: which variant would be preferred or would actually be used in practice? There are four to pick from for initial support. "MIPS" is really more like 4 different architectures under a single name. (Note: big endian is probably going to be more difficult than little endian).

@lePereT
Copy link

lePereT commented Feb 19, 2023

Just looking at the number of end user devices that would be hit, I'd probably suggest the following order of priority:

  1. mipseb (32 bit big endian)
  2. mipsel (32 bit little endian)

The rationale for this is that just the ath79 family alone represents probably hundreds of millions of target devices worldwide

@aykevl
Copy link
Member

aykevl commented Feb 19, 2023

I did some experimenting with MIPS support and managed to get very limited support working:

$ GOARCH=mips tinygo run -gc=leaking ./testdata/alias.go
x
apple
true
false

I have no plans currently to continue working on this, but if there's anybody interested feel free to complete support for MIPS. The branch is here: dev...mips

@aykevl
Copy link
Member

aykevl commented Jul 29, 2024

Does TinyGo use the -e MIPS=softfloat option I used in de docker command or is it ignored?

Not yet, I'm working on it.

@b0ch3nski
Copy link

My router runs on MediaTek MT7621AT SoC and "big Go" compiles perfectly fine for it using GOARCH=mipsle flag.

I can confirm that current dev branch of TinyGo successfully builds the binary that works on the above HW. Great job @aykevl !

The super basic test - create main.go:

package main

func main() {
	println("hello world")
}

Build with Docker:

$ docker run --rm --name "tinygo-build" -v "$(pwd):/src" -w "/src" -e GOARCH=mipsle -e GOOS=linux tinygo/tinygo-dev:latest tinygo build -no-debug -o test-mipsle main.go
...
$ file test-mipsle
test-mipsle: ELF 32-bit LSB executable, MIPS, MIPS32 rel2 version 1 (SYSV), statically linked, not stripped

What's interesting is the file size difference - when I build the amd64 binary exactly the same, mipsle is more than twice the size:

$ du -b test-*
15200	test-amd64
33408	test-mipsle

But after running upx on both, they get quite similar in size:

$ du -b test-*
12624	test-amd64
11388	test-mipsle

@aykevl
Copy link
Member

aykevl commented Jul 29, 2024

@DJAGABATWORK this might fix the issue: #4371

@aykevl
Copy link
Member

aykevl commented Jul 29, 2024

@b0ch3nski I don't know why that is, my guess is that MIPS is an even less efficient instruction set than amd64 (or it hasn't gotten a lot of optimization work).

To reduce binary size, you can also try strip (or llvm-strip) which strips unnecessary stuff like the symbol table. The binary size after stripping would be a more fair comparison.

@DJAGABATWORK
Copy link

DJAGABATWORK commented Jul 30, 2024

@b0ch3nski 's Docker example got me on the right track. Thank you.
I entered:

docker run --rm --name "tinygo-build" -v "$(pwd):/src" -w "/src" -e GOARCH=mips -e GOOS=linux -e GOMIPS=softfloat tinygo/tinygo-dev:latest tinygo build -no-debug -o test-mips main.go

Running from the same directory were the main.go file is.

contents of main.go

package main

func main() {

        println("Hello from here")
}
file test-mips
test-mips: ELF 32-bit MSB executable, MIPS, MIPS32 rel2 version 1 (SYSV), statically linked, not stripped

Execution results:

root@Teltonika-TRB255:/installs# ./test-mips
Hello from here

So it is working with simple Hello World example on big endian mips. too! Good job @aykevl
In the coming weeks I will increase complexity to see if I can get it to crash again, like the serial example does.
Btw @aykevl: I tested the serial binary again after your change mentioned in #4371. It unfortunately still crashes with Illegal Instruction message, but without further details this info is of little use. Slowly increasing complexity from the hello world example is the way to (tiny)go IMO.

@aykevl
Copy link
Member

aykevl commented Jul 30, 2024

@DJAGABATWORK

I tested the serial binary again after your change mentioned in #4371.

How did you test it? It's not merged, so if you used Docker you weren't using that change.
It would be really useful to know the faulting instruction. Does it print an address somewhere? If you give me the fault address and the binary I can probably figure out what went wrong.

(Also I formatted your comment a little, I hope you don't mind).

@aykevl
Copy link
Member

aykevl commented Jul 30, 2024

So I found that Go normally uses MIPS32r1 as the minimum requirement, while TinyGo uses MIPS32r2. That could be a reason why it crashes.
@DJAGABATWORK do you know which specific CPU core this is? All I can see on the Qualcomm website is "Clock Speed: Up to 650 MHz" which is useless information for this purpose.

@b0ch3nski
Copy link

Teltonika TRB-255

@aykevl @DJAGABATWORK HW seems to be MIPS32_24Kc (mips32r2): https://openwrt.org/docs/techref/instructionset/mips_24kc

While my HW is MIPS32_1004Kc: https://s3-eu-west-1.amazonaws.com/downloads-mips/documents/MIPS32_1004K_1211.pdf
Looks like this exact SoC doesn't have FPU but binaries build with both big Go and latest TinyGo dev runs just fine without GOMIPS=softfloat 🤔

@aykevl
Copy link
Member

aykevl commented Jul 31, 2024

Looks like this exact SoC doesn't have FPU but binaries build with both big Go and latest TinyGo dev runs just fine without GOMIPS=softfloat 🤔

You probably just got lucky. A hello world example is unlikely to use FPU instructions, and appears to also have avoided the new instructions introduced in mips32r2.

After the softfloat PR is merged, I intend to make a new PR that switches to mips32r1 (aka mips32).

@b0ch3nski
Copy link

After the softfloat PR is merged, I intend to make a new PR that switches to mips32r1 (aka mips32).

Wouldn't it make sense to also have this configurable somehow? I realize that this potentially can break a lot of stuff but "I want to shoot myself in the foot" kind of switches are already present in TinyGo 😄

@aykevl
Copy link
Member

aykevl commented Jul 31, 2024

@b0ch3nski there's an accepted proposal for that: golang/go#60072
I think we should default to mips32r1 (or even MIPS III?) for now because it's a safe default, and maybe implement this proposal in the future if there's interest. Later MIPS variants are mainly useful for improved performance, but MIPS cores are generally backwards compatible.

@DJAGABATWORK
Copy link

serial.zip

@aykevl: I have attached the binary in question.

How did you test it? It's not merged, so if you used Docker you weren't using that change.

Sorry. Somehow I assumed it was already merged.

@aykevl
Copy link
Member

aykevl commented Aug 2, 2024

@DJAGABATWORK I found a way to detect invalid instructions using -cpu 4Kc to QEMU.

It looks like the sdc1 is present when building examples/serial with the dev branch, but with the mips-softfloat branch (#4371) it is avoided when you use GOMIPS=softfloat.
There are still some mips32r2 instructions remaining, I'll fix that in a future PR (after #4371 is merged).

@DJAGABATWORK
Copy link

It looks like the sdc1 is present when building examples/serial with the dev branch, but with the mips-softfloat branch (#4371) it is avoided when you use GOMIPS=softfloat.
There are still some mips32r2 instructions remaining, I'll fix that in a future PR (after #4371 is merged).

@aykevl I noticed that the #4371 got merged. Therefore I tried the docker version again with softfloat support: The following occurred:

docker run --rm --name "tinygo-build" -v "$(pwd):/src" -w "/src" -e GOARCH=mips -e GOOS=linux -e GOMIPS=softfloat tinygo/tinygo-dev:latest tinygo build -no-debug -o test-mips main.go failed to run linker: signal: segmentation fault.
Any ideas why this command fails?

@DJAGABATWORK
Copy link

docker run --rm --name "tinygo-build" -v "$(pwd):/src" -w "/src" -e GOARCH=mips -e GOOS=linux -e GOMIPS=softfloat tinygo/tinygo-dev:latest tinygo build -no-debug -o test-mips main.go failed to run linker: signal: segmentation fault.

Without the softfloat option the command succeeds.

@aykevl
Copy link
Member

aykevl commented Aug 14, 2024

Oh great, that looks like a LLVM bug.

Can you provide the source, so that I can reproduce this issue locally?

@DJAGABATWORK
Copy link

DJAGABATWORK commented Aug 14, 2024

Oh great, that looks like a LLVM bug.

Can you provide the source, so that I can reproduce this issue locally?

@aykevl Sure:


import (
        "fmt"
        
)

func main() {
        
        fmt.Print("Hello")

}

A simple Hello.

@nonibytes
Copy link

This is great progress! Thank you for working on this long awaited feature.

Does the garbage collection work properly in this setup?

@deadprogram
Copy link
Member

Does the garbage collection work properly in this setup?

Yes, it appears it should support everything except 64-bit atomics.

@DJAGABATWORK
Copy link

DJAGABATWORK commented Aug 19, 2024

Oh great, that looks like a LLVM bug.

Can you provide the source, so that I can reproduce this issue locally?

I was wondering, With the supplied contents of main.go as the source, were you able to reproduce it locally @aykevl?

@aykevl
Copy link
Member

aykevl commented Aug 21, 2024

@DJAGABATWORK yes I can reproduce the issue! This definitely looks like a LLVM bug.

@aykevl
Copy link
Member

aykevl commented Aug 21, 2024

This should fix the issue: #4425
Whether it's a LLVM bug is debatable, the same issue isn't present on ARM. But the PR fixes the crash.

@DJAGABATWORK
Copy link

This should fix the issue: #4425 Whether it's a LLVM bug is debatable, the same issue isn't present on ARM. But the PR fixes the crash.

@aykevl: I've just tried it again after noticing #4425 got pushed to the dev branch.
I think there is a new bug there because it now always builds a little endian binary, even with GOARCH=mips.

test-mips: ELF 32-bit LSB executable, MIPS, MIPS32 rel2 version 1 (SYSV), statically linked, not stripped

The result on the Teltonika trying to execute the binary is the following:

./test-mips: line 1: syntax error: unexpected "("

@aykevl
Copy link
Member

aykevl commented Aug 22, 2024

@DJAGABATWORK well that's awkward. See: #4428

@aykevl
Copy link
Member

aykevl commented Aug 22, 2024

And to avoid MIPS32r2 instructions: #4429

@DJAGABATWORK
Copy link

@DJAGABATWORK well that's awkward. See: #4428

Hmm. Well at least it works now with a simple example built with softfloat enabled running on a TRB-255. Good job!
When using tinyGo for mips BE seams doable for us, chances are we are going to replace the current application which is written in "Big Go" with the tinyGo version to save some room for future extensions. Talking about 222 locations in the field.
For now, I will closely follow this development and will do some tests where I can. Next one is #4429 when it has reached the dev branch.

@aykevl
Copy link
Member

aykevl commented Aug 23, 2024

TRB-255

That one has a MIPS32r2 chip according to the product page (24Kc). So #4429 should not be needed.

However there is also #4430 (and other to-be-written PRs) to fully support big-endian systems. Right now there are a few bugs for these systems, as MIPS is the first chip for TinyGo that's big endian and the compiler/stdlib still assumes little endian in a few places.

@aykevl
Copy link
Member

aykevl commented Aug 23, 2024

Fixed another MIPS big-endian issue (the reflect package) so now it's almost on par with MIPS little-endian: #4430
The only remaining issue (that I'm aware of) is CGo support. Bitfields don't work yet on big-endian systems.

Oh and I've seen an issue with unaligned loads/stores in the reflect package that I haven't investigated yet, a workaround is GOMIPS=softfloat if you hit this issue. The symptom is a SIGBUS, at least inside QEMU.

@deadprogram
Copy link
Member

Closing since some MIPS support is now in TinyGo. Let's open new specific issues as needed. Thank you!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
Development

No branches or pull requests