QEMU TCG研究

本文详细探讨了QEMU的动态翻译组件TCG的工作原理,包括如何将目标指令转换为TCG中间码,以及如何将中间码进一步翻译成宿主机指令。重点介绍了CPU初始化、TB(Translation Block)管理和指令翻译思想,阐述了TCG上下文、内存池管理、变量分配等关键概念,并以`cpu_gen_code`和`tcg_gen_code`函数为例,展示了指令翻译的具体流程。
摘要由CSDN通过智能技术生成

TCG

动态翻译的基本思想就是把每一条Target指令切分成为若干条微指令,每条微指令由一段简单的C代码来实现,运行时通过一个动态代码生成器把这些微指令组合成一个函数,最后执行这个函数,就相当于执行了一条Target指令。那么现在的CPU指令这么多,怎么知道要分为哪些微指令呢?其实CPU指令看似名目繁多,异常复杂,实际上多数指令不外乎以下几大类:数据传送、算术运算、逻辑运算、程序控制;例如,数据传送包括:传送指令(如MOV)、堆栈操作(PUSH、POP)等,程序控制包括:函数调用(CALL)、转移指令(JMP)等;
在这里插入图片描述

在这里插入图片描述

上述流程图是从 CPU 初始化到生成 TCG 中间代码的过程,部分代码与 Target 强相关,从如下 References 可以看出
在这里插入图片描述

0x23 指令翻译核心函数 cpu_gen_code

变量 s 作为 TCG 上下文
在这里插入图片描述

TCGContext 的定义(部分代码)

struct TCGContext {
   
    uint8_t *pool_cur, *pool_end;
    TCGPool *pool_first, *pool_current;
    TCGLabel *labels;
    int nb_labels;
    TCGTemp *temps; /* globals first, temps after */
    int nb_globals;
    int nb_temps;
    /* index of free temps, -1 if none */
    int first_free_temp[TCG_TYPE_COUNT * 2]; 

    /* goto_tb support */
    uint8_t *code_buf;
    unsigned long *tb_next;
    uint16_t *tb_next_offset;
    uint16_t *tb_jmp_offset; /* != NULL if USE_DIRECT_JUMP */

    /* liveness analysis */
    uint16_t *op_dead_args; /* for each operation, each bit tells if the
                               corresponding argument is dead */
    
    /* tells in which temporary a given register is. It does not take
       into account fixed registers */
    int reg_to_temp[TCG_TARGET_NB_REGS];
    TCGRegSet reserved_regs;
    tcg_target_long current_frame_offset;
    tcg_target_long frame_start;
    tcg_target_long frame_end;
    int frame_reg;

    uint8_t *code_ptr;
    TCGTemp static_temps[TCG_MAX_TEMPS];

    TCGHelperInfo *helpers;
    int nb_helpers;
    int allocated_helpers;
    int helpers_sorted;
};

在对一个翻译块进行二进制翻译时,TCG 需要维护一些信息完成动态翻译,即 TCGContext,TCG 上下文包含三类信息:内存池、标号和变量1。

  • TCGPool:内存池,用于二进制转换期间的内存管理。为了提高性能,TCG 在初始化期间分配了较大的存储空间(32K)。TCG 需要内存时,直接从中获取,当内存池剩余空间不满足申请需求,再申请新内存。内存池之间通过链表维护。
  • TCG 变量:临时、局部和全局变量。在 TCG 上下文中,所有变量存放在一个静态分配的数组中。不再使用的变量,使用链表链接。先从被释放链表中分配,后从静态数组中分配。
    在这里插入图片描述

目标指令翻译成 TCG 中间码

gen_intermediate_code() 函数定义在不同架构的 target-xxx/translate.c 文件中。该函数将 target 指令翻译成中间码。操作码和操作数分开存储。操作码存放在 gen_opc_buf变量,操作数存放在 gen_opparam_buf变量。翻译过程就是不断向上述两个缓冲区填充操作码和操作数。
将基本块(basic block, tb) 翻译成 TCG 中间代码(intermediate code)。

TCG 中间码翻译成宿主机指令

tcg_gen_code() 函数定义在 tcg.c 文件中。该函数将中间代码翻译成 host code。
将 TCG 中间码翻译成 host 机器码的函数是 tcg_gen_code_common 。主要过程如下

  • 从缓存中找到 TCG 操作码和相应参数;
  • 为输入参数分配 host 平台的寄存器
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值