160 likes | 317 Views
TCG to LLVM. Ding-Yong Hong. Category of TCG IR. Register movement : mov , movi Logical : and, or, xor , shl , shr , … Arithmetic : add, sub, mul , div, … Memory Ops : qemu_ld , qemu_st Ex: mov % eax , 0x4(% ebx ) Internal memory Ops : ld , st Used to access entry of CPUState
E N D
TCG to LLVM Ding-Yong Hong
Category of TCG IR • Register movement: mov, movi • Logical: and, or, xor, shl, shr, … • Arithmetic: add, sub, mul, div, … • Memory Ops: qemu_ld, qemu_st • Ex: mov %eax, 0x4(%ebx) • Internal memory Ops: ld, st • Used to access entry of CPUState • Ex: movi 0x8000000, 0x20(%r14) # env->eip = 0x8000000 • Branch Ops: jmp, br, brcond • Helper function: call • Misc: exit_tb, end • Index to opcode: INDEX_op_XXX • Ex: INDEX_op_add
TCG IR Structure • gen_opc_buf: list of opcodes • gen_opparam_buf: list of opcode parameters Ex: mov %eax, %ebx add %ebx, %ecx mov 0x10, %edx ... jmp 0x8000000 exit_tb ...... gen_opc_buf mov movi end add ...... gen_opparam_buf
LLVM IR Function Interface • TCG-to-LLVM IR functions are contained in class IRFactory • All functions are named op_XXXand have the same interface TCGArg*args • The return value of a function is # parameters used in this op • All IR function pointers are stored in a mapping table class IRFactory { intop_mov(constTCGArg *args); intop_add(constTCGArg *args); intop_call(constTCGArg *args); map<opcode, FnPtr*> OpcFn; }; args = gen_opparam_buf; for (i = 0; I < num_opc; i++) { TCGOpcodeopc = gen_opc_buf [i]; NumParam = (IF->*OpcFn[opc])(args); args += NumParam; } exit_tb ...... gen_opc_buf mov movi end add ...... gen_opparam_buf
Information We Need from TCG • Information about virtual registers allocated in TCG IR • We prepare the same # of LLVM virtual registers eax ebx Register tmp1 tmp2 tmp8 ..... struct Register { int Type; int Base; int Size; llvm_offset Off; char *Name; Value *Data; boolDirty; }; Register Reg[0] { .Type = I32; .Base = R14; .Size = 32; .Off = 0x4; .Name = “ecx”; .Data = NULL; .Dirty = false; }; exit_tb ...... gen_opc_buf mov movi end add ...... gen_opparam_buf tmp1 tmp1 tmp2 tmp8
Load States from CPUState • LoadInput()is to load state from CPUState to LLVM virtual register • Return value if already loaded or load from memory Register Register Reg[8] { .Type = I32; .Base = R14; .Size = 32; .Off = 0x4; .Name = “ecx”; .Data = NULL; .Dirty = false; }; Register Reg[8] { .Type = I32; .Base = R14; .Size = 32; .Off = 0x4; .Name = “ecx”; .Data = pointer to Value(X); .Dirty = false; }; ..... llvm::Value X
Register Movement • Register movement: mov, movi intIRFactory::op_mov_i32(constTCGArg *args) { Register *Out = &Reg[args[0]]; Register *In = &Reg[args[1]]; Value *InData = LoadInput(In); # A = new LoadInst(addr); Out->setData(InData, true); return 2; } opc mov Register args[0] args ..... structRegister Reg[args[0]] Reg[args[1]] { int Type; int Base; int Size; llvm_offset Off; char *Name; Value *Data; A A boolDirty; true false }; llvm::Value A args[1]
Logical & Arithmetic Operations • Logical: and, or, xor, shl, shr, … • Arithmetic: add, sub, mul, div, … intIRFactory::op_add_i32(constTCGArg *args) { Register *Out = &Reg[args[0]]; Register *In1 = &Reg[args[1]]; Register *In2 = &Reg[args[2]]; Value *InData1 = LoadInput(In1); Value *InData2 = LoadInput(In2); Value *OutData; = ADD(InData1, InData2); Out->setData(OutData, true); return 3; } #define AND(a,b) BinaryOperator::Create(Instruction::And, a, b, "", InsertPos) #define OR(a,b) BinaryOperator::Create(Instruction::Or, a, b, "", InsertPos) #define ADD(a,b) BinaryOperator::Create(Instruction::Add, a, b, "", InsertPos) opc add args tmp1 tmp1 tmp2
Memory Operations • Memory Ops: qemu_ld, qemu_st • Ex: mov 0x4(%ebx), %eax intIRFactory::op_qemu_ld32(constTCGArg *args) { Register *Out = &Reg[args[0]]; Register *In = &Reg[args[1]]; Value *InData = LoadInput(In); # load %ebx SaveGlobals(COHERENCE_GLOBAL, LastInst); InData = QEMULoad(InData, GUEST_BASE, 2, args[2]); Out->setData(InData, true); return 3; } opc qemu_ld32 args eax ebx 0x4
Store Dirty States to CPUState • SaveGlobals() is to store dirty states back to memory • Opcodes need to save states • op_jmp • op_br • op_brcond • op_call • op_goto_tb • op_exit_tb • op_qemu_ld_XXX • op_qemu_st_XXX Register D Register Reg[1] { .Type = I32; .Base = R14; .Size = 32; .Off = 0x4; .Name = “ecx”; .Data = pointer to X; .Dirty = true; }; ..... llvm::Value X D A
Page Fault Handling in QEMU System Mode • QEMULoad() Host code: Guest code: S1: mov %eax, %ebx S2: add %eax, %ecx S3: add %eax, %edx S4: mov(%eax), eax S5: mov %eax, %ebx S6: mov %eax, %ebx S1’: … S2’: … S3’: … S4’: op_qemu_ld32 %1 = LoadInput ( %eax ) %2 = do_tlb_Lookup( %r0 ) If%2 = HIT then mov(%eax), eax goto S5’ else# page fault call PageFaultHelper() endif S5’: … S6’: … translate
Category of TCG IR • Internal memory Ops: ld, st • Used to access entry of CPUState • Ex: movi 0x8000000, 0x20(%r14) • Branch Ops: jmp, br, brcond • Helper function: call • Misc: exit_tb, end