QEMU uses the TCG (Tiny code generator) translation engine, and the TCG functions as a true compiler backend, primarily responsible for parsing, optimizing target code, and generating host code. The so-called "micro-instruction" is the middle representation that QEMU uses for instruction translation, in which QEMU first breaks down the instruction of each target into a number of micro instructions similar to RISC instructions, which can be optimized, such as the life cycle analysis of micro-instructions (liveness Analysis), and then the instruction of the driven by host machine is implemented after the micro instruction.
CPU instructions are generally very regular, each instruction length, operation code, operation number has a fixed format, according to the front can be deduced from the back, micro-instruction design also adopted a similar rule, each micro-directive has a fixed input, output and constant operand (except the call instruction has an indefinite number of input and output operations). In addition, with the CPU instructions, micro-instructions also designed data transmission, arithmetic operations, logic operations, program control several major classes of instructions.
The following is an analysis of the micro-instruction types provided by QEMU:
1. Micro-instruction Basic format
Micro directives are defined in tcg/tcg-opc.h. Defines the format as
DEF (name, Oargs,iargs, Cargs, flags)
Where name is a micro-instruction name, Oargs is the number of output operations, Iargs is the number of input operations, Cargs is a constant operand, and flags represents some flags for special instructions, such as the flags value of Tcg_opf_side_ Effects indicates that the directive affects in-memory content.
For example, an add instruction micro-operation is defined as:
DEF (ADD_I32, 1, 2, 0, 0)
The meaning is:
ADD_I32 t0, T1, T2 (t0 <-t1 + T2), i32 indicates that the target machine is a 32-bit machine. T0 is the output operand, T1, T2 is two input operands, there is no constant operand.
2.QEMU pre-defined micro instructions
The CPU instruction corresponds, the micro instruction also designs the data transmission, the arithmetic operation, the logical operation, the program control several big class instruction. And for 32-bit and 64-bit target machines, QEMU defined a set of micro-instructions, namely [OPNAME]_I32, [opname]_i64, because the current Csky CPU is 32 bits, so we first focus on 32-bit micro-instructions.
1) Data transfer
2) Arithmetic operations
3) Logical operation
4) Program Control
3. Micro-instruction type induction
Instruction Name |
Instruction format |
directive meaning |
/* 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. |
Pager |
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, 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, up to or from 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 |
-bit sign Extension |
Ext16u_i32 |
EXT16U_I32 t0, T1 |
-bit Zero extension |
Bswap16_i32 |
BSWAP16_I32 t0, T1 |
-bit byte swap on a + bit value |
Bswap32_i32 |
BSWAP32_I32 t0, T1 |
A byte swap on a + 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 is linked to this TB. Otherwise Execute the next Instructions. |
|
|
|
qemu_ld8u |
qemu_ld8u t0, T1, flags |
Load data at the QEMU CPU address T1 to 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. |
QEMU Intermediate Code Micro Instruction type Summary