在qemu的softmmu代码中,有很多函数它们的功能是相似的,只是处理的数据类型不同,这里我姑且称之为“同构”函数。如果为它们分别编写函数体,代码量及维护工作量会增加数倍,以softmmu_defs.h文件中声明的函数为例,共声明了16个函数
//softmmu_defs.h uint8_t REGPARM __ldb_mmu(target_ulong addr, int mmu_idx); void REGPARM __stb_mmu(target_ulong addr, uint8_t val, int mmu_idx); uint16_t REGPARM __ldw_mmu(target_ulong addr, int mmu_idx); void REGPARM __stw_mmu(target_ulong addr, uint16_t val, int mmu_idx); uint32_t REGPARM __ldl_mmu(target_ulong addr, int mmu_idx); void REGPARM __stl_mmu(target_ulong addr, uint32_t val, int mmu_idx); uint64_t REGPARM __ldq_mmu(target_ulong addr, int mmu_idx); void REGPARM __stq_mmu(target_ulong addr, uint64_t val, int mmu_idx); uint8_t REGPARM __ldb_cmmu(target_ulong addr, int mmu_idx); void REGPARM __stb_cmmu(target_ulong addr, uint8_t val, int mmu_idx); uint16_t REGPARM __ldw_cmmu(target_ulong addr, int mmu_idx); void REGPARM __stw_cmmu(target_ulong addr, uint16_t val, int mmu_idx); uint32_t REGPARM __ldl_cmmu(target_ulong addr, int mmu_idx); void REGPARM __stl_cmmu(target_ulong addr, uint32_t val, int mmu_idx); uint64_t REGPARM __ldq_cmmu(target_ulong addr, int mmu_idx); void REGPARM __stq_cmmu(target_ulong addr, uint64_t val, int mmu_idx);而定义这些函数仅用了两个函数体。如何实现的呢?就是使用宏glue:
//softmmu_template.h #define DATA_SIZE (1 << SHIFT) #if DATA_SIZE == 8 #define SUFFIX q #define USUFFIX q #define DATA_TYPE uint64_t #elif DATA_SIZE == 4 #define SUFFIX l #define USUFFIX l #define DATA_TYPE uint32_t #elif DATA_SIZE == 2 #define SUFFIX w #define USUFFIX uw #define DATA_TYPE uint16_t #elif DATA_SIZE == 1 #define SUFFIX b #define USUFFIX ub #define DATA_TYPE uint8_t #else #error unsupported data size #endif DATA_TYPE REGPARM glue(glue(__ld, SUFFIX), MMUSUFFIX)(target_ulong addr, int mmu_idx) { ... } #ifndef SOFTMMU_CODE_ACCESS void REGPARM glue(glue(__st, SUFFIX), MMUSUFFIX)(target_ulong addr, DATA_TYPE val, int mmu_idx) { ... } #endif #undef SHIFT #undef DATA_TYPE #undef SUFFIX #undef USUFFIX
softmmu_template.h仅是头文件,并非函数定义,只有在#include "softmmu_template.h"时才真正定义函数。在exec.c文件中,具有下列语句:
#define MMUSUFFIX _cmmu #define GETPC() NULL #define env cpu_single_env #define SOFTMMU_CODE_ACCESS #define SHIFT 0 #include "softmmu_template.h" #define SHIFT 1 #include "softmmu_template.h" #define SHIFT 2 #include "softmmu_template.h" #define SHIFT 3 #include "softmmu_template.h"我们不难发现,这相当于定义了下列函数:
//op_helper.c #define MMUSUFFIX _mmu #define ALIGNED_ONLY #define SHIFT 0 #include "softmmu_template.h" #define SHIFT 1 #include "softmmu_template.h" #define SHIFT 2 #include "softmmu_template.h" #define SHIFT 3 #include "softmmu_template.h"而这就相当于定义了下列函数: