softmmu同構函數的定義

在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:
#define xglue(x, y) x ## y
#define glue(x, y) xglue(x, y)
分析函數聲明我們不難發現,__ld函數首先分爲兩類,一類是_mmu,另一類是_cmmu,每種類別又分爲4個子類,差別體現在函數返回類型上,函數名稱同時與之對應。
如返回類型是uint8_t時,函數名稱以__ldb開頭,表示字節操作。__st函數也具有相同的特點。所以我們不難理解softmmu_template.h文件中的下列定義:

//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"
我們不難發現,這相當於定義了下列函數:

uint8_t REGPARM __ldb_cmmu(target_ulong addr, int mmu_idx)
{
    ...
}
uint16_t REGPARM __ldw_cmmu(target_ulong addr, int mmu_idx)

{
    ...
}
uint32_t REGPARM __ldl_cmmu(target_ulong addr, int mmu_idx)
{
    ...
}
uint64_t REGPARM __ldq_cmmu(target_ulong addr, int mmu_idx)
{
    ...
}
由於exec.c中定義了宏SOFTMMU_CODE_ACCESS,所以這裏引用softmmu_template.h文件時並未定義__st函數。實際上在0.14.0版本中沒有使用__st*_cmmu函數,所以也沒有定義這些函數。

在op_helper.c文件中,存在下面語句:

//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"
而這就相當於定義了下列函數:
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)
{
    ...
}



發佈了44 篇原創文章 · 獲贊 7 · 訪問量 9萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章