一直以来,软件生态上的不足是国产CPU和国产操作系统推广的最大障碍。各种操作系统和应用程序都与指令集相关,所以x86架构(指令集)的CPU就不能直接运行ARM架构(指令集)的应用程序,反之亦然。因此诞生了各种各样的二进制(指令)翻译技术,用于跨架构模拟运行其它平台的操作系统和应用程序。由于构建自主软件生态需要较长的时间,因而在过渡时期,国产CPU和国产操作系统可以用二进制翻译的方式,运行X86版本Windows平台的应用软件。本次龙芯就通过二进制翻译的方式实现了在龙芯+UOS操作系统上运行X86版windows微信和PS等软件。
以软件方式进行二进制(指令)翻译必须存在一个宿主系统,模拟器程序在宿主系统上运行。比如各种游戏模拟器,用来在电脑上玩红白机游戏、街机游戏、PS游戏等,以纯软件的方式构建了一个虚拟的主机环境,让那些游戏程序成为缸中之脑,游戏程序执行的所有指令、请求的所有资源都是由翻译软件模拟出来的,但它以为自己是在真正的主机中运行。模拟通用计算机的CPU和相关硬件环境要比模拟游戏主机复杂得多。这方面的代表软件,有开源的可虚拟多种架构的qemu、苹果的rosetta 2、以及微软Windows11在arm上模拟x86和在x86上模拟arm的技术等等。其中qemu可以在多种架构(指令集)之间相互转换,不但只支持动态翻译,而且性能最低,平均运行效率仅为原生性能的5%左右。苹果和微软都是一对一的专用翻译,且与操作系统深度结合,效率较高。二进制(指令)翻译技术可以分为软件翻译、硬件翻译、软硬结合的翻译这三大类。
硬件翻译以Transmeta CPU为代表,它的CPU本身是一种“超长指令字”架构,但在指令译码的阶段,接受的是x86指令,然后把x86指令转换为它自己的指令来运行。这种方式使它的CPU看起来就是一块x86架构的CPU,并且不需要对电脑中的其它硬件进行模拟,各种支持x86指令集的操作系统和应用程序都可以在使用Transmeta CPU的电脑上直接安装运行。Intel/AMD现在的CPU其实也是硬件翻译技术的代表,它们内部是执行的“微码(类似于精简指令集)”,而对于的表现则依然是x86架构的处理器。
龙芯的LoongArch架构(指令集)则代表了第三个分类,即软件和硬件结合的二进制翻译方式。这种方式既有软件翻译的灵活性,又能接近或达到硬件翻译的效率,兼具二者的优点。龙芯的二进制翻译本质上也是软件翻译,但是对软件翻译中比较耗时的处理提供了专门的硬件指令来加速翻译过程,因此称它为软硬结合的二进制翻译技术。龙芯之所以不使用纯硬件的翻译方式,是因为我们必须建立自主的软件生态体系。如果像Transmeta那样对外表现为x86的CPU,那么它能直接运行的就只有基于x86的操作系统和应用程序,生存状况高度依赖于Intel和微软的态度,因此它虽然在Intel的诉讼中获胜,但却在Intel对市场的操作下惨然离场。
龙芯的LoongArch架构(指令集)本身是一种独立的,完善的指令系统,可以建立独立于x86/ARM之外的软件生态体系。龙芯的二进制翻译技术主要是在LoongArch原生软件生态建设的初期,用于补充原生软件的不足,LoongArch架构和龙芯CPU的生存不依赖于Intel/ARM/MS/Google等主导的软件生态。
二进制翻译技术具有单方面的决定权,任何公司都没有理由阻止任何软件以二进制翻译的方式在某种原生不支持的架构上运行。即使软件开发商以检测CPU型号等技术手段阻止运行,那么以软件为主体的二进制翻译技术也能轻松解决这个问题,而固化在CPU硬件中的各种信息和特征则不可能像软件那样在线升级。以软件翻译为主体的二进制翻译,甚至可以针对特定程序把自己模拟成特定的CPU型号。
即使要翻译的目标架构频繁升级指令集版本,增加新的指令,不断推陈出新,对于龙芯来说,要模拟最新的CPU和指令集,也只是更新一下软件的事儿。而那些需要架构授权的CPU产品,如果没有购买到新版本的架构授权,那就无论如何发布多少个新款CPU产品,都不可能兼容新版架构的新指令。
基于龙芯LoongArch架构(指令集)的CPU,在运行原生的LoongArch指令集的程序时,不需要二进制翻译,可以直接运行。
在运行基于其它架构(指令集)的Linux程序时,由龙芯的二进制翻译模块对指令进行转译。程序对Linux的API调用,可以直接由操作系统本身提供支持。
在运行Windows(x86)的程序时,由于Linux系统本身不能提供Windows系统的API,因此需要使用Wine来提供对Windows API的支持。Wine是给Windows(x86)程序提供虚拟的API接口,而不负责对指令的转译,因此只用wine并不能在非x86的CPU运行Windows程序。在x86的应用程序中,不但程序自身逻辑以及第三方库的二进制代码都是x86指令,而且用于调用Windows API的二进制代码也是x86指令,如果没有二进制翻译,在LoongArch上Windows程序甚至连程序入口的代码都不能执行,也无法调用Window API,程序自身的代码和第三方库就更不可能运行了。
操作系统API(应用程序编程接口)是由操作系统提供给应用程序的接口,在Linux上运行Windows程序时,假如调用读取文件数据的API,就可以由Wine给应用程序提供这个接口,但接口内部不再是Windows的代码,而是由Wine去调用Linux的相关接口来实现相同的功能,这就是对API的模拟。在应用程序读取到数据之后做的操作,就不在Wine的管辖范围内了。比如程序取得数据后可能加密解密、可能作为图像数据计算对比度、可能作为音频数据计算特殊音效……这些操作可能是由程序自身代码来完成,也可能是调用其它的库文件的接口来实现。这些在Wine支持范围之外的代码,在x86架构(指令集)的CPU上是由CPU直接执行,在LoongArch架构(指令集)的CPU上,就只能由二进制翻译模块转译为LoongArch的指令来执行。
操作系统和应用程序对CPU指令的使用,是属于ABI(应用程序二进制接口)的一部分,ABI的层级很低,是二进制代码的规范。在基于LoongArch架构的CPU上运行x86程序时,就是由二进制翻译模块来处理对指令的转译,也就是对x86的ABI规范的模拟。不管是Linux还是Windows的应用程序,只要它不是LoongArch原生指令集的,最终都需要经过二进制翻译才能在龙芯的CPU上运行。
龙芯的二进制翻译模块当前和qemu一样也是只支持动态翻译,但效率比原生的qemu高出一个数量级。将来会支持动、静态结合的翻译模式,也就是程序运行时的动态翻译结果可以保留下来,下次运行相同的程序就直接使用翻译的结果,仅对程序运行时修改自身代码等行为需要动态翻译。这样可以降低翻译的CPU消耗,翻译运行的效率可以大幅度提高,预计运行x86程序可以达到80%的原生效率。这里的80%是指平均80%,而不像某些纯软件的翻译方案仅对特定类型程序翻译效率较高,就笼统地宣传“高效率”。
最简单的方式,是在使用3A5000的电脑上安装统信的UOS系统,然后等着UOS系统的应用商店中提供了什么Windows软件,就安装什么软件,可以无障碍,无门槛,无后顾之忧……可是Windows的软件千奇百怪,UOS的应用商店不可能提供所有的Windows软件,那么我们就需要动动小手,自己解决自己的需求。
目前只有UOS for 3A5000(体验版)系统中集成了龙芯的二进制翻译模块,我下面就以UOS为例说明一下如何在龙芯3A5000上运行“任何”的Windows软件,“任何”是指可以尝试任何软件,但不能保证所有软件都能正常运行。
UOS中已经集成了龙芯二进制翻译模块,但要运行Windows软件仍然需要一个Wine环境。UOS本身有多个版本的Wine,有经过深度/统信改良了效率和兼容性的deepin-wine,也有原生的版本,我们要使用deepin-wine。最简单的方式是从UOS应用商店中安装一个由Wine支持的软件,环境就自动配置好了。如果使用Loongnix或其它的系统,就需要手工完成这个过程,可能还需要从UOS复制一些文件和配置,比较麻烦。建议安装的软件是PhotoShop,因为PhotoShop是一个很大很复杂的软件,能够让PhotoShop正常运行的环境,就能让大多数软件正常运行。