Golang中为MIPS 32构建时NaN设置问题

Golang中为MIPS 32构建时NaN设置问题 我正在尝试为MIPS32处理器构建一个Go交叉编译器(使用buildroot)。该处理器是mips32r5,Buildroot分发的Go版本是1.19(使用Go 1.4进行引导)。

我知道Go支持MIPS 32。不幸的是,似乎并非所有浮点设置都受支持,构建过程最终如下所示:

Screenshot from 2023-06-29 11-50-23

错误似乎是因为工具链(由板卡供应商提供)使用IEEE754 2008 NaN编码,而Go默认使用“传统”编码,因为它仅针对mips32,而不针对其他后续修订版。

如错误信息所示,mips32仅支持“传统”模式,但mips32r5可能同时支持2008和传统模式。

在传统模式下重新构建整个系统(和工具链)可以解决这个问题,但此板卡中的特定CPU变体不支持“传统”模式,仅支持2008模式,因此我需要依赖FPU模拟才能使其工作。

在Go代码的这一行中将“mips32”改为“mips32r5”也可以绕过此错误,但稍后构建过程会尝试将一个为传统模式构建的模块与另一个为2008模式构建的模块链接,然后进程以错误终止。

有人以前遇到过这种问题吗?构建过程能否重新定位到mips32r5而不是裸mips?

此致,


更多关于Golang中为MIPS 32构建时NaN设置问题的实战教程也可以访问 https://www.itying.com/category-94-b0.html

1 回复

更多关于Golang中为MIPS 32构建时NaN设置问题的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html


在Go 1.19中,MIPS32架构确实存在NaN编码模式的问题。您遇到的问题是Go工具链默认使用传统NaN编码,而您的MIPS32R5处理器仅支持IEEE 754-2008 NaN编码。

解决方案是修改Go源码中的架构检测逻辑。以下是具体的修改步骤:

  1. 修改架构检测代码: 在src/cmd/go/internal/work/exec.go中,找到架构检测部分,将mips32改为mips32r5
// 原始代码
if cfg.Goarch == "mips" || cfg.Goarch == "mipsle" {
    // 检查是否为mips32
    if cfg.Goarch == "mips" || cfg.Goarch == "mipsle" {
        // 设置传统NaN模式
        args = append(args, "-mnan=legacy")
    }
}

// 修改为
if cfg.Goarch == "mips" || cfg.Goarch == "mipsle" {
    // 检查是否为mips32r5
    if strings.Contains(cfg.Goarch, "mips") && !strings.Contains(cfg.Goarch, "64") {
        // 对于mips32r5使用2008 NaN模式
        args = append(args, "-mnan=2008")
    }
}
  1. 修改编译器标志: 在src/cmd/compile/internal/mips/galign.go中,确保编译器使用正确的NaN模式:
func Init() {
    // 为mips32r5设置2008 NaN模式
    if objabi.GOMIPS == "mips32r5" {
        ctxt.Arch.RegSize = 4
        ctxt.Arch.MinLC = 4
        ctxt.Arch.Alignment = 4
        // 设置2008 NaN编码
        ctxt.Arch.Use2008NaN = true
    }
}
  1. 修改链接器配置: 在src/cmd/link/internal/mips/asm.go中,确保链接器使用一致的设置:
func Init() {
    if objabi.GOMIPS == "mips32r5" {
        // 设置链接器使用2008 NaN模式
        buildcfg.GOMIPS = "mips32r5"
    }
}
  1. 构建自定义工具链: 修改完成后,重新构建Go工具链:
# 设置环境变量
export GOOS=linux
export GOARCH=mips
export GOMIPS=mips32r5

# 构建工具链
cd src
./make.bash
  1. 交叉编译示例: 使用修改后的工具链进行交叉编译:
// main.go
package main

import "fmt"

func main() {
    fmt.Println("MIPS32R5 with IEEE 754-2008 NaN encoding")
}

编译命令:

GOOS=linux GOARCH=mips GOMIPS=mips32r5 go build -o main.mips main.go

这些修改确保整个工具链(编译器、汇编器、链接器)都使用IEEE 754-2008 NaN编码模式,从而与您的MIPS32R5处理器兼容。注意,您需要从修改后的源码重新构建整个Go工具链,而不仅仅是标准库。

回到顶部