From patchwork Sat Feb 21 03:05:15 2015 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Chen Gang X-Patchwork-Id: 442172 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from lists.gnu.org (lists.gnu.org [IPv6:2001:4830:134:3::11]) (using TLSv1 with cipher AES256-SHA (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 10C3B14016A for ; Sat, 21 Feb 2015 13:58:03 +1100 (AEDT) Received: from localhost ([::1]:34954 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1YP0GV-0006OX-2Q for incoming@patchwork.ozlabs.org; Fri, 20 Feb 2015 21:57:59 -0500 Received: from eggs.gnu.org ([2001:4830:134:3::10]:56273) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1YP0GA-00063x-Vo for qemu-devel@nongnu.org; Fri, 20 Feb 2015 21:57:41 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1YP0G7-0002SU-MY for qemu-devel@nongnu.org; Fri, 20 Feb 2015 21:57:38 -0500 Received: from out1134-227.mail.aliyun.com ([42.120.134.227]:63551) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1YP0G6-0002Q3-Po for qemu-devel@nongnu.org; Fri, 20 Feb 2015 21:57:35 -0500 X-Alimail-AntiSpam: AC=CONTINUE; BC=0.07423498|-1; FP=0|0|0|0|0|-1|-1|-1; HT=r41g03008; MF=gang.chen@sunrus.com.cn; PH=DS; RN=6; RT=6; SR=0; Received: from ShengShiZhuChengdeMacBook-Pro.local(mailfrom:gang.chen@sunrus.com.cn ip:223.72.65.10) by smtp.aliyun-inc.com(10.147.38.252); Sat, 21 Feb 2015 10:57:23 +0800 Message-ID: <54E7F5EB.60402@sunrus.com.cn> Date: Sat, 21 Feb 2015 11:05:15 +0800 From: Chen Gang S User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.10; rv:31.0) Gecko/20100101 Thunderbird/31.4.0 MIME-Version: 1.0 To: Peter Maydell , Chris Metcalf , Riku Voipio , "rth@twiddle.net" , "walt@tilera.com" X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.6.x X-Received-From: 42.120.134.227 Cc: qemu-devel Subject: [Qemu-devel] [PATCH] target-tilegx: Finish decoding the first TB block. X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.14 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Sender: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org At present finish decoding the first TB block: _start. Always let y1 and x1 pipe at the last which may content jump instructions. The related disassembly code is below which is the same as the objdump: y0: 00000000500bfdb4 move r52, r54 y2: 0208000007600000 ld r1, r54 y1: 1c06400000000000 fnop x0: 0000000051483000 fnop x1: 180f86c600000000 addi r12, r54, -16 x0: 00000000403f8336 andi r54, r12, -8 x1: 286af00680000000 lnk r13 y0: 00000000500bf005 move r5, r0 y2: 03f8000007600000 st r54, r63 y1: 040046c600000000 addi r12, r54, 8 y0: 00000000500bfff7 move r55, r63 y2: 03f8000004c00000 st r12, r63 y1: 0400468100000000 addi r2, r52, 8 x0: 0000000040110d86 addi r6, r54, 16 x1: 07ffffe000000000 moveli r0, -1 x0: 000000007ffff000 shl16insli r0, r0, -1 x1: 000007e180000000 moveli r3, 0 x0: 000000007ffa8000 shl16insli r0, r0, -88 x1: 3800006180000000 shl16insli r3, r3, 0 x0: 00000000500cd000 and r0, r0, r13 x1: 3877406180000000 shl16insli r3, r3, 3816 x0: 0000000010000fcc moveli r12, 0 x1: 2806686180000000 add r3, r3, r13 x0: 000000007000030c shl16insli r12, r12, 0 x1: 000007e200000000 moveli r4, 0 x0: 000000007039030c shl16insli r12, r12, 912 x1: 3800008200000000 shl16insli r4, r4, 0 x0: 00000000500cd30c and r12, r12, r13 x1: 3881808200000000 shl16insli r4, r4, 4144 x0: 00000000500cd104 and r4, r4, r13 x1: 286a718000000000 jr r12 Signed-off-by: Chen Gang --- target-tilegx/cpu-qom.h | 2 + target-tilegx/cpu.c | 4 - target-tilegx/cpu.h | 1 + target-tilegx/translate.c | 437 +++++++++++++++++++++++++++++++++++++++++++++- 4 files changed, 433 insertions(+), 11 deletions(-) diff --git a/target-tilegx/cpu-qom.h b/target-tilegx/cpu-qom.h index e15a8b8..866a77d 100644 --- a/target-tilegx/cpu-qom.h +++ b/target-tilegx/cpu-qom.h @@ -69,4 +69,6 @@ static inline TilegxCPU *tilegx_env_get_cpu(CPUTLState *env) #define ENV_GET_CPU(e) CPU(tilegx_env_get_cpu(e)) +#define ENV_OFFSET offsetof(TilegxCPU, env) + #endif diff --git a/target-tilegx/cpu.c b/target-tilegx/cpu.c index 3dd66b5..a10cc24 100644 --- a/target-tilegx/cpu.c +++ b/target-tilegx/cpu.c @@ -69,10 +69,6 @@ static void tilegx_cpu_realizefn(DeviceState *dev, Error **errp) mcc->parent_realize(dev, errp); } -static void tilegx_tcg_init(void) -{ -} - static void tilegx_cpu_initfn(Object *obj) { CPUState *cs = CPU(obj); diff --git a/target-tilegx/cpu.h b/target-tilegx/cpu.h index 09a2b26..439c14f 100644 --- a/target-tilegx/cpu.h +++ b/target-tilegx/cpu.h @@ -54,6 +54,7 @@ typedef struct CPUTLState { #include "exec/cpu-all.h" +void tilegx_tcg_init(void); int cpu_tilegx_exec(CPUTLState *s); int cpu_tilegx_signal_handler(int host_signum, void *pinfo, void *puc); diff --git a/target-tilegx/translate.c b/target-tilegx/translate.c index 5131fa7..254f439 100644 --- a/target-tilegx/translate.c +++ b/target-tilegx/translate.c @@ -25,17 +25,440 @@ #include "exec/cpu_ldst.h" #include "exec/helper-gen.h" +#define TILEGX_BUNDLE_SIZE 8 /* Each bundle size in bytes */ +#define TILEGX_BUNDLE_INSNS 3 /* Maximized insns per bundle */ +#define TILEGX_BUNDLE_OPCS 10 /* Assume maximized opcs per bundle */ + +/* Check Bundle whether is Y type, else is X type */ +#define TILEGX_BUNDLE_TYPE_MASK 0xc000000000000000ULL +#define TILEGX_BUNDLE_TYPE_Y(bundle) ((bundle) & TILEGX_BUNDLE_TYPE_MASK) +#define TILEGX_BUNDLE_TYPE_X(bundle) (!TILEGX_BUNDLE_TYPE_Y(bundle)) + +/* Bundle pipe mask, still remain the bundle type */ +#define TILEGX_PIPE_X0(bundle) ((bundle) & 0x000000007fffffffULL) +#define TILEGX_PIPE_X1(bundle) ((bundle) & 0x3fffffff80000000ULL) +#define TILEGX_PIPE_Y0(bundle) ((bundle) & 0x00000000780fffffULL) +#define TILEGX_PIPE_Y1(bundle) ((bundle) & 0x3c07ffff80000000ULL) +#define TILEGX_PIPE_Y2(bundle) ((bundle) & 0x03f8000007f00000ULL) + +/* Code mask */ +#define TILEGX_CODE_X0(bundle) ((bundle) & 0x0000000070000000ULL) +#define TILEGX_CODE_X0_18(bundle) ((bundle) & 0x000000000ffc0000ULL) +#define TILEGX_CODE_X0_20(bundle) ((bundle) & 0x000000000ff00000ULL) +#define TILEGX_CODE_X1(bundle) ((bundle) & 0x3800000000000000ULL) +#define TILEGX_CODE_X1_49(bundle) ((bundle) & 0x07fe000000000000ULL) +#define TILEGX_CODE_X1_49_43(bundle) ((bundle) & 0x0001f80000000000ULL) +#define TILEGX_CODE_X1_51(bundle) ((bundle) & 0x07f8000000000000ULL) +#define TILEGX_CODE_Y0(bundle) ((bundle) & 0x0000000078000000ULL) +#define TILEGX_CODE_Y0_E(bundle) ((bundle) & 0x00000000000c0000ULL) +#define TILEGX_CODE_Y1(bundle) ((bundle) & 0x3c00000000000000ULL) +#define TILEGX_CODE_Y1_E(bundle) ((bundle) & 0x0006000000000000ULL) +#define TILEGX_CODE_Y2(bundle) ((bundle) & 0x0200000004000000ULL) +/* No Y2_E */ + +/* (F)Nop operation, only have effect within their own pipe */ +#define TILEGX_OPCX0_FNOP 0x0000000051483000ULL +#define TILEGX_OPCX0_NOP 0x0000000051485000ULL +#define TILEGX_OPCX1_FNOP 0x286a300000000000ULL +#define TILEGX_OPCX1_NOP 0x286b080000000000ULL +#define TILEGX_OPCY0_FNOP 0x00000000300c3000ULL +#define TILEGX_OPCY0_NOP 0x00000000300c5000ULL +#define TILEGX_OPCY1_FNOP 0x1c06400000000000ULL +#define TILEGX_OPCY1_NOP 0x1c06780000000000ULL +/* No Y2 (F)NOP */ + +/* Data width mask */ +#define TILEGX_DATA_REGISTER 0x3f /* Register data width mask */ +#define TILEGX_DATA_IMM8 0xff /* Imm8 data width mask */ +#define TILEGX_DATA_IMM16 0xffff /* Imm8 data width mask */ + +static TCGv_ptr cpu_env; + +#include "exec/gen-icount.h" + +void tilegx_tcg_init(void) +{ + cpu_env = tcg_global_reg_new_ptr(TCG_AREG0, "env"); +} + +/* This is the state at translation time. */ +struct DisasContext { + uint64_t pc; + + int is_jmp; + unsigned int cpustate_changed; +}; + +static int translate_x0_bundle(struct DisasContext *dc, uint64_t bundle) +{ + unsigned char rdest, rsrc, rsrcb; + char im8; + short im16; + + qemu_log("\nx0: %16.16lx\t", bundle); + if (bundle == TILEGX_OPCX0_FNOP) { + qemu_log("fnop"); + return 0; + } + + if (bundle == TILEGX_OPCX0_NOP) { + qemu_log("nop"); + return 0; + } + + switch (TILEGX_CODE_X0(bundle)) { + case 0x0000000010000000ULL: + rdest = (unsigned char)(bundle & TILEGX_DATA_REGISTER); + rsrc = (unsigned char)((bundle >> 6) & TILEGX_DATA_REGISTER); + im16 = (short)((bundle >> 12) & TILEGX_DATA_IMM16); + if (rsrc != 0x3f) { + /* FIXME: raise an exception for invalid instruction */ + qemu_log("invalid moveli src value: %x", rsrc); + return -1; + } + qemu_log("moveli r%d, %d", rdest, im16); + break; + + case 0x0000000040000000ULL: + switch (TILEGX_CODE_X0_20(bundle)) { + /* andi Dest, SrcA, Imm8 */ + case 0x0000000000300000ULL: + rdest = (unsigned char)(bundle & TILEGX_DATA_REGISTER); + rsrc = (unsigned char)((bundle >> 6) & TILEGX_DATA_REGISTER); + im8 = (char)((bundle >> 12) & TILEGX_DATA_IMM8); + qemu_log("andi r%d, r%d, %d", rdest, rsrc, im8); + break; + + /* addi Dest, SrcA, Imm8 */ + case 0x0000000000100000ULL: + rdest = (unsigned char)(bundle & TILEGX_DATA_REGISTER); + rsrc = (unsigned char)((bundle >> 6) & TILEGX_DATA_REGISTER); + im8 = (char)((bundle >> 12) & TILEGX_DATA_IMM8); + qemu_log("addi r%d, r%d, %d", rdest, rsrc, im8); + break; + + default: + /* FIXME: raise an exception for invalid instruction */ + qemu_log("20 bundle value: %16.16llx", TILEGX_CODE_X0_20(bundle)); + return -1; + } + break; + + case 0x0000000050000000ULL: + switch (TILEGX_CODE_X0_18(bundle)) { + /* add Dest, SrcA, SrcB */ + case 0x00000000000c0000ULL: + rdest = (unsigned char)(bundle & TILEGX_DATA_REGISTER); + rsrc = (unsigned char)((bundle >> 6) & TILEGX_DATA_REGISTER); + rsrcb = (unsigned char)((bundle >> 12) & TILEGX_DATA_REGISTER); + qemu_log("and r%d, r%d, r%d", rdest, rsrc, rsrcb); + break; + + default: + /* FIXME: raise an exception for invalid instruction */ + qemu_log("18 bundle value: %16.16llx", TILEGX_CODE_X0_18(bundle)); + return -1; + } + break; + + /* shl16insli Dest, SrcA, Imm16 */ + case 0x0000000070000000ULL: + rdest = (unsigned char)(bundle & TILEGX_DATA_REGISTER); + rsrc = (unsigned char)((bundle >> 6) & TILEGX_DATA_REGISTER); + im16 = (short)((bundle >> 12) & TILEGX_DATA_IMM16); + qemu_log("shl16insli r%d, r%d, %d", rdest, rsrc, im16); + break; + + default: + /* FIXME: raise an exception for invalid instruction */ + qemu_log("bundle value: %16.16llx", TILEGX_CODE_X0(bundle)); + return -1; + } + + return 0; +} + +static int translate_x1_bundle(struct DisasContext *dc, uint64_t bundle) +{ + unsigned char rdest, rsrc, rsrcb; + char im8; + short im16; + + qemu_log("\nx1: %16.16lx\t", bundle); + if (bundle == TILEGX_OPCX1_FNOP) { + qemu_log("fnop"); + return 0; + } + + if (bundle == TILEGX_OPCX1_NOP) { + qemu_log("nop"); + return 0; + } + + switch (TILEGX_CODE_X1(bundle)) { + /* moveli Dest, Imm16 */ + case 0x0000000000000000ULL: + rdest = (unsigned char)((bundle >> 31) & TILEGX_DATA_REGISTER); + rsrc = (unsigned char)((bundle >> 37) & TILEGX_DATA_REGISTER); + im16 = (short)((bundle >> 43) & TILEGX_DATA_IMM16); + if (rsrc != 0x3f) { + /* FIXME: raise an exception for invalid instruction */ + qemu_log("invalid moveli src value: %x", rsrc); + return -1; + } + qemu_log("moveli r%d, %d", rdest, im16); + break; + + case 0x1800000000000000ULL: + switch (TILEGX_CODE_X1_51(bundle)) { + /* addi Dest, SrcA, Imm8 */ + case 0x0008000000000000ULL: + rdest = (unsigned char)((bundle >> 31) & TILEGX_DATA_REGISTER); + rsrc = (unsigned char)((bundle >> 37) & TILEGX_DATA_REGISTER); + im8 = (char)((bundle >> 43) & TILEGX_DATA_IMM8); + qemu_log("addi r%d, r%d, %d", rdest, rsrc, im8); + break; + default: + /* FIXME: raise an exception for invalid instruction */ + qemu_log("51 bundle value: %llx", TILEGX_CODE_X1_51(bundle)); + return -1; + } + break; + + case 0x2800000000000000ULL: + switch (TILEGX_CODE_X1_49(bundle)) { + /* add Dest, SrcA, SrcB */ + case 0x0006000000000000ULL: + rdest = (unsigned char)((bundle >> 31) & TILEGX_DATA_REGISTER); + rsrc = (unsigned char)((bundle >> 37) & TILEGX_DATA_REGISTER); + rsrcb = (unsigned char)((bundle >> 43) & TILEGX_DATA_REGISTER); + qemu_log("add r%d, r%d, r%d", rdest, rsrc, rsrcb); + break; + + case 0x006a000000000000ULL: + switch (TILEGX_CODE_X1_49_43(bundle)) { + /* lnk Dest */ + case 0x0000f00000000000ULL: + rdest = (unsigned char)((bundle >> 31) & TILEGX_DATA_REGISTER); + qemu_log("lnk r%d", rdest); + break; + /* jr SrcA */ + case 0x0000700000000000ULL: + rsrc = (unsigned char)((bundle >> 37) & TILEGX_DATA_REGISTER); + qemu_log("jr r%d", rsrc); + dc->is_jmp = DISAS_JUMP; + break; + + default: + /* FIXME: raise an exception for invalid instruction */ + qemu_log("49_43 bundle value: %16.16llx", + TILEGX_CODE_X1_49_43(bundle)); + return -1; + } + break; + default: + /* FIXME: raise an exception for invalid instruction */ + qemu_log("49 bundle value: %16.16llx", TILEGX_CODE_X1_49(bundle)); + return -1; + } + break; + + /* shl16insli Dest, SrcA, Imm16 */ + case 0x3800000000000000ULL: + rdest = (unsigned char)((bundle >> 31) & TILEGX_DATA_REGISTER); + rsrc = (unsigned char)((bundle >> 37) & TILEGX_DATA_REGISTER); + im16 = (short)((bundle >> 43) & TILEGX_DATA_IMM16); + qemu_log("shl16insli r%d, r%d, %d", rdest, rsrc, im16); + break; + + default: + /* FIXME: raise an exception for invalid instruction */ + qemu_log("bundle value: %16.16llx", TILEGX_CODE_X1(bundle)); + return -1; + } + + return 0; +} + +static int translate_y0_bundle(struct DisasContext *dc, uint64_t bundle) +{ + unsigned char rsrc, rdst; + + qemu_log("\ny0: %16.16lx\t", bundle); + if (bundle == TILEGX_OPCY0_FNOP) { + qemu_log("fnop"); + return 0; + } + + if (bundle == TILEGX_OPCY0_NOP) { + qemu_log("nop"); + return 0; + } + + switch (TILEGX_CODE_Y0(bundle)) { + case 0x0000000050000000ULL: + switch (TILEGX_CODE_Y0_E(bundle)) { + /* move Dest, SrcA */ + case 0x0000000000080000ULL: + rdst = (unsigned char)(bundle & TILEGX_DATA_REGISTER); + rsrc = (unsigned char)((bundle >> 6) & TILEGX_DATA_REGISTER); + qemu_log("move r%d, r%d", rdst, rsrc); + break; + default: + /* FIXME: raise an exception for invalid instruction */ + return -1; + } + break; + + default: + /* FIXME: raise an exception for invalid instruction */ + qemu_log("bundle value: %16.16llx", TILEGX_CODE_Y0(bundle)); + return -1; + } + + return 0; +} + +static int translate_y1_bundle(struct DisasContext *dc, uint64_t bundle) +{ + unsigned char rdest, rsrc; + char im8; + + qemu_log("\ny1: %16.16lx\t", bundle); + if (bundle == TILEGX_OPCY1_FNOP) { + qemu_log("fnop"); + return 0; + } + + if (bundle == TILEGX_OPCY1_NOP) { + qemu_log("nop"); + return 0; + } + + switch (TILEGX_CODE_Y1(bundle)) { + /* addi Dest, SrcA, Imm8 */ + case 0x0400000000000000ULL: + rdest = (unsigned char)((bundle >> 31) & TILEGX_DATA_REGISTER); + rsrc = (unsigned char)((bundle >> 37) & TILEGX_DATA_REGISTER); + im8 = (char)((bundle >> 43) & TILEGX_DATA_IMM8); + qemu_log("addi r%d, r%d, %d", rdest, rsrc, im8); + break; + + default: + /* FIXME: raise an exception for invalid instruction */ + qemu_log("bundle value: %16.16llx", TILEGX_CODE_Y1(bundle)); + return -1; + } + + return 0; +} + +static int translate_y2_bundle(struct DisasContext *dc, uint64_t bundle, + uint64_t mode) +{ + unsigned char rsrc, rdest; + + qemu_log("\ny2: %16.16lx\t", bundle); + switch (TILEGX_CODE_Y2(bundle)) { + case 0x0200000004000000ULL: + switch (mode) { + /* ld Dest, Src */ + case 0x8000000000000000ULL: + rdest = (unsigned char)((bundle >> 51) & TILEGX_DATA_REGISTER); + rsrc = (unsigned char)((bundle >> 20) & TILEGX_DATA_REGISTER); + qemu_log("ld r%d, r%d", rdest, rsrc); + break; + /* st Dest, Src */ + case 0xc000000000000000ULL: + rdest = (unsigned char)((bundle >> 20) & TILEGX_DATA_REGISTER); + rsrc = (unsigned char)((bundle >> 51) & TILEGX_DATA_REGISTER); + qemu_log("st r%d, r%d", rdest, rsrc); + break; + default: + /* FIXME: raise an exception for invalid instruction */ + qemu_log("bundle value: %16.16llx, mode: %16.16lx", + TILEGX_CODE_Y2(bundle), mode); + return -1; + } + break; + + default: + /* FIXME: raise an exception for invalid instruction */ + qemu_log("bundle value: %16.16llx", TILEGX_CODE_Y2(bundle)); + return -1; + } + + return 0; +} + +static int translate_one_bundle(struct DisasContext *dc, uint64_t bundle) +{ + int ret = 0; + + if (TILEGX_BUNDLE_TYPE_Y(bundle)) { + ret = translate_y0_bundle(dc, TILEGX_PIPE_Y0(bundle)); + if (ret) { + return ret; + } + ret = translate_y2_bundle(dc, TILEGX_PIPE_Y2(bundle), + bundle & TILEGX_BUNDLE_TYPE_MASK); + if (ret) { + return ret; + } + /* y1 may jump, so the last */ + return translate_y1_bundle(dc, TILEGX_PIPE_Y1(bundle)); + } + + ret = translate_x0_bundle(dc, TILEGX_PIPE_X0(bundle)); + if (ret) { + return ret; + } + /* x1 may jump, so the last */ + return translate_x1_bundle(dc, TILEGX_PIPE_X1(bundle)); +} + static inline void gen_intermediate_code_internal(TilegxCPU *cpu, TranslationBlock *tb, bool search_pc) { - /* - * FIXME: after load elf64 tilegx binary successfully, it will quit, at - * present, and will implement the related features next. - */ - fprintf(stderr, "\nLoad elf64 tilegx successfully\n"); - fprintf(stderr, "reach code start position: [" TARGET_FMT_lx "] %s\n\n", - tb->pc, lookup_symbol(tb->pc)); + int ret = 0; + struct DisasContext ctx; + struct DisasContext *dc = &ctx; + + CPUTLState *env = &cpu->env; + uint64_t pc_start = tb->pc; + uint64_t next_page_start = (pc_start & TARGET_PAGE_MASK) + TARGET_PAGE_SIZE; + int num_insns = 0; + int max_insns = tb->cflags & CF_COUNT_MASK; + + /* FIXME: do not consider about search_pc firstly. */ + + dc->is_jmp = DISAS_NEXT; + dc->pc = pc_start; + dc->cpustate_changed = 0; + + if (!max_insns) { + max_insns = CF_COUNT_MASK; + } + + gen_tb_start(tb); + do { + ret = translate_one_bundle(dc, cpu_ldq_data(env, dc->pc)); + if (ret) { + goto err; + } + num_insns++; + dc->pc += 8; + } while (tcg_op_buf_count() <= OPC_MAX_SIZE - TILEGX_BUNDLE_OPCS + && num_insns <= max_insns - TILEGX_BUNDLE_INSNS + && dc->pc <= next_page_start - TILEGX_BUNDLE_SIZE + && !dc->is_jmp + && !dc->cpustate_changed); + gen_tb_end(tb, num_insns); + + /* FIXME: Only decode once */ +err: + qemu_log("\n\nfinish tb translation.\n"); exit(0); }