标签:
Qemu采用TCG(Tiny code generator)翻译引擎,TCG的作用也和一个真正的编译器后端一样,主要负责分析、优化Target代码以及生成Host代码。所谓“微指令”,是qemu用于指令翻译的中间表示,进行指令翻译时,qemu首先将每条target的指令分解为多条类似RISC指令的微指令,这个阶段可以进行一些优化,如微指令的生命周期分析(liveness analysis)等,之后微指令在后端由host机的指令实现。
CPU指令一般都是很规则的,每条指令的长度、操作码、操作数都有固定格式,根据前面就可推导出后面,微指令的设计也采用了类似的规则,每条微指令都有固定的输入、输出与常数操作数(除了call指令有不定数目的输入输出操作数)。另外,与cpu指令对应,微指令也设计了数据传送、算术运算、逻辑运算、程序控制几大类指令。
下面对Qemu提供的微指令类型进行分析归纳:
1. 微指令基本格式
微指令在tcg/tcg-opc.h中定义。定义格式为
DEF(name, oargs,iargs, cargs, flags)
其中name为微指令名,oargs为输出操作数个数,iargs为输入操作数个数,cargs为常数操作数个数,flags表示 为特殊指令的一些标志,如flags取值为TCG_OPF_SIDE_EFFECTS表示该指令会影响内存中内容。
例如,一条add指令微操作定义为:
DEF(add_i32, 1,2, 0, 0)
其含义为:
add_i32 t0, t1, t2 (t0 <- t1 + t2), i32表示target机为32位机。t0为输出操作数,t1、t2为两个输入操作数,没有常数操作数。
2.qemu预定义的微指令
cpu指令对应,微指令也设计了数据传送、算术运算、逻辑运算、程序控制几大类指令。且针对32位和64位的目标机,qemu分别定义了一套微指令,即[opname]_i32、[opname]_i64,由于目前csky的cpu为32位,因此我们先只关注32位的微指令。
1) 数据传送
2) 算术运算
3) 逻辑运算
4) 程序控制
3. 微指令类型归纳
指令名 |
指令格式 |
指令含义 |
/* predefined ops */ |
||
end |
end |
end of tb |
nop |
|
|
nop1 |
|
|
nop2 |
|
|
nop3 |
|
|
nopn |
|
|
discard |
discard t0 |
mark t0 as dead variable |
set_label |
set_label $label |
Define label ‘label‘ at the current program point. |
call |
call <ret><params> ptr |
call function ‘ptr‘ (pointer type) |
jmp |
jmp t0 |
Absolute jump to address t0 (pointer type) |
br |
br $label |
Jump to label. |
mov_i32 |
mov_i32 t0, t1 |
t0 = t1 |
movi_i32 |
mov_i32 t0, $(constant) |
t0 = $(constant) |
setcond_i32 |
setcond_i32 cond, dest, t1, t2 |
dest = (t1 cond t2) |
brcond_i32 |
brcond_i32 cond, t0, t1, label |
Conditional jump if t0 cond t1 is true |
|
||
/* load/store */ |
||
ld8u_i32 |
ld8u_i32 t0, t1, offset |
t0 = read(t1 + offset) Load 8, 16, 32 or 64 bits with or without sign extension from host memory. offset must be a constant. |
ld8s_i32 |
ld8s_i32 t0, t1, offset |
|
ld16u_i32 |
ld16u_i32 t0, t1, offset |
|
ld16s_i32 |
ld16s_i32 t0, t1, offset |
|
ld_i32 |
ld_i32 t0, t1, offset |
|
st8_i32 |
st8_i32 t0, t1, offset |
write(t0, t1 + offset) Write 8, 16, 32 or 64 bits to host memory. |
st16_i32 |
st16_i32 t0, t1, offset |
|
st_i32 |
st_i32 t0, t1, offset |
|
|
||
/* arith */ |
||
add_i32 |
add_i32 t0, t1, t2 |
t0=t1+t2 |
sub_i32 |
sub_i32 t0, t1, t2 |
t0=t1-t2 |
mul_i32 |
mul_i32 t0, t1, t2 |
t0=t1*t2 |
div_i32 |
div_i32 t0, t1, t2 |
t0=t1/t2 (signed) |
divu_i32 |
divu_i32 t0, t1, t2 |
t0=t1/t2 (unsigned) |
rem_i32 |
rem_i32 t0, t1, t2 |
t0=t1%t2 (signed) |
remu_i32 |
remu_i32 t0, t1, t2 |
t0=t1%t2 (unsigned) |
and_i32 |
and_i32 t0, t1, t2 |
t0=t1&t2 |
or_i32 |
or_i32 t0, t1, t2 |
t0=t1|t2 |
xor_i32 |
xor_i32 t0, t1, t2 |
t0=t1^t2 |
|
||
/* shifts/rotates */ |
||
shl_i32 |
shl_i32 t0, t1, t2 |
t0=t1 << t2 |
shr_i32 |
shr_i32 t0, t1, t2 |
t0=t1 >> t2 |
sar_i32 |
sar_i32 t0, t1, t2 |
t0=t1 >> t2 (signed) |
rotl_i32 |
rotl_i32 t0, t1, t2 |
Rotation of t2 bits to the left |
rotr_i32 |
rotr_i32 t0, t1, t2 |
Rotation of t2 bits to the right |
deposit_i32 |
deposit_i32 dest, t1, t2, pos, len |
LEN - the length of the bitfield POS - the position of the first bit, counting from the LSB For example, pos=8, len=4: dest = (t1 & ~0x0f00) | ((t2 << 8) & 0x0f00) |
ext8s_i32 |
ext8s_i32 t0, t1 |
8 bit sign extension |
ext8u_i32 |
ext8u_i32 t0, t1 |
8 bit zero extension |
ext16s_i32 |
ext16s_i32 t0, t1 |
16 bit sign extension |
ext16u_i32 |
ext16u_i32 t0, t1 |
16 bit zero extension |
bswap16_i32 |
bswap16_i32 t0, t1 |
16 bit byte swap on a 32 bit value |
bswap32_i32 |
bswap32_i32 t0, t1 |
32 bit byte swap on a 32 bit value |
not_i32 |
not_i32 t0, t1 |
t0=~t1 |
neg_i32 |
neg_i32 t0, t1 |
t0=-t1 |
andc_i32 |
andc_i32 t0, t1, t2 |
t0=t1&~t2 |
orc_i32 |
orc_i32 t0, t1, t2 |
t0=t1|~t2 |
eqv_i32 |
eqv_i32 t0, t1, t2 |
t0=~(t1^t2), or equivalently, t0=t1^~t2 |
nand_i32 |
nand_i32 t0, t1, t2 |
t0=~(t1&t2) |
nor_i32 |
nor_i32 t0, t1, t2 |
t0=~(t1|t2) |
|
||
/* QEMU specific */ |
||
debug_insn_start |
debug_insn_start $pc |
write the PC of the corresponding QEMU CPU instruction |
exit_tb |
exit_tb t0 |
Exit the current TB and return the value t0 (word type) |
goto_tb |
goto_tb index |
Exit the current TB and jump to the TB index ‘index‘ (constant) if the current TB was linked to this TB. Otherwise execute the next instructions. |
|
|
|
qemu_ld8u |
qemu_ld8u t0, t1, flags |
Load data at the QEMU CPU address t1 into t0. t1 has the QEMU CPU address type. ‘flags‘ contains the QEMU memory index (selects user or kernel access) for example. |
qemu_ld8s |
qemu_ld8s t0, t1, flags |
|
qemu_ld16u |
qemu_ld16u t0, t1, flags |
|
qemu_ld16s |
qemu_ld16s t0, t1, flags |
|
qemu_ld32 |
qemu_ld32 t0, t1, flags |
|
qemu_ld32u |
qemu_ld32u t0, t1, flags |
|
qemu_ld32s |
qemu_ld32s t0, t1, flags |
|
qemu_ld64 |
qemu_ld64 t0, t1, flags |
|
|
|
|
qemu_st8 |
qemu_st8 t0, t1, flags |
Store the data t0 at the QEMU CPU Address t1. t1 has the QEMU CPU address type. ‘flags‘ contains the QEMU memory index (selects user or kernel access) for example. |
标签:
原文地址:http://blog.csdn.net/lulu901130/article/details/45716883