在 PlayStation 2 上的 Golang

这是一篇关于在 PlayStation 2(PS2)上运行 Go 代码的博客文章,主要内容如下:

  • 挑战:Go 默认只支持少数平台,不包括 PS2。TinyGo 是用于小设备的 Go 编译器,但它依赖的 LLVM 19 不直接支持 PS2 的 Emotion Engine(R5900 CPU)。此外,作者对 PS2 的工作原理知之甚少。
  • ps2dev SDK 及其 quirks:ps2dev 是一个用于为 PS2 开发代码的 SDK,提供了许多库。但它的库编译为 MIPS-III N32 标准,与 Go 生成的代码目标不一致,导致一些问题。作者尝试生成mipsel代码并使用 N32 ABI 来解决这些问题。
  • Getting TinyGo to generate some code:为了让 TinyGo 知道 PS2 目标,需要一个ps2.json文件,定义了一系列参数,如llvm-targetcpu等。还需要一个裸金属配置文件baremetal_ps2.go和一个运行时定义文件runtime_ps2.go,以及一个中断定义文件interrupt_ps2.go
  • Calling Go functions from C:通过将 Go 函数导出为 C 函数,可以在 C 代码中调用 Go 函数。作者展示了一个简单的示例,包括 Go 代码和 C 代码的加载器,通过链接生成可执行文件并在 PCSX2 模拟器中运行成功。
  • Switching to Go’s main:让 Go 应用程序可以独立运行,而不需要 C 加载器。需要在runtime_ps2.go中暴露main函数,并进行一些内存管理的操作。作者还展示了一个在 Go 中编写的简单调试函数,并成功在模拟器中运行。
  • The DDIVU problem:在测试中发现fmt.Sprintf函数在 PS2 上工作不正常,经过深入研究,发现是 TinyGo 生成的 LLVM IR 代码中使用了DDIVU指令,而 PS2 不支持该指令。作者通过在 TinyGo 的编译器中添加__udivdi3函数来解决这个问题,从而使 64 位整数除法能够正确执行。
  • What now?:还有很多工作要做,如目标特定的系统调用、内联汇编和中断支持、浮点数支持、新的 LLVM MIPS CPU 等。目前,人们可以使用 Go 调用 ps2dev 的库并进行一些实验。

总的来说,作者通过一系列的努力,在 PS2 上实现了运行 Go 代码的初步尝试,并解决了一些遇到的问题,但仍有很多工作需要进一步完善和扩展。

阅读 6
0 条评论