X-Git-Url: https://gerrit.opnfv.org/gerrit/gitweb?a=blobdiff_plain;f=qemu%2Ftarget-xtensa%2Ftranslate.c;h=989448846902408ca558ad1899e3295f30f819c6;hb=refs%2Fchanges%2F03%2F14303%2F1;hp=f2118c24c03522b09c3a442376ef9257ec1f1e2f;hpb=5bbd6fe9b8bab2a93e548c5a53b032d1939eec05;p=kvmfornfv.git diff --git a/qemu/target-xtensa/translate.c b/qemu/target-xtensa/translate.c index f2118c24c..989448846 100644 --- a/qemu/target-xtensa/translate.c +++ b/qemu/target-xtensa/translate.c @@ -28,7 +28,7 @@ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#include +#include "qemu/osdep.h" #include "cpu.h" #include "exec/exec-all.h" @@ -43,6 +43,7 @@ #include "exec/helper-gen.h" #include "trace-tcg.h" +#include "exec/log.h" typedef struct DisasContext { @@ -73,7 +74,7 @@ typedef struct DisasContext { unsigned cpenable; } DisasContext; -static TCGv_ptr cpu_env; +static TCGv_env cpu_env; static TCGv_i32 cpu_pc; static TCGv_i32 cpu_R[16]; static TCGv_i32 cpu_FR[16]; @@ -217,24 +218,24 @@ void xtensa_translate_init(void) int i; cpu_env = tcg_global_reg_new_ptr(TCG_AREG0, "env"); - cpu_pc = tcg_global_mem_new_i32(TCG_AREG0, + cpu_pc = tcg_global_mem_new_i32(cpu_env, offsetof(CPUXtensaState, pc), "pc"); for (i = 0; i < 16; i++) { - cpu_R[i] = tcg_global_mem_new_i32(TCG_AREG0, + cpu_R[i] = tcg_global_mem_new_i32(cpu_env, offsetof(CPUXtensaState, regs[i]), regnames[i]); } for (i = 0; i < 16; i++) { - cpu_FR[i] = tcg_global_mem_new_i32(TCG_AREG0, + cpu_FR[i] = tcg_global_mem_new_i32(cpu_env, offsetof(CPUXtensaState, fregs[i].f32[FP_F32_LOW]), fregnames[i]); } for (i = 0; i < 256; ++i) { if (sregnames[i].name) { - cpu_SR[i] = tcg_global_mem_new_i32(TCG_AREG0, + cpu_SR[i] = tcg_global_mem_new_i32(cpu_env, offsetof(CPUXtensaState, sregs[i]), sregnames[i].name); } @@ -242,7 +243,7 @@ void xtensa_translate_init(void) for (i = 0; i < 256; ++i) { if (uregnames[i].name) { - cpu_UR[i] = tcg_global_mem_new_i32(TCG_AREG0, + cpu_UR[i] = tcg_global_mem_new_i32(cpu_env, offsetof(CPUXtensaState, uregs[i]), uregnames[i].name); } @@ -501,9 +502,9 @@ static bool gen_check_sr(DisasContext *dc, uint32_t sr, unsigned access) { if (!xtensa_option_bits_enabled(dc->config, sregnames[sr].opt_bits)) { if (sregnames[sr].name) { - qemu_log("SR %s is not configured\n", sregnames[sr].name); + qemu_log_mask(LOG_GUEST_ERROR, "SR %s is not configured\n", sregnames[sr].name); } else { - qemu_log("SR %d is not implemented\n", sr); + qemu_log_mask(LOG_UNIMP, "SR %d is not implemented\n", sr); } gen_exception_cause(dc, ILLEGAL_INSTRUCTION_CAUSE); return false; @@ -514,8 +515,8 @@ static bool gen_check_sr(DisasContext *dc, uint32_t sr, unsigned access) [SR_X] = "xsr", }; assert(access < ARRAY_SIZE(access_text) && access_text[access]); - qemu_log("SR %s is not available for %s\n", sregnames[sr].name, - access_text[access]); + qemu_log_mask(LOG_GUEST_ERROR, "SR %s is not available for %s\n", sregnames[sr].name, + access_text[access]); gen_exception_cause(dc, ILLEGAL_INSTRUCTION_CAUSE); return false; } @@ -875,18 +876,18 @@ static void disas_xtensa_insn(CPUXtensaState *env, DisasContext *dc) { #define HAS_OPTION_BITS(opt) do { \ if (!option_bits_enabled(dc, opt)) { \ - qemu_log("Option is not enabled %s:%d\n", \ - __FILE__, __LINE__); \ + qemu_log_mask(LOG_GUEST_ERROR, "Option is not enabled %s:%d\n", \ + __FILE__, __LINE__); \ goto invalid_opcode; \ } \ } while (0) #define HAS_OPTION(opt) HAS_OPTION_BITS(XTENSA_OPTION_BIT(opt)) -#define TBD() qemu_log("TBD(pc = %08x): %s:%d\n", dc->pc, __FILE__, __LINE__) +#define TBD() qemu_log_mask(LOG_UNIMP, "TBD(pc = %08x): %s:%d\n", dc->pc, __FILE__, __LINE__) #define RESERVED() do { \ - qemu_log("RESERVED(pc = %08x, %02x%02x%02x): %s:%d\n", \ - dc->pc, b0, b1, b2, __FILE__, __LINE__); \ + qemu_log_mask(LOG_GUEST_ERROR, "RESERVED(pc = %08x, %02x%02x%02x): %s:%d\n", \ + dc->pc, b0, b1, b2, __FILE__, __LINE__); \ goto invalid_opcode; \ } while (0) @@ -1186,7 +1187,7 @@ static void disas_xtensa_insn(CPUXtensaState *env, DisasContext *dc) gen_jump(dc, cpu_SR[EPC1 + RRR_S - 1]); } } else { - qemu_log("RFI %d is illegal\n", RRR_S); + qemu_log_mask(LOG_GUEST_ERROR, "RFI %d is illegal\n", RRR_S); gen_exception_cause(dc, ILLEGAL_INSTRUCTION_CAUSE); } break; @@ -1222,7 +1223,7 @@ static void disas_xtensa_insn(CPUXtensaState *env, DisasContext *dc) gen_helper_simcall(cpu_env); } } else { - qemu_log("SIMCALL but semihosting is disabled\n"); + qemu_log_mask(LOG_GUEST_ERROR, "SIMCALL but semihosting is disabled\n"); gen_exception_cause(dc, ILLEGAL_INSTRUCTION_CAUSE); } break; @@ -1544,7 +1545,7 @@ static void disas_xtensa_insn(CPUXtensaState *env, DisasContext *dc) TCGv_i64 tmp = tcg_temp_new_i64(); \ tcg_gen_extu_i32_i64(tmp, reg); \ tcg_gen_##cmd##_i64(v, v, tmp); \ - tcg_gen_trunc_i64_i32(cpu_R[RRR_R], v); \ + tcg_gen_extrl_i64_i32(cpu_R[RRR_R], v); \ tcg_temp_free_i64(v); \ tcg_temp_free_i64(tmp); \ } while (0) @@ -1865,7 +1866,7 @@ static void disas_xtensa_insn(CPUXtensaState *env, DisasContext *dc) if (uregnames[st].name) { tcg_gen_mov_i32(cpu_R[RRR_R], cpu_UR[st]); } else { - qemu_log("RUR %d not implemented, ", st); + qemu_log_mask(LOG_UNIMP, "RUR %d not implemented, ", st); TBD(); } } @@ -1876,7 +1877,7 @@ static void disas_xtensa_insn(CPUXtensaState *env, DisasContext *dc) if (uregnames[RSR_SR].name) { gen_wur(RSR_SR, cpu_R[RRR_T]); } else { - qemu_log("WUR %d not implemented, ", RSR_SR); + qemu_log_mask(LOG_UNIMP, "WUR %d not implemented, ", RSR_SR); TBD(); } } @@ -1943,7 +1944,8 @@ static void disas_xtensa_insn(CPUXtensaState *env, DisasContext *dc) switch (OP2) { case 0: /*L32E*/ HAS_OPTION(XTENSA_OPTION_WINDOWED_REGISTER); - if (gen_check_privilege(dc)) { + if (gen_check_privilege(dc) && + gen_window_check2(dc, RRR_S, RRR_T)) { TCGv_i32 addr = tcg_temp_new_i32(); tcg_gen_addi_i32(addr, cpu_R[RRR_S], (0xffffffc0 | (RRR_R << 2))); @@ -1954,7 +1956,8 @@ static void disas_xtensa_insn(CPUXtensaState *env, DisasContext *dc) case 4: /*S32E*/ HAS_OPTION(XTENSA_OPTION_WINDOWED_REGISTER); - if (gen_check_privilege(dc)) { + if (gen_check_privilege(dc) && + gen_window_check2(dc, RRR_S, RRR_T)) { TCGv_i32 addr = tcg_temp_new_i32(); tcg_gen_addi_i32(addr, cpu_R[RRR_S], (0xffffffc0 | (RRR_R << 2))); @@ -1963,6 +1966,17 @@ static void disas_xtensa_insn(CPUXtensaState *env, DisasContext *dc) } break; + case 5: /*S32N*/ + if (gen_window_check2(dc, RRI4_S, RRI4_T)) { + TCGv_i32 addr = tcg_temp_new_i32(); + + tcg_gen_addi_i32(addr, cpu_R[RRI4_S], RRI4_IMM4 << 2); + gen_load_store_alignment(dc, 2, addr, false); + tcg_gen_qemu_st32(cpu_R[RRI4_T], addr, dc->cring); + tcg_temp_free(addr); + } + break; + default: RESERVED(); break; @@ -1970,6 +1984,16 @@ static void disas_xtensa_insn(CPUXtensaState *env, DisasContext *dc) break; case 10: /*FP0*/ + /*DEPBITS*/ + if (option_enabled(dc, XTENSA_OPTION_DEPBITS)) { + if (!gen_window_check2(dc, RRR_S, RRR_T)) { + break; + } + tcg_gen_deposit_i32(cpu_R[RRR_T], cpu_R[RRR_T], cpu_R[RRR_S], + OP2, RRR_R + 1); + break; + } + HAS_OPTION(XTENSA_OPTION_FP_COPROCESSOR); switch (OP2) { case 0: /*ADD.Sf*/ @@ -2104,6 +2128,16 @@ static void disas_xtensa_insn(CPUXtensaState *env, DisasContext *dc) break; case 11: /*FP1*/ + /*DEPBITS*/ + if (option_enabled(dc, XTENSA_OPTION_DEPBITS)) { + if (!gen_window_check2(dc, RRR_S, RRR_T)) { + break; + } + tcg_gen_deposit_i32(cpu_R[RRR_T], cpu_R[RRR_T], cpu_R[RRR_S], + OP2 + 16, RRR_R + 1); + break; + } + HAS_OPTION(XTENSA_OPTION_FP_COPROCESSOR); #define gen_compare(rel, br, a, b) \ @@ -2973,7 +3007,7 @@ static void disas_xtensa_insn(CPUXtensaState *env, DisasContext *dc) return; invalid_opcode: - qemu_log("INVALID(pc = %08x)\n", dc->pc); + qemu_log_mask(LOG_GUEST_ERROR, "INVALID(pc = %08x)\n", dc->pc); gen_exception_cause(dc, ILLEGAL_INSTRUCTION_CAUSE); #undef HAS_OPTION } @@ -2984,22 +3018,6 @@ static inline unsigned xtensa_insn_len(CPUXtensaState *env, DisasContext *dc) return xtensa_op0_insn_len(OP0); } -static void check_breakpoint(CPUXtensaState *env, DisasContext *dc) -{ - CPUState *cs = CPU(xtensa_env_get_cpu(env)); - CPUBreakpoint *bp; - - if (unlikely(!QTAILQ_EMPTY(&cs->breakpoints))) { - QTAILQ_FOREACH(bp, &cs->breakpoints, entry) { - if (bp->pc == dc->pc) { - tcg_gen_movi_i32(cpu_pc, dc->pc); - gen_exception(dc, EXCP_DEBUG); - dc->is_jmp = DISAS_UPDATE; - } - } - } -} - static void gen_ibreak_check(CPUXtensaState *env, DisasContext *dc) { unsigned i; @@ -3013,15 +3031,12 @@ static void gen_ibreak_check(CPUXtensaState *env, DisasContext *dc) } } -static inline -void gen_intermediate_code_internal(XtensaCPU *cpu, - TranslationBlock *tb, bool search_pc) +void gen_intermediate_code(CPUXtensaState *env, TranslationBlock *tb) { + XtensaCPU *cpu = xtensa_env_get_cpu(env); CPUState *cs = CPU(cpu); - CPUXtensaState *env = &cpu->env; DisasContext dc; int insn_count = 0; - int j, lj = -1; int max_insns = tb->cflags & CF_COUNT_MASK; uint32_t pc_start = tb->pc; uint32_t next_page_start = @@ -3030,6 +3045,9 @@ void gen_intermediate_code_internal(XtensaCPU *cpu, if (max_insns == 0) { max_insns = CF_COUNT_MASK; } + if (max_insns > TCG_MAX_INSNS) { + max_insns = TCG_MAX_INSNS; + } dc.config = env->config; dc.singlestep_enabled = cs->singlestep_enabled; @@ -3062,28 +3080,24 @@ void gen_intermediate_code_internal(XtensaCPU *cpu, } do { - check_breakpoint(env, &dc); + tcg_gen_insn_start(dc.pc); + ++insn_count; - if (search_pc) { - j = tcg_op_buf_count(); - if (lj < j) { - lj++; - while (lj < j) { - tcg_ctx.gen_opc_instr_start[lj++] = 0; - } - } - tcg_ctx.gen_opc_pc[lj] = dc.pc; - tcg_ctx.gen_opc_instr_start[lj] = 1; - tcg_ctx.gen_opc_icount[lj] = insn_count; - } + ++dc.ccount_delta; - if (unlikely(qemu_loglevel_mask(CPU_LOG_TB_OP | CPU_LOG_TB_OP_OPT))) { - tcg_gen_debug_insn_start(dc.pc); + if (unlikely(cpu_breakpoint_test(cs, dc.pc, BP_ANY))) { + tcg_gen_movi_i32(cpu_pc, dc.pc); + gen_exception(&dc, EXCP_DEBUG); + dc.is_jmp = DISAS_UPDATE; + /* The address covered by the breakpoint must be included in + [tb->pc, tb->pc + tb->size) in order to for it to be + properly cleared -- thus we increment the PC here so that + the logic setting tb->size below does the right thing. */ + dc.pc += 2; + break; } - ++dc.ccount_delta; - - if (insn_count + 1 == max_insns && (tb->cflags & CF_LAST_IO)) { + if (insn_count == max_insns && (tb->cflags & CF_LAST_IO)) { gen_io_start(); } @@ -3104,7 +3118,6 @@ void gen_intermediate_code_internal(XtensaCPU *cpu, } disas_xtensa_insn(env, &dc); - ++insn_count; if (dc.icount) { tcg_gen_mov_i32(cpu_SR[ICOUNT], dc.next_icount); } @@ -3142,24 +3155,8 @@ void gen_intermediate_code_internal(XtensaCPU *cpu, qemu_log("\n"); } #endif - if (search_pc) { - j = tcg_op_buf_count(); - memset(tcg_ctx.gen_opc_instr_start + lj + 1, 0, - (j - lj) * sizeof(tcg_ctx.gen_opc_instr_start[0])); - } else { - tb->size = dc.pc - pc_start; - tb->icount = insn_count; - } -} - -void gen_intermediate_code(CPUXtensaState *env, TranslationBlock *tb) -{ - gen_intermediate_code_internal(xtensa_env_get_cpu(env), tb, false); -} - -void gen_intermediate_code_pc(CPUXtensaState *env, TranslationBlock *tb) -{ - gen_intermediate_code_internal(xtensa_env_get_cpu(env), tb, true); + tb->size = dc.pc - pc_start; + tb->icount = insn_count; } void xtensa_cpu_dump_state(CPUState *cs, FILE *f, @@ -3213,7 +3210,8 @@ void xtensa_cpu_dump_state(CPUState *cs, FILE *f, } } -void restore_state_to_opc(CPUXtensaState *env, TranslationBlock *tb, int pc_pos) +void restore_state_to_opc(CPUXtensaState *env, TranslationBlock *tb, + target_ulong *data) { - env->pc = tcg_ctx.gen_opc_pc[pc_pos]; + env->pc = data[0]; }