QEMU 用户模式(User Mode)流程及源码分析 (三)
TCG中间码生成完毕后,由tcg_gen_code函数负责将 TCG 中间码翻译为 HOST 平台代码,这里以 GUEST 端为 x86_64, HOST 端为 ARM64 为例。
tcg_gen_code
tcg_gen_code的实现位于tcg/tcg.c文件内,总共有2个参数,类型分别是TCGContext和TranslationBlock。其中TranslationBlock类型参数tb主要是用来表示翻译的代码存储的位置,该位置是tb->tc.ptr,之后会将其值赋给TCGContext类型参数s的成员变量code_buf保存,参数tb在翻译过程中的使命就结束了,TCGContext类型参数s贯穿整个翻译流程。 TCGContext内存储TCG中间码,参数s内的ops即为存储的每条TCG中间码,通过遍历每条中间码,并根据HOST端类型翻译成本机指令,并写入到code_buf内。
中间码翻译示例
GUEST端为x86_64时,存储CPU状态的结构体类型为CPUX86State,在翻译的HOST代码中,存储CPU状态的结构体指针地址值会存入指定寄存器。该寄存器由HOST端决定,例如,当HOST端为x86_64时,该寄存器为rbx;当HOST端为ARM64时,该寄存器为x19。以此来建立GUEST端和HOST端寄存器的映射。 例如,GUEST端为x86_64时,eip寄存器对应的eip成员变量在CPUX86State结构体的偏移为sizeof(target_ulong[CPU_NB_REGS])=108,那么当HOST端为ARM64时,eip被翻译为[x19, #108];当HOST为x86_64时,eip被翻译为108(%rbx)。
为了优化翻译的代码,避免不必要的内存读取,每个代码块内,当且仅当GUEST寄存器在首次访问和被同步时,才按照上述方式翻译,并将值从内存中加载进HOST端某个空闲寄存器,并建立该GUEST端寄存器与HOST端某个空闲寄存器的映射。例如,如下代码中,rcx在CPUX86State的偏移为8,那么GUEST端代码
被翻译到ARM64的HOST端时,可能为
对于上一章提到的tcg中间码
在HOST端为ARM64时,翻译结果为

