目录
1.寄存器宏 - FIELD()
2.寄存器操作 - FIELD_SETTER() & FIELD_GETTER()
3.指令辅助方法 - HELPER()
3.1.辅助宏
3.2.指令示例
3.3.函数调用
4.PSW 寄存器读写 - psw_read() & psw_write()
1.寄存器宏 - FIELD()
FIELD() 宏定义寄存器 MASK
// include/hw/registerfields.h
#define FIELD(reg, field, shift, length) \enum { R_ ## reg ## _ ## field ## _SHIFT = (shift)}; \enum { R_ ## reg ## _ ## field ## _LENGTH = (length)}; \enum { R_ ## reg ## _ ## field ## _MASK = \MAKE_64BIT_MASK(shift, length)};
参数含义如下
-
reg:寄存器名称;
-
field:对应的 FIELD,如 ICR 寄存器的 0~7 位为 CCPN;
-
shift:该 FIELD 在寄存器中的起始比特位,如 PIPN 从 ICR 的第 16 位开始;
-
length:该 FIELD 的长度,如 CCPN 长度的为 8,在 32 位的 ICR 寄存器中占 8 位;
以 TriCore ICR 寄存器为例
// target/tricore/cpu.h
FIELD(ICR, PIPN, 16, 8)
使用 FIELD() 宏定义寄存器,相当于实现如下的操作:
enum {
R_ICR_PIPN_SHIFT = (16)
};enum {
R_ICR_PIPN_LENGTH = (1)
};enum {
R_ICR_PIPN_MASK = MAKE_64BIT_MASK(shift, length)
};
// PIPN 有效位的 Mask 如下
// 0000 0000 1111 1111
// 0000 0000 0000 0000
对照 TC3XX 手册,这些 FILED() 宏实现寄存器内部相关位域的定义,其中后缀 _13 表示 P1.3(TC27X 平台)版本,_161 为 P1.6.1 版本(TC37X 平台)
// target/tricore/cpu.h
FIELD(ICR, IE_161, 15, 1) // TC3XX,P1.6.1版本
FIELD(ICR, IE_13, 8, 1) // TC2XX,P1.3版本
FIELD(ICR, PIPN, 16, 8)
FIELD(ICR, CCPN, 0, 8)
2.寄存器操作 - FIELD_SETTER() & FIELD_GETTER()
每个寄存器都定义了对应的 HELPER() 函数,实现对寄存器相关操作,如 get()、set() 等
// target/tricore/cpu.h
FIELD(ICR, IE_161, 15, 1)
FIELD(ICR, IE_13, 8, 1)
FIELD(ICR, PIPN, 16, 8)
FIELD(ICR, CCPN, 0, 8)
uint32_t icr_get_ie(CPUTriCoreState *env);
uint32_t icr_get_ccpn(CPUTriCoreState *env);
void icr_set_ie(CPUTriCoreState *env, uint32_t val);
void icr_set_ccpn(CPUTriCoreState *env, uint32_t val);
使用宏 FIELD_SETTER() 及 FIELD_GETTER() 宏生成具体的函数
// target/tricore/helper.c
FIELD_GETTER_WITH_FEATURE(icr_get_ie, ICR, IE, 161)
FIELD_SETTER_WITH_FEATURE(icr_set_ie, ICR, IE, 161)
FIELD_GETTER(icr_get_ccpn, ICR, CCPN)
FIELD_SETTER(icr_set_ccpn, ICR, CCPN)
---------------------------------------------------------------// target/tricore/helper.c
#define FIELD_GETTER_WITH_FEATURE(NAME, REG, FIELD, FEATURE) \
uint32_t NAME(CPUTriCoreState *env) \
{ \if (tricore_has_feature(env, TRICORE_FEATURE_##FEATURE)) { \return FIELD_EX32(env->REG, REG, FIELD ## _ ## FEATURE); \} \return FIELD_EX32(env->REG, REG, FIELD ## _13); \
}
...#define FIELD_SETTER(NAME, REG, FIELD) \
void NAME(CPUTriCoreState *env, uint32_t val) \
{ \env->REG = FIELD_DP32(env->REG, REG, FIELD, val); \
}
3.指令辅助方法 - HELPER()
使用 DEF_HELPER() 宏生成对应的指令,如 svucx 指令、call 指令等
// target/tricore/helper.h
DEF_HELPER_2(call, void, env, i32)
...
DEF_HELPER_1(rslcx, void, env)
HELPER 宏后面的数字表示参数个数,具体的定义如下
// include/exec/helper-head.h
#define DEF_HELPER_0(name, ret) \DEF_HELPER_FLAGS_0(name, 0, ret)
...
#define DEF_HELPER_7(name, ret, t1, t2, t3, t4, t5, t6, t7) \DEF_HELPER_FLAGS_7(name, 0, ret, t1, t2, t3, t4, t5, t6, t7)
DEF_HELPER_FLAGS() 在 helper-info.c.inc、helper-proto.h.inc、henler-gen.h.inc 中均有定义,根据文件包含哪个 .inc 调用对应的宏,例如,在 TriCore 的 translate.c 文件中,将 helper.h 定义为 HELPER_H 宏,从而包含该文件中相关 HELPER 函数的定义,在 helper-info.c.inc 中实现相关宏定义后,将 helper.h 头文件中定义的 DEF_HELPER_x() 展开
// target/tricore/translate.c
#include "exec/helper-proto.h"
#include "exec/helper-gen.h"
...
#define HELPER_H "helper.h"
#include "exec/helper-info.c.inc"
#undef HELPER_H
-----------------------------------------------------// include/exec/helper-info.c.inc
#define DEF_HELPER_FLAGS_7(NAME, FLAGS, RET, T1, T2, T3, T4, T5, T6, T7)
...
#include HELPER_H
-----------------------------------------------------// target/tricore/helper.h
...
DEF_HELPER_3(add_suov, i32, env, i32, i32)
DEF_HELPER_3(add_h_ssov, i32, env, i32, i32)
3.1.辅助宏
宏展开时使用的相关辅助宏
// include/exec/helper-head.h
#define DEF_HELPER_3(name, ret, t1, t2, t3) \DEF_HELPER_FLAGS_3(name, 0, ret, t1, t2, t3) // 注意参数顺序改变
----------------------------------------------------------------------------// include/qemu/compiler.h
#define xglue(x, y) x ## y
#define glue(x, y) xglue(x, y)
----------------------------------------------------------------------------// include/exec/helper-head.h
#define HELPER(name) glue(helper_, name) // helper_absdif_b
----------------------------------------------------------------------------// include/exec/helper-info.c.inc
#define str(s) #s // "absdif_b"
----------------------------------------------------------------------------// include/exec/helper-head.h
#define dh_alias_i32 i32
...
#define dh_alias(t) glue(dh_alias_, t) // dh_alias_i32 --> i32
...
#define dh_callflag_i32 0
...
#define dh_callflag(t) glue(dh_callflag_, dh_alias(t)) // dh_callflag_i32 --> 0
...
#define dh_typecode_i32 2
...
#define dh_typecode_ptr 6
...
#define dh_typecode_env dh_typecode_ptr
#define dh_typecode(t) dh_typecode_##t
...
#define dh_typemask(t, n) (dh_typecode(t) << (n * 3))
3.2.指令示例
以 DEF_HELPER_3(absdif_b, i32, env, i32, i32) 及其对应生成的 gen_helper_absdif_b() 为例,首先是生成对应的 helper_info_xxx() 结构体
// target/tricore/helper.h
DEF_HELPER_3(absdif_b, i32, env, i32, i32)
// 对应:DEF_HELPER_FLAGS_3(absdif_b, 0, i32, env, i32, i32)
----------------------------------------------------------------------------// include/exec/helper-info.c.inc
#define DEF_HELPER_FLAGS_3(NAME, FLAGS, RET, T1, T2, T3) \TCGHelperInfo glue(helper_info_, NAME) = { \.func = HELPER(NAME), .name = str(NAME), \.flags = FLAGS | dh_callflag(RET), \.typemask = dh_typemask(RET, 0) | dh_typemask(T1, 1) \| dh_typemask(T2, 2) | dh_typemask(T3, 3) \};
// dh_typemask(RET, 0) --> dh_typemask(i32, 0) --> (dh_typecode(i32) << (0 * 3))
// --> (dh_typecode_i32 << 0) --> 2 << 0 --> 0000 0000 0010// dh_typemask(T1, 1) --> dh_typemask(env, 1) --> (dh_typecode(env) << (1 * 3))
// --> (dh_typecode_ptr << 3) --> 6 << 3 --> 0000 0011 0000// dh_typemask(T2, 2) --> ... --> 2 << 6 --> 0000 1000 0000
// dh_typemask(T3, 3) --> ... --> 2 << 9 --> 0100 0000 0000
----------------------------------------------------------------------------// 展开结果
TCGHelperInfo helper_info_absdif_b = {.func = helper_absdif_b,.name = "absdif_b",.flags = 0,.typemask = 0100 1011 0010
};
继续解析宏,生成 gen_helper_xxx() 函数
// target/tricore/helper.h
DEF_HELPER_3(absdif_b, i32, env, i32, i32)
// 对应:DEF_HELPER_FLAGS_3(absdif_b, 0, i32, env, i32, i32)
----------------------------------------------------------------------------// include/exec/helper-gen.h.inc
#define DEF_HELPER_FLAGS_3(name, flags, ret, t1, t2, t3) \
extern TCGHelperInfo glue(helper_info_, name); \
static inline void glue(gen_helper_, name)(dh_retvar_decl(ret) \dh_arg_decl(t1, 1), dh_arg_decl(t2, 2), dh_arg_decl(t3, 3)) \
{ \tcg_gen_call3(&glue(helper_info_, name), dh_retvar(ret), \dh_arg(t1, 1), dh_arg(t2, 2), dh_arg(t3, 3)); \
}
// dh_retvar_decl(ret) --> dh_retvar_decl_i32 --> TCGv_i32 retval,
// dh_arg_decl(t1, 1) --> TCGv_ptr arg1
// dh_arg_decl(t2, 2) --> TCGv_i32 arg2
// dh_arg_decl(t3, 3) --> TCGv_i32 arg3
// &glue(helper_info_, name) --> &helper_info_absdif_b
// dh_retvar(ret) --> --> dh_retvar_i32 --> tcgv_i32_temp(retval)
// dh_arg(t1, 1) --> tcgv_ptr_temp(arg1)
// dh_arg(t2, 2) --> tcgv_i32_temp(arg2)
// dh_arg(t3, 3) --> tcgv_i32_temp(arg3)
----------------------------------------------------------------------------// 展开结果
extern TCGHelperInfo helper_info_absdif_b;
static inline void gen_helper_absdif_b(TCGv_i32 retval, TCGv_ptr arg1, TCGv_i32 arg2, TCGv_i32 arg3)
{tcg_gen_call3(&helper_info_absdif_b, tcgv_i32_temp(retval), tcgv_ptr_temp(arg1), tcgv_i32_temp(arg2), tcgv_i32_temp(arg3));
}
3.3.函数调用
gen_helper_xxx() 具体对应的是 helper_xxx()
// target/tricore/translate.c
/* RR format */
static void decode_rr_accumulator(DisasContext *ctx)
{...switch (op2) {...case OPC2_32_RR_ABSDIF_B:gen_helper_absdif_b(cpu_gpr_d[r3], tcg_env, cpu_gpr_d[r1],cpu_gpr_d[r2]);
----------------------------------------------------------------------------// target/tricore/op_helper.c
uint32_t helper_absdif_b(CPUTriCoreState *env, target_ulong r1, target_ulong r2)
{int32_t b, i;int32_t extr_r2;int32_t ovf = 0;int32_t avf = 0;int32_t ret = 0;for (i = 0; i < 4; i++) {extr_r2 = sextract32(r2, i * 8, 8);b = sextract32(r1, i * 8, 8);b = (b > extr_r2) ? (b - extr_r2) : (extr_r2 - b);ovf |= (b > 0x7F) || (b < -0x80);avf |= b ^ b * 2u;ret |= (b & 0xff) << (i * 8);}env->PSW_USB_V = ovf << 31;env->PSW_USB_SV |= env->PSW_USB_V;env->PSW_USB_AV = avf << 24;env->PSW_USB_SAV |= env->PSW_USB_AV;return ret;
}
4.PSW 寄存器读写 - psw_read() & psw_write()
用于读取和修改 TriCore 的 PSW 寄存器
// target/tricore/helper.c
uint32_t psw_read(CPUTriCoreState *env)
{/* clear all USB bits */env->PSW &= 0x7ffffff;/* now set them from the cache */env->PSW |= ((env->PSW_USB_C != 0) << 31);env->PSW |= ((env->PSW_USB_V & (1 << 31)) >> 1);env->PSW |= ((env->PSW_USB_SV & (1 << 31)) >> 2);env->PSW |= ((env->PSW_USB_AV & (1 << 31)) >> 3);env->PSW |= ((env->PSW_USB_SAV & (1 << 31)) >> 4);return env->PSW;
}
----------------------------------------------------------------------------// target/tricore/helper.c
void psw_write(CPUTriCoreState *env, uint32_t val)
{env->PSW_USB_C = (val & MASK_USB_C);env->PSW_USB_V = (val & MASK_USB_V) << 1;env->PSW_USB_SV = (val & MASK_USB_SV) << 2;env->PSW_USB_AV = (val & MASK_USB_AV) << 3;env->PSW_USB_SAV = (val & MASK_USB_SAV) << 4;env->PSW = val;fpu_set_state(env);
}