qemu-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [Qemu-devel] [PATCH V5 2/7] nios2: Add architecture emulation suppor


From: Marek Vasut
Subject: Re: [Qemu-devel] [PATCH V5 2/7] nios2: Add architecture emulation support
Date: Sun, 23 Oct 2016 05:01:38 +0200
User-agent: Mozilla/5.0 (X11; Linux x86_64; rv:45.0) Gecko/20100101 Icedove/45.4.0

On 10/20/2016 04:35 PM, Richard Henderson wrote:
> On 10/20/2016 06:44 AM, Marek Vasut wrote:
>> +typedef struct Nios2Instruction {
>> +    void     (*handler)(DisasContext *dc, uint32_t code, TCGMemOp
>> flags);
>> +    uint32_t  flags;
>> +} Nios2Instruction;
> 
> I gave you some bad advice wrt the type of flags beforehand.  I had
> failed to divine that it was also used for EXCP_* and TCG_COND_*.  I
> think you were right the first time with unsigned.
> 
> My bad, sorry.

I undid the change, thanks.

>> +/* Load instructions */
>> +static void gen_ldx(DisasContext *dc, uint32_t code, TCGMemOp flags)
>> +{
>> +    I_TYPE(instr, code);
>> +
>> +    TCGv addr = tcg_temp_new();
>> +    TCGv data = tcg_temp_new();
>> +    tcg_gen_addi_tl(addr, load_gpr(dc, instr.a), instr.imm16s);
>> +    tcg_gen_qemu_ld_tl(data, addr, dc->mem_idx, flags);
>> +
>> +    /*
>> +     * WARNING: Loads into R_ZERO are ignored, but we must generate the
>> +     *          memory access itself to emulate the CPU precisely. Load
>> +     *          from a protected page to R_ZERO will cause SIGSEGV on
>> +     *          the Nios2 CPU.
>> +     */
>> +    if (likely(instr.b != R_ZERO)) {
>> +        tcg_gen_mov_tl(dc->cpu_R[instr.b], data);
>> +    }
> 
> Consider
> 
>   TCGv data;
> 
>   if (unlikely(instr.b == R_ZERO)) {
>     /* The writeback to R_ZERO is ignored, but we must generate the
>      * memory access itself to emulate the CPU precisely.  Load from
>      * a protected page to R_ZERO will cause SIGSEGV on the Nios2 CPU.
>      */
>     data = tcg_temp_new();
>   } else {
>     data = dc->cpu_R[instr.b];
>   }
> 
>   tcg_gen_qemu_ld_tl(data, addr, dc->mem_idx, flags);
> 
>   if (unlikely(instr.b == R_ZERO)) {
>     tcg_temp_free(data);
>   }
> 
> so that you don't require the mov opcode.
> 
> That's really what I do on Alpha with dest_gpr.

OK

>> +#define gen_r_div(fname,
>> insn)                                              \
>> +static void (fname)(DisasContext *dc, uint32_t code, TCGMemOp
>> flags)        \
>> +{                                                                          
>> \
>> +    R_TYPE(instr,
>> (code));                                                  \
>> +    if (likely(instr.c != R_ZERO))
>> {                                        \
>> +        TCGv val =
>> tcg_const_tl(0);                                         \
>> +        tcg_gen_setcond_tl(TCG_COND_EQ, val, load_gpr((dc), instr.b),
>> val); \
>> +        tcg_gen_or_tl(val, val, load_gpr((dc),
>> instr.b));                   \
>> +        tcg_gen_##insn((dc)->cpu_R[instr.c], load_gpr((dc), instr.a),
>> val); \
>> +       
>> tcg_temp_free(val);                                                 \
>> +   
>> }                                                                       \
>> +}
>> +
>> +gen_r_div(divs, div_tl)
> 
> For signed division, you have to protect against 0x80000000 / -1 as
> well, which raises an overflow exception on the x86 host.

You mean similar to what mips does on OPC_DIV vs OPC_DIVU , right ?

>> +    /* Set up instruction counts */
>> +    num_insns = 0;
>> +    max_insns = tb->cflags & CF_COUNT_MASK;
>> +    if (max_insns == 0) {
>> +        max_insns = CF_COUNT_MASK;
>> +    }
>> +    if (max_insns > TCG_MAX_INSNS) {
>> +        max_insns = TCG_MAX_INSNS;
>> +    }
>> +    next_page_start = (tb->pc & TARGET_PAGE_MASK) + TARGET_PAGE_SIZE;
> ...
>> +    } while (!dc->is_jmp &&
>> +             !tcg_op_buf_full() &&
>> +             !cs->singlestep_enabled &&
>> +             !singlestep &&
>> +             dc->pc < next_page_start &&
>> +             num_insns < max_insns);
> 
> Consider
> 
>   if (cs->singlestep_enabled || singlestep) {
>     max_insns = 1;
>   } else {
>     int page_insns = (TARGET_PAGE_SIZE - (tb->pc & TARGET_PAGE_MASK)) / 4;
>     max_insns = tb->cflags & CF_COUNT_MASK;
>     if (max_insns == 0) {
>       max_insns = CF_COUNT_MASK;
>     }
>     if (max_insns > page_insns) {
>       max_insns = page_insns;
>     }
>     if (max_insns > TCG_MAX_INSNS) {
>       max_insns = TCG_MAX_INSNS;
>     }
>   }
> 
> so that we collapse the last 4 loop conditions into: num_insns < max_insns.

OK, fixed.

>> +    /* End off the block */
>> +    gen_tb_end(tb, num_insns);
>> +
>> +    /* Mark instruction starts for the final generated instruction */
>> +    tb->size = dc->pc - tb->pc;
>> +    tb->icount = num_insns;
> 
> No CPU_LOG_TB_IN_ASM disassembly?  I thought patch 1 added a nios2
> disassembler.

Nope, I removed it in V4, maybe i misunderstood the review comment?
"
> +    /* Dump the CPU state to the log */
> +    if (qemu_loglevel_mask(CPU_LOG_TB_IN_ASM)) {
> +        qemu_log("--------------\n");
> +        log_cpu_state(cs, 0);
> +    }

Cpu state is dumped by -d cpu generically.
"
-- 
Best regards,
Marek Vasut



reply via email to

[Prev in Thread] Current Thread [Next in Thread]